From 2eafd894126d2b8646d0c9d6a407e202682bea75 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Fri, 26 Nov 2021 23:21:14 +0100 Subject: [PATCH 001/174] [web] apple config app passwords enhancements + translations Signed-off-by: Kristian Feldsam --- data/web/lang/lang.cs-cz.json | 24 +++++++++++++++------ data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.it-it.json | 2 +- data/web/lang/lang.ro-ro.json | 2 +- data/web/lang/lang.sk-sk.json | 25 +++++++++++++++------- data/web/lang/lang.uk-ua.json | 2 +- data/web/lang/lang.zh-cn.json | 2 +- data/web/lang/lang.zh-tw.json | 2 +- data/web/templates/modals/user.twig | 12 +++++------ data/web/templates/user/tab-user-auth.twig | 6 +++--- data/web/user.php | 6 ++++-- 12 files changed, 53 insertions(+), 34 deletions(-) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 5e119fbd6..b1b03c42d 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -41,6 +41,7 @@ "alias_domain": "Doménový alias", "alias_domain_info": "Platné názvy domén (oddělené čárkami).", "app_name": "Název aplikace", + "app_passwd_protocols": "Povolené protokoly pro hesla aplikací", "app_password": "Přidat heslo aplikace", "automap": "Pokusit se automaticky mapovat složky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti záložního MX", @@ -493,6 +494,7 @@ "optional": "Tento záznam je volitelný." }, "edit": { + "acl": "ACL (Oprávnění)", "active": "Aktivní", "admin": "Upravit administrátora", "advanced_settings": "Pokročilá nastavení", @@ -502,6 +504,7 @@ "allowed_protocols": "Povolené protokoly", "app_name": "Název aplikace", "app_passwd": "Heslo aplikace", + "app_passwd_protocols": "Povolené protokoly pro hesla aplikací", "automap": "Pokusit se automaticky mapovat složky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti záložního MX", "bcc_dest_format": "Cíl kopie musí být jedna platná email adresa. Pokud potřebujete posílat kopie na více adres, vytvořte Alias a použijte jej zde.", @@ -585,6 +588,8 @@ "sieve_desc": "Krátký popis", "sieve_type": "Typ filtru", "skipcrossduplicates": "Přeskočit duplicitní zprávy (\"první přijde, první mele\")", + "sogo_access": "Udělit přímý přihlašovací přístup do služby SOGo", + "sogo_access_info": "Jednotné přihlášení (SSO) z mail UI zůstává funkční. Toto nastavení neovlivňuje přístup ke všem ostatním službám ani neodstraňuje či nemění stávající profil uživatele SOGo.", "sogo_visible": "Alias dostupný v SOGo", "sogo_visible_info": "Tato volba určuje objekty, jež lze zobrazit v SOGo (sdílené nebo nesdílené aliasy, jež ukazuje alespoň na jednu schránku).", "spam_alias": "Vytvořit nebo změnit dočasné aliasy", @@ -1022,13 +1027,16 @@ "alias_valid_until": "Platný do", "aliases_also_send_as": "Smí odesílat také jako uživatel", "aliases_send_as_all": "Nekontrolovat přístup odesílatele pro následující doménu(y) a jejich aliasy domény:", + "allowed_protocols": "Povolené protokoly", "app_hint": "Hesla aplikací jsou alternativní heslo pro přihlášení k IMAP, SMTP, CalDAV, CardDAV a EAS. Uživatelské jméno zůstává stejné.
SOGo však nelze s heslem aplikace použít.", "app_name": "Název aplikace", "app_passwds": "Hesla aplikací", "apple_connection_profile": "Profil připojení Apple", "apple_connection_profile_complete": "Tento profil obsahuje parametry připojení k IMAP, SMTP, CalDAV (kalendáře) a CardDAV (kontakty) pro zařízení Apple.", "apple_connection_profile_mailonly": "Tento profil obsahuje parametry připojení k IMAP a SMTP pro zařízení Apple.", + "apple_connection_profile_with_app_password": "Nové heslo aplikace se vygeneruje a přidá do profilu, takže při nastavování zařízení není třeba zadávat žádné heslo. Soubor nesdílejte, protože poskytuje plný přístup k vaší poštovní schránce.", "change_password": "Změnit heslo", + "change_password_hint_app_passwords": "Váš účet má %d hesel aplikací, která nebudou změněna. Chcete-li je spravovat, přejděte na kartu Hesla aplikací.", "clear_recent_successful_connections": "Vymazat nedávné úspěšné přihlášení", "client_configuration": "Zobrazit průvodce nastavením e-mailových klientů a smartphonů", "create_app_passwd": "Vytvořit heslo aplikace", @@ -1039,6 +1047,7 @@ "delete_ays": "Potvrďte odstranění.", "direct_aliases": "Přímé aliasy", "direct_aliases_desc": "Na přímé aliasy se uplatňuje filtr spamu a nastavení pravidel TLS", + "direct_protocol_access": "Tento uživatel mailové schránky má přímý externí přístup k následujícím protokolům a aplikacím. Toto nastavení je řízeno správcem. Pro udělení přístupu k jednotlivým protokolům a aplikacím lze vytvořit hesla aplikací.
Tlačítko \" Přihlaste se do webmailu\" zajišťuje jednotné přihlášení k SOGo a je vždy k dispozici.", "eas_reset": "Smazat mezipaměť zařízení ActiveSync", "eas_reset_help": "Obnovení mezipaměti zařízení pomůže zpravidla obnovit poškozený profil služby ActiveSync.
Upozornění: Všechna data budou opětovně stažena!", "eas_reset_now": "Smazat", @@ -1132,15 +1141,15 @@ "spamfilter_yellow": "Žlutá: tato zpráva může být spam, bude označena jako spam a přesunuta do složky nevyžádané pošty", "status": "Stav", "sync_jobs": "Synchronizační úlohy", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problém s autentifikací", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Chybné uživatelské jméno nebo heslo", + "syncjob_EXIT_CONNECTION_FAILURE": "Problém se spojením", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nelze se připojit ke vzdálenému serveru", + "syncjob_EXIT_OVERQUOTA": "Cílová schránka je plná", + "syncjob_EXIT_TLS_FAILURE": "Problém se šifrovaným spojením", + "syncjob_EX_OK": "Úspěch", "syncjob_check_log": "Zkontrolujte záznam", "syncjob_last_run_result": "Výsledek posledního spuštění", - "syncjob_EX_OK": "Úspěch", - "syncjob_EXIT_CONNECTION_FAILURE": "Problém se spojením", - "syncjob_EXIT_TLS_FAILURE": "Problém se šifrovaným spojením", - "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problém s autentifikací", - "syncjob_EXIT_OVERQUOTA": "Cílová schránka je plná", - "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nelze se připojit ke vzdálenému serveru", - "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Chybné uživatelské jméno nebo heslo", "tag_handling": "Zacházení s označkovanou poštou", "tag_help_example": "Příklad e-mailové adresy se značkou: me+Facebook@example.org", "tag_help_explain": "V podsložce: v doručené poště bude vytvořena nová podsložka pojmenovaná po značce zprávy (\"INBOX / Facebook\").
\r\nV předmětu: název značky bude přidáván k předmětu mailu, například: \"[Facebook] Moje zprávy\".", @@ -1160,6 +1169,7 @@ "week": "týden", "weekly": "Každý týden", "weeks": "týdny", + "with_app_password": "s heslem aplikace", "year": "rok", "years": "let" }, diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 8ff1cf062..c93da77a6 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -1110,7 +1110,7 @@ "apple_connection_profile_mailonly": "Dieses Verbindungsprofil beinhaltet IMAP- und SMTP-Konfigurationen für ein Apple-Gerät.", "apple_connection_profile_with_app_password": "Es wird ein neues App-Passwort erzeugt und in das Profil eingefügt, damit bei der Einrichtung kein Passwort eingegeben werden muss. Geben Sie das Profil nicht weiter, da es einen vollständigen Zugriff auf Ihr Postfach ermöglicht.", "change_password": "Passwort ändern", - "change_password_hint_app_passwords": "Ihre Mailbox hat {{number_of_app_passwords}} App-Passwörter, die nicht geändert werden. Um diese zu verwalten, gehen Sie bitte zum App-Passwörter-Tab.", + "change_password_hint_app_passwords": "Ihre Mailbox hat %d App-Passwörter, die nicht geändert werden. Um diese zu verwalten, gehen Sie bitte zum App-Passwörter-Tab.", "clear_recent_successful_connections": "Alle erfolgreichen Verbindungen bereinigen", "client_configuration": "Konfigurationsanleitungen für E-Mail-Programme und Smartphones anzeigen", "create_app_passwd": "Erstelle App-Passwort", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index bfac011ec..0037b484c 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -1117,7 +1117,7 @@ "apple_connection_profile_mailonly": "This connection profile includes IMAP and SMTP configuration parameters for an Apple device.", "apple_connection_profile_with_app_password": "A new app password is generated and added to the profile so that no password needs to be entered when setting up your device. Please do not share the file as it grants full access to your mailbox.", "change_password": "Change password", - "change_password_hint_app_passwords": "Your account has {{number_of_app_passwords}} app passwords that will not be changed. To manage these, go to the App passwords tab.", + "change_password_hint_app_passwords": "Your account has %d app passwords that will not be changed. To manage these, go to the App passwords tab.", "clear_recent_successful_connections": "Clear seen successful connections", "client_configuration": "Show configuration guides for email clients and smartphones", "create_app_passwd": "Create app password", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index d8d6978c0..b415982e6 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -1192,7 +1192,7 @@ "weeks": "settimane", "year": "anno", "years": "anni", - "change_password_hint_app_passwords": "Il tuo account ha {{number_of_app_passwords}} password delle app che non verranno modificate. Per gestirle, vai alla scheda App passwords.", + "change_password_hint_app_passwords": "Il tuo account ha %d password delle app che non verranno modificate. Per gestirle, vai alla scheda App passwords.", "syncjob_check_log": "Controlla i log", "syncjob_last_run_result": "Risultato dell'ultima esecuzione", "open_logs": "Apri i log", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index 8e6e1d454..f4b0fdc0a 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -1038,7 +1038,7 @@ "apple_connection_profile_mailonly": "Acest profil de conexiune include parametrii de configurare IMAP și SMTP pentru dispozitivele Apple.", "apple_connection_profile_with_app_password": "O nouă parolă pentru aplicație este generată și adăugată la profil, astfel încât să nu fie necesară introducerea unei parole la configurarea dispozitivului. Vă rugăm să nu partajați fișierul, deoarece oferă acces deplin la căsuța dvs. poștală.", "change_password": "Schimbă parola", - "change_password_hint_app_passwords": "Contul dvs. are {{number_of_app_passwords}} parole de aplicație care nu vor fi modificate. Pentru a le gestiona, accesați secțiunea Parole aplicație.", + "change_password_hint_app_passwords": "Contul dvs. are %d parole de aplicație care nu vor fi modificate. Pentru a le gestiona, accesați secțiunea Parole aplicație.", "clear_recent_successful_connections": "Ștergeți conexiunile reușite văzute", "client_configuration": "Afișează ghidurile de configurare pentru clienții de email și smartphone-uri", "create_app_passwd": "Crează parola aplicației", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 2b93650fc..406b14f70 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -41,6 +41,7 @@ "alias_domain": "Alias doména", "alias_domain_info": "Len platné mená domén (oddelené čiarkou).", "app_name": "Meno aplikácie", + "app_passwd_protocols": "Povolené protokoly pre heslá aplikácií", "app_password": "Pridať heslo aplikácie", "automap": "Skúsiť automaticky mapovať priečinky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti preposielania", @@ -505,6 +506,7 @@ "allowed_protocols": "Povolené protokoly", "app_name": "Meno aplikácie", "app_passwd": "Heslo aplikácie", + "app_passwd_protocols": "Povolené protokoly pre heslá aplikácií", "automap": "Skúsiť automapovať priečinky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti preposielania", "bcc_dest_format": "Cieľ kópie musí byť jedna platná emailová adresa. Pokiaľ potrebujete posielať kópie na viac adries, vytvorte Alias a použite ho tu.", @@ -589,6 +591,8 @@ "sieve_desc": "Krátky popis", "sieve_type": "Typ filtru", "skipcrossduplicates": "Preskočiť duplikované správy naprieč priečinkami (akceptuje sa prvý nález)", + "sogo_access": "Udeliť priamy prístup k prihláseniu do služby SOGo", + "sogo_access_info": "Jednotné prihlásenie (SSO) z mail UI zostáva funkčné. Toto nastavenie nemá vplyv na prístup k všetkým ostatným službám, ani neodstraňuje alebo nemení existujúci profil používateľa SOGo.", "sogo_visible": "Alias je viditeľný v SOGo", "sogo_visible_info": "Táto voľba ovplyvňuje len objekty, ktoré dokážu byť zobrazené v SOGo (zdieľané alebo nezdieľané alias adresy ukazujúc na minimálne jednu lokálnu mailovú schránku). Ak je skrytý, alias nebude prezentovaný ako voliteľný odosielateľ v SOGo.", "spam_alias": "Vytvoriť alebo zmeniť časovo limitované alias adresy", @@ -1031,13 +1035,16 @@ "alias_valid_until": "Platné do", "aliases_also_send_as": "Môže odosielať ako používateľ", "aliases_send_as_all": "Nekontrolovať prístup odosielateľa pre nasledujúcu doménu/y a jej alias domény", + "allowed_protocols": "Povolené protokoly", "app_hint": "Heslá aplikácií sú alternatívne heslá pre vaše IMAP, SMTP, CalDAV, CardDAV a EAS prihlásenie. Používateľské meno zostáva nezmenené.
SOGo nie je momentálne podporovaný.", "app_name": "Meno aplikácie", "app_passwds": "Heslá aplikácií", "apple_connection_profile": "Apple konfiguračný profil", "apple_connection_profile_complete": "Tento profil zahŕňa IMAP a SMTP parametre, ako aj CalDAV (kalendáre) a CardDAV (kontakty) pre zariadenia Apple.", "apple_connection_profile_mailonly": "Tento profil zahŕňa IMAP a SMTP konfiguračné parametre pre zariadenia Apple.", + "apple_connection_profile_with_app_password": "Nové heslo aplikácie sa vygeneruje a pridá do profilu, takže pri nastavovaní zariadenia nie je potrebné zadávať žiadne heslo. Súbor nezdieľajte, pretože poskytuje úplný prístup k vašej poštovej schránke.", "change_password": "Zmeniť heslo", + "change_password_hint_app_passwords": "Váš účet má %d hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", "clear_recent_successful_connections": "Vymazať nedávne úspešné prihlásenia", "client_configuration": "Zobraziť konfiguračné pokyny pre emailových klientov a smartfóny", "create_app_passwd": "Vytvoriť heslo aplikácie", @@ -1048,6 +1055,7 @@ "delete_ays": "Potvrďte zmazanie.", "direct_aliases": "Priame alias adresy", "direct_aliases_desc": "Priame aliasy sú ovplyvnené spam filtrom a nastavením TLS pravidiel.", + "direct_protocol_access": "Tento používateľ mailovej schránky má priamy, externý prístup k nasledujúcim protokolom a aplikáciám. Toto nastavenie má pod kontrolou Váš správca. Na udelenie prístupu k jednotlivým protokolom a aplikáciám je možné vytvoriť heslá aplikácií.
Tlačidlo \" Prihláste sa do webmailu\" poskytuje jednotné prihlásenie do systému SOGo a je vždy k dispozícii.", "eas_reset": "Resetovať medzipamäť u ActiveSync zariadení", "eas_reset_help": "Vo väčšine prípadov, reset medzipamäte ActiveSync pomôže opravit nefunkčný profil.
Pozor: Všetky potrebné dáta budú opäť stiahnuté!", "eas_reset_now": "Reset ActiveSync", @@ -1141,15 +1149,15 @@ "spamfilter_yellow": "Žltá: Táto správa môže byť spam, bude označená ako spam a presunutá do priečinku nevyžiadanej pošty", "status": "Status", "sync_jobs": "Synchronizačné úlohy", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problém s autentifikáciou", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Chybné uživateľské meno alebo heslo", + "syncjob_EXIT_CONNECTION_FAILURE": "Problém so spojením", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nedá sa pripojiť k vzdialenému serveru", + "syncjob_EXIT_OVERQUOTA": "Cieľová schránka je plná", + "syncjob_EXIT_TLS_FAILURE": "Problém so šifrovaným spojením", + "syncjob_EX_OK": "Úspech", "syncjob_check_log": "Skontrolujte záznam", "syncjob_last_run_result": "Výsledok posledného spustenia", - "syncjob_EX_OK": "Úspech", - "syncjob_EXIT_CONNECTION_FAILURE": "Problém so spojením", - "syncjob_EXIT_TLS_FAILURE": "Problém so šifrovaným spojením", - "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problém s autentifikáciou", - "syncjob_EXIT_OVERQUOTA": "Cieľová schránka je plná", - "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nedá sa pripojiť k vzdialenému serveru", - "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Chybné uživateľské meno alebo heslo", "tag_handling": "Zaobchádzanie s označenou poštou", "tag_help_example": "Príklad tagu e-mailovej adresy: me+Facebook@example.org", "tag_help_explain": "V podadresári: nový podadresár s menom tag-u bude vytvorený nižšie INBOX (\"INBOX/Facebook\").
\r\nIn subject: meno štítka bude pridané pred predmet pošty, napríklad: \"[Facebook] My News\".", @@ -1169,10 +1177,11 @@ "week": "týždeň", "weekly": "Týždenne", "weeks": "týždne", + "with_app_password": "s heslom aplikácie", "year": "rok", "years": "rokov", "apple_connection_profile_with_app_password": "Nové heslo aplikácie sa vygeneruje a pridá do profilu, takže pri nastavovaní zariadenia nie je potrebné zadávať žiadne heslo. Súbor nezdieľajte, pretože poskytuje úplný prístup k vašej mail schránke.", - "change_password_hint_app_passwords": "Vaše konto má {{number_of_app_passwords}} hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", + "change_password_hint_app_passwords": "Vaše konto má %d hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", "direct_protocol_access": "Tento používateľ mailovej schránky má priamy, externý prístup k nasledujúcim protokolom a aplikáciám. Toto nastavenie kontroluje administrátor. Na udelenie prístupu k jednotlivým protokolom a aplikáciám je možné vytvoriť heslá aplikácií.
Tlačidlo \"Prihlásenie do webmailu\" poskytuje jednotné prihlásenie do systému SOGo a je vždy k dispozícii." }, "warning": { diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 0a5c71b87..e7a8a415d 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -1037,7 +1037,7 @@ "apple_connection_profile_complete": "Цей профіль включає налаштування IMAP та SMTP, а також CalDAV (календарів) та CardDAV (контактів) для пристрою Apple.", "apple_connection_profile_mailonly": "Цей профіль включає лише налаштування IMAP та SMTP для пристрою Apple.", "change_password": "Змінити пароль", - "change_password_hint_app_passwords": "Ваш обліковий запис містить {{number_of_app_passwords}} паролів додатків, які не змінюватимуться. Щоб керувати ними, перейдіть на вкладку \"Паролі додатків\".", + "change_password_hint_app_passwords": "Ваш обліковий запис містить %d паролів додатків, які не змінюватимуться. Щоб керувати ними, перейдіть на вкладку \"Паролі додатків\".", "clear_recent_successful_connections": "Очистити історію успішних підключень", "create_app_passwd": "Створити новий пароль", "create_syncjob": "Створити нове завдання синхронізації", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index e57ea2a7f..e07129582 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -1042,7 +1042,7 @@ "apple_connection_profile_mailonly": "此连接描述文件包括提供给 Apple 设备的 IMAP 和 SMTP 配置参数。", "apple_connection_profile_with_app_password": "一个新的应用程序密码将会被生成并添加到该配置文件中,因此在设备设置时不需要输入密码。请不要随意分享该文件,因为它包含你的邮箱的完全访问权限。", "change_password": "更改密码", - "change_password_hint_app_passwords": "你的账户有 {{number_of_app_passwords}} 个应用密码,这些密码将不会被更改。如果需要管理这些密码,请访问应用密码标签。", + "change_password_hint_app_passwords": "你的账户有 %d 个应用密码,这些密码将不会被更改。如果需要管理这些密码,请访问应用密码标签。", "clear_recent_successful_connections": "清除成功匹配的连接", "client_configuration": "显示邮箱客户端和智能手机的配置指南", "create_app_passwd": "添加应用密码", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index 916188dbc..eca244828 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -1036,7 +1036,7 @@ "apple_connection_profile_mailonly": "此連接描述檔案包括提供給 Apple 裝置的 IMAP 和 SMTP 組態參數。", "apple_connection_profile_with_app_password": "應用程式密碼已產生並加入到連接描述檔案中,因此裝置在設定時不需要輸入密碼。請勿分享這個檔案,因為它擁有存取信箱的所有權限。", "change_password": "更改密碼", - "change_password_hint_app_passwords": "你的帳號有 {{number_of_app_passwords}} 個應用程式密碼不會被更動。要管理這些密碼,請至應用程式密碼分頁。", + "change_password_hint_app_passwords": "你的帳號有 %d 個應用程式密碼不會被更動。要管理這些密碼,請至應用程式密碼分頁。", "clear_recent_successful_connections": "中斷成功的連線", "client_configuration": "顯示電子信箱程式和智慧型手機的設定指南", "create_app_passwd": "新增應用程式密碼", diff --git a/data/web/templates/modals/user.twig b/data/web/templates/modals/user.twig index 8c96397f6..20846a6f4 100644 --- a/data/web/templates/modals/user.twig +++ b/data/web/templates/modals/user.twig @@ -285,15 +285,13 @@
+ {% if number_of_app_passwords > 0 %} +
+ {{ lang.user.change_password_hint_app_passwords|format(number_of_app_passwords) }} +
+ {% endif %}
- {% if number_of_app_passwords > 0 %} -
-
- {{ lang.user.change_password_hint_app_passwords | replace({'{{number_of_app_passwords}}': number_of_app_passwords}) }} -
-
- {% endif %}
diff --git a/data/web/templates/user/tab-user-auth.twig b/data/web/templates/user/tab-user-auth.twig index 646c79102..a1e2e2c25 100644 --- a/data/web/templates/user/tab-user-auth.twig +++ b/data/web/templates/user/tab-user-auth.twig @@ -129,13 +129,13 @@
-
{{ lang.user.apple_connection_profile }}
{{ lang.user.with_app_password }}:
+
{{ lang.user.apple_connection_profile }}
{{ lang.user.with_app_password }}:

{{ lang.user.email }} IMAP, SMTP

-

{{ lang.user.apple_connection_profile_mailonly }} {{ lang.user.apple_connection_profile_with_app_password }}

+

{{ lang.user.apple_connection_profile_mailonly }}
{{ lang.user.apple_connection_profile_with_app_password }}

{% if not skip_sogo %}

{{ lang.user.email_and_dav }} IMAP, SMTP, Cal/CardDAV

-

{{ lang.user.apple_connection_profile_complete }} {{ lang.user.apple_connection_profile_with_app_password }}

+

{{ lang.user.apple_connection_profile_complete }}
{{ lang.user.apple_connection_profile_with_app_password }}

{% endif %}
diff --git a/data/web/user.php b/data/web/user.php index 5fddff6ec..19aafdddc 100644 --- a/data/web/user.php +++ b/data/web/user.php @@ -62,16 +62,18 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == ' $user_domains = array_merge($user_domains, $user_alias_domains); } - $template = 'user.twig'; + // get number of app passwords $number_of_app_passwords = 0; foreach (app_passwd("get") as $app_password) { $app_password = app_passwd("details", $app_password['id']); if ($app_password['active']) { - ++$number_of_app_passwords; + $number_of_app_passwords++; } } + + $template = 'user.twig'; $template_data = [ 'acl' => $_SESSION['acl'], 'acl_json' => json_encode($_SESSION['acl']), From f295b8cd91f9d691ad93c53191e6319282dcae55 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 8 May 2023 12:55:38 +0200 Subject: [PATCH 002/174] [Rspamd] add domain wide footer --- data/conf/rspamd/lua/rspamd.local.lua | 120 +++++++++++++++++++++++++ data/web/edit.php | 2 + data/web/inc/functions.mailbox.inc.php | 73 +++++++++++++++ data/web/json_api.php | 27 +++--- data/web/lang/lang.de-de.json | 5 ++ data/web/lang/lang.en-gb.json | 5 ++ data/web/templates/edit/domain.twig | 28 ++++++ 7 files changed, 248 insertions(+), 12 deletions(-) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 6318bd23a..3d4716009 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -499,3 +499,123 @@ rspamd_config:register_symbol({ end end }) + +rspamd_config:register_symbol({ + name = 'MOO_FOOTER', + type = 'prefilter', + callback = function(task) + local lua_mime = require "lua_mime" + local rspamd_logger = require "rspamd_logger" + local rspamd_redis = require "rspamd_redis" + local ucl = require "ucl" + local redis_params = rspamd_parse_redis_server('footer') + local envfrom = task:get_from(1) + local uname = task:get_user() + if not envfrom or not uname then + return false + end + local uname = uname:lower() + local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case + + local function newline(task) + local t = task:get_newlines_type() + + if t == 'cr' then + return '\r' + elseif t == 'lf' then + return '\n' + end + + return '\r\n' + end + local function redis_cb_footer(err, data) + if err or type(data) ~= 'string' then + rspamd_logger.infox(rspamd_config, "domain wide footer request for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err) + else + -- parse json string + local parser = ucl.parser() + local res,err = parser:parse_string(data) + if not res then + rspamd_logger.infox(rspamd_config, "parsing domain wide footer for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err) + else + local footer = parser:get_object() + + if footer and type(footer) == "table" and (footer.html or footer.plain) then + rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain) + + -- add footer + local out = {} + local rewrite = lua_mime.add_text_footer(task, footer.html, footer.plain) or {} + + local seen_cte + local newline_s = newline(task) + + local function rewrite_ct_cb(name, hdr) + if rewrite.need_rewrite_ct then + if name:lower() == 'content-type' then + local nct = string.format('%s: %s/%s; charset=utf-8', + 'Content-Type', rewrite.new_ct.type, rewrite.new_ct.subtype) + out[#out + 1] = nct + return + elseif name:lower() == 'content-transfer-encoding' then + out[#out + 1] = string.format('%s: %s', + 'Content-Transfer-Encoding', 'quoted-printable') + seen_cte = true + return + end + end + out[#out + 1] = hdr.raw:gsub('\r?\n?$', '') + end + + task:headers_foreach(rewrite_ct_cb, {full = true}) + + if not seen_cte and rewrite.need_rewrite_ct then + out[#out + 1] = string.format('%s: %s', 'Content-Transfer-Encoding', 'quoted-printable') + end + + -- End of headers + out[#out + 1] = newline_s + + if rewrite.out then + for _,o in ipairs(rewrite.out) do + out[#out + 1] = o + end + else + out[#out + 1] = task:get_rawbody() + end + local out_parts = {} + for _,o in ipairs(out) do + if type(o) ~= 'table' then + out_parts[#out_parts + 1] = o + out_parts[#out_parts + 1] = newline_s + else + out_parts[#out_parts + 1] = o[1] + if o[2] then + out_parts[#out_parts + 1] = newline_s + end + end + end + task:set_message(out_parts) + else + rspamd_logger.infox(rspamd_config, "domain wide footer request for user %s returned invalid or empty data (\"%s\")", uname, data) + end + end + end + end + + local redis_ret_footer = rspamd_redis_make_request(task, + redis_params, -- connect params + env_from_domain, -- hash key + false, -- is write + redis_cb_footer, --callback + 'HGET', -- command + {"DOMAIN_WIDE_FOOTER", env_from_domain} -- arguments + ) + if not redis_ret_footer then + rspamd_logger.infox(rspamd_config, "cannot make request to load footer for domain") + end + + return true + end, + priority = 1 +}) diff --git a/data/web/edit.php b/data/web/edit.php index 09db796d3..7655b3c3a 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -47,6 +47,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { $quota_notification_bcc = quota_notification_bcc('get', $domain); $rl = ratelimit('get', 'domain', $domain); $rlyhosts = relayhost('get'); + $domain_footer = mailbox('get', 'domain_wide_footer', $domain); $template = 'edit/domain.twig'; $template_data = [ 'acl' => $_SESSION['acl'], @@ -56,6 +57,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { 'rlyhosts' => $rlyhosts, 'dkim' => dkim('details', $domain), 'domain_details' => $result, + 'domain_footer' => $domain_footer, ]; } } diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 4e036b99c..dace3e8ac 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -3320,6 +3320,45 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; + case 'domain_wide_footer': + $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46); + if (!is_valid_domain_name($domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'domain_invalid' + ); + return false; + } + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + return false; + } + + $footers = array(); + $footers['html'] = isset($_data['footer_html']) ? $_data['footer_html'] : ''; + $footers['plain'] = isset($_data['footer_plain']) ? $_data['footer_plain'] : ''; + try { + $redis->hSet('DOMAIN_WIDE_FOOTER', $domain, json_encode($footers)); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('redis_error', $e) + ); + return false; + } + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('domain_footer_modified', htmlspecialchars($domain)) + ); + break; } break; case 'get': @@ -4399,6 +4438,40 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } return $resourcedata; break; + case 'domain_wide_footer': + $domain = idn_to_ascii(strtolower(trim($_data)), 0, INTL_IDNA_VARIANT_UTS46); + if (!is_valid_domain_name($domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'domain_invalid' + ); + return false; + } + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + return false; + } + + try { + $footers = $redis->hGet('DOMAIN_WIDE_FOOTER', $domain); + $footers = json_decode($footers, true); + } + catch (RedisException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('redis_error', $e) + ); + return false; + } + + return $footers; + break; } break; case 'delete': diff --git a/data/web/json_api.php b/data/web/json_api.php index ec028fe4b..e21219c59 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -288,18 +288,18 @@ if (isset($_GET['query'])) { case "domain-admin": process_add_return(domain_admin('add', $attr)); break; - case "sso": - switch ($object) { - case "domain-admin": - $data = domain_admin_sso('issue', $attr); - if($data) { - echo json_encode($data); - exit(0); - } - process_add_return($data); - break; - } - break; + case "sso": + switch ($object) { + case "domain-admin": + $data = domain_admin_sso('issue', $attr); + if($data) { + echo json_encode($data); + exit(0); + } + process_add_return($data); + break; + } + break; case "admin": process_add_return(admin('add', $attr)); break; @@ -1867,6 +1867,9 @@ if (isset($_GET['query'])) { case "quota_notification_bcc": process_edit_return(quota_notification_bcc('edit', $attr)); break; + case "domain-wide-footer": + process_edit_return(mailbox('edit', 'domain_wide_footer', $attr)); + break; case "mailq": process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr))); break; diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 6b280bbb8..f1378500d 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -576,6 +576,10 @@ "disable_login": "Login verbieten (Mails werden weiterhin angenommen)", "domain": "Domain bearbeiten", "domain_admin": "Domain-Administrator bearbeiten", + "domain_footer": "Domain wide footer", + "domain_footer_html": "HTML footer", + "domain_footer_info": "Domain wide footer werden allen E-Mails hinzugefügt, die von der angegebenen Domain gesendet werden.", + "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain Speicherplatz gesamt (MiB)", "domains": "Domains", "dont_check_sender_acl": "Absender für Domain %s u. Alias-Domain nicht prüfen", @@ -1011,6 +1015,7 @@ "domain_admin_added": "Domain-Administrator %s wurde angelegt", "domain_admin_modified": "Änderungen an Domain-Administrator %s wurden gespeichert", "domain_admin_removed": "Domain-Administrator %s wurde entfernt", + "domain_footer_modified": "Änderungen an Domain Footer %s wurden gespeichert", "domain_modified": "Änderungen an Domain %s wurden gespeichert", "domain_removed": "Domain %s wurde entfernt", "dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index e53fe896c..30be210cc 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -576,6 +576,10 @@ "disable_login": "Disallow login (incoming mail is still accepted)", "domain": "Edit domain", "domain_admin": "Edit domain administrator", + "domain_footer": "Domain wide footer", + "domain_footer_html": "HTML footer", + "domain_footer_info": "Domain wide footers will be added to all emails sent from the specified domain.", + "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain quota", "domains": "Domains", "dont_check_sender_acl": "Disable sender check for domain %s (+ alias domains)", @@ -1018,6 +1022,7 @@ "domain_admin_added": "Domain administrator %s has been added", "domain_admin_modified": "Changes to domain administrator %s have been saved", "domain_admin_removed": "Domain administrator %s has been removed", + "domain_footer_modified": "Changes to domain footer %s have been saved", "domain_modified": "Changes to domain %s have been saved", "domain_removed": "Domain %s has been removed", "dovecot_restart_success": "Dovecot was restarted successfully", diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 0c424887d..16c1a9661 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -7,6 +7,7 @@ +
@@ -229,6 +230,33 @@
+
+
+
+

{{ lang.edit.domain_footer }}

+

{{ lang.edit.domain_footer_info|raw }}

+
+
+ +
+ +
+
+
+ +
+ +
+
+
+
+ +
+
+
+
+
+
{% else %} {{ parent() }} From 1de47072f8c4885eaa0d9f72e833fd7299cd4da8 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 12:26:57 +0200 Subject: [PATCH 003/174] Added DQS Values to update.sh/generate + check of variable --- generate_config.sh | 27 ++++++++++++++++++++++++++- update.sh | 36 ++++++++++++++++++++++++++++++++---- 2 files changed, 58 insertions(+), 5 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index 0232d3a18..8117c7630 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -21,7 +21,7 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox grep if cp --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""; exit 1; fi if sed --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox sed detected, please install gnu sed, \"apk add --no-cache --upgrade sed\""; exit 1; fi -for bin in openssl curl docker git awk sha1sum; do +for bin in openssl curl docker git awk sha1sum grep cut whois; do if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi done @@ -58,6 +58,23 @@ else exit 1 fi +detect_bad_asn() { + if [[ curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) ]]; then + if ! $SPAMHAUS_DQS_KEY; then + echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." + echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" + echo "" + echo -e "\e[31mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account" + echo -e "\e[31mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!" + sleep 2 + + else + echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." + echo -e "\e[33mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key..." + fi + fi +} + ### If generate_config.sh is started with --dev or -d it will not check out nightly or master branch and will keep on the current branch if [[ ${1} == "--dev" || ${1} == "-d" ]]; then SKIP_BRANCH=y @@ -431,6 +448,12 @@ ACME_CONTACT= # root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates WEBAUTHN_ONLY_TRUSTED_VENDORS=n +# Spamhaus Data Query Service Key +# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist. +# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS. +# Otherwise it will work normally. +SPAMHAUS_DQS_KEY= + EOF mkdir -p data/assets/ssl @@ -503,3 +526,5 @@ else echo '?>' >> data/web/inc/app_info.inc.php echo -e "\e[33mCannot determine current git repository version...\e[0m" fi + +detect_bad_asn \ No newline at end of file diff --git a/update.sh b/update.sh index e68fe2933..d5fb68b7b 100755 --- a/update.sh +++ b/update.sh @@ -255,6 +255,23 @@ elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then fi } +detect_bad_asn() { + if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1); then + if [ -z "$SPAMHAUS_DQS_KEY" ]; then + echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." + echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" + echo "" + echo -e "\e[31mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account" + echo -e "\e[31mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!" + sleep 2 + + else + echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." + echo -e "\e[33mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key..." + fi + fi +} + ############## End Function Section ############## # Check permissions @@ -301,7 +318,7 @@ umask 0022 unset COMPOSE_COMMAND unset DOCKER_COMPOSE_VERSION -for bin in curl docker git awk sha1sum; do +for bin in curl docker git awk sha1sum grep cut whois; do if [[ -z $(command -v ${bin}) ]]; then echo "Cannot find ${bin}, exiting..." exit 1; @@ -442,8 +459,11 @@ CONFIG_ARRAY=( "ACME_CONTACT" "WATCHDOG_VERBOSE" "WEBAUTHN_ONLY_TRUSTED_VENDORS" + "SPAMHAUS_DQS_KEY" ) +detect_bad_asn + sed -i --follow-symlinks '$a\' mailcow.conf for option in ${CONFIG_ARRAY[@]}; do if [[ ${option} == "ADDITIONAL_SAN" ]]; then @@ -659,7 +679,7 @@ for option in ${CONFIG_ARRAY[@]}; do echo '# Setting it at a later point will require the following steps:' >> mailcow.conf echo '# https://docs.mailcow.email/troubleshooting/debug-reset_tls/' >> mailcow.conf echo 'ACME_CONTACT=' >> mailcow.conf - fi + fi elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then if ! grep -q ${option} mailcow.conf; then echo "# WebAuthn device manufacturer verification" >> mailcow.conf @@ -667,11 +687,19 @@ for option in ${CONFIG_ARRAY[@]}; do echo '# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates' >> mailcow.conf echo 'WEBAUTHN_ONLY_TRUSTED_VENDORS=n' >> mailcow.conf fi -elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then + elif [[ ${option} == "SPAMHAUS_DQS_KEY" ]]; then + if ! grep -q ${option} mailcow.conf; then + echo "# Spamhaus Data Query Service Key" >> mailcow.conf + echo '# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.' >> mailcow.conf + echo '# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.' >> mailcow.conf + echo '# Otherwise it will work as usual.' >> mailcow.conf + echo 'SPAMHAUS_DQS_KEY=' >> mailcow.conf + fi + elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then if ! grep -q ${option} mailcow.conf; then echo '# Enable watchdog verbose logging' >> mailcow.conf echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf - fi + fi elif ! grep -q ${option} mailcow.conf; then echo "Adding new option \"${option}\" to mailcow.conf" echo "${option}=n" >> mailcow.conf From bf6a61fa2d05fa2229a8ff5856d55c4c5a025b9c Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 14:20:06 +0200 Subject: [PATCH 004/174] Small corrections to update/generate.sh --- generate_config.sh | 1 + update.sh | 6 ++++++ 2 files changed, 7 insertions(+) diff --git a/generate_config.sh b/generate_config.sh index 8117c7630..ce550e46f 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -449,6 +449,7 @@ ACME_CONTACT= WEBAUTHN_ONLY_TRUSTED_VENDORS=n # Spamhaus Data Query Service Key +# Optional: Leave empty for none # Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist. # If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS. # Otherwise it will work normally. diff --git a/update.sh b/update.sh index d5fb68b7b..be96f4f80 100755 --- a/update.sh +++ b/update.sh @@ -662,6 +662,7 @@ for option in ${CONFIG_ARRAY[@]}; do fi elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" echo '# Additional server names for mailcow UI' >> mailcow.conf echo '#' >> mailcow.conf echo '# Specify alternative addresses for the mailcow UI to respond to' >> mailcow.conf @@ -673,6 +674,7 @@ for option in ${CONFIG_ARRAY[@]}; do fi elif [[ ${option} == "ACME_CONTACT" ]]; then if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" echo '# Lets Encrypt registration contact information' >> mailcow.conf echo '# Optional: Leave empty for none' >> mailcow.conf echo '# This value is only used on first order!' >> mailcow.conf @@ -682,6 +684,7 @@ for option in ${CONFIG_ARRAY[@]}; do fi elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" echo "# WebAuthn device manufacturer verification" >> mailcow.conf echo '# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed' >> mailcow.conf echo '# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates' >> mailcow.conf @@ -689,7 +692,9 @@ for option in ${CONFIG_ARRAY[@]}; do fi elif [[ ${option} == "SPAMHAUS_DQS_KEY" ]]; then if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" echo "# Spamhaus Data Query Service Key" >> mailcow.conf + echo '# Optional: Leave empty for none' >> mailcow.conf echo '# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.' >> mailcow.conf echo '# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.' >> mailcow.conf echo '# Otherwise it will work as usual.' >> mailcow.conf @@ -697,6 +702,7 @@ for option in ${CONFIG_ARRAY[@]}; do fi elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then if ! grep -q ${option} mailcow.conf; then + echo "Adding new option \"${option}\" to mailcow.conf" echo '# Enable watchdog verbose logging' >> mailcow.conf echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf fi From 03b7a8d639adad2d380b235955c93c7e508d5e2e Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 14:25:07 +0200 Subject: [PATCH 005/174] Implemented Postfix Blocklist generation --- .gitignore | 1 + data/Dockerfiles/postfix/postfix.sh | 66 +++++++++++++++++++++++++++++ 2 files changed, 67 insertions(+) diff --git a/.gitignore b/.gitignore index 5782cad95..0169c439a 100644 --- a/.gitignore +++ b/.gitignore @@ -36,6 +36,7 @@ data/conf/postfix/extra.cf data/conf/postfix/sni.map data/conf/postfix/sni.map.db data/conf/postfix/sql +data/conf/postfix/dns_blocklists.cf data/conf/rspamd/custom/* data/conf/rspamd/local.d/* data/conf/rspamd/override.d/* diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 78b070e0e..56f37a035 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -393,6 +393,72 @@ query = SELECT goto FROM spamalias AND validity >= UNIX_TIMESTAMP() EOF +if [ -n "$SPAMHAUS_DQS_KEY" ]; then + cat < /opt/postfix/conf/dns_blocklists.cf + # Autogenerated by mailcow + postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6 + ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 + ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 +EOF + +else + cat < /opt/postfix/conf/dns_blocklists.cf + # Autogenerated by mailcow + postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 + zen.spamhaus.org=127.0.0.[10;11]*8 + zen.spamhaus.org=127.0.0.[4..7]*6 + zen.spamhaus.org=127.0.0.3*4 + zen.spamhaus.org=127.0.0.2*3 +EOF +fi + sed -i '/User overrides/q' /opt/postfix/conf/main.cf echo >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf From 380cdab6fc08b44622ef2180d3905b1b6f7de915 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 14:26:17 +0200 Subject: [PATCH 006/174] Removed dnsbl from main.cf --- data/conf/postfix/main.cf | 28 ---------------------------- 1 file changed, 28 deletions(-) diff --git a/data/conf/postfix/main.cf b/data/conf/postfix/main.cf index a445b60ce..a5751c65c 100644 --- a/data/conf/postfix/main.cf +++ b/data/conf/postfix/main.cf @@ -40,34 +40,6 @@ postscreen_blacklist_action = drop postscreen_cache_cleanup_interval = 24h postscreen_cache_map = proxy:btree:$data_directory/postscreen_cache postscreen_dnsbl_action = enforce -postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 - zen.spamhaus.org=127.0.0.[10;11]*8 - zen.spamhaus.org=127.0.0.[4..7]*6 - zen.spamhaus.org=127.0.0.3*4 - zen.spamhaus.org=127.0.0.2*3 postscreen_dnsbl_threshold = 6 postscreen_dnsbl_ttl = 5m postscreen_greet_action = enforce From 408381bddb1fd1b2422aa89398ed5cea04981100 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 15:48:13 +0200 Subject: [PATCH 007/174] Update Postfix image to 1.69 + improvements --- data/Dockerfiles/postfix/Dockerfile | 1 + data/Dockerfiles/postfix/postfix.sh | 36 +++++++++++++++++++++++++++++ docker-compose.yml | 3 ++- update.sh | 16 +++++++------ 4 files changed, 48 insertions(+), 8 deletions(-) diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index 07ab8949c..4a894fd4f 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -33,6 +33,7 @@ RUN groupadd -g 102 postfix \ syslog-ng-core \ syslog-ng-mod-redis \ tzdata \ + whois \ && rm -rf /var/lib/apt/lists/* \ && touch /etc/default/locale \ && printf '#!/bin/bash\n/usr/sbin/postconf -c /opt/postfix/conf "$@"' > /usr/local/sbin/postconf \ diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 56f37a035..b1c575c30 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -394,6 +394,8 @@ query = SELECT goto FROM spamalias EOF if [ -n "$SPAMHAUS_DQS_KEY" ]; then + echo "Detected SPAMHAUS_DQS_KEY variable from mailcow.conf..." + echo "Using DQS Blocklists from Spamhaus!" cat < /opt/postfix/conf/dns_blocklists.cf # Autogenerated by mailcow postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 @@ -426,6 +428,39 @@ if [ -n "$SPAMHAUS_DQS_KEY" ]; then EOF else + if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then + echo "The AS of your IP is listed as a banned AS from Spamhaus!" + echo "No SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!" + cat < /opt/postfix/conf/dns_blocklists.cf + # Autogenerated by mailcow + postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 +EOF + else + echo "The AS of your IP is NOT listed as a banned AS from Spamhaus!" + echo "Using the open Spamhaus blocklists." cat < /opt/postfix/conf/dns_blocklists.cf # Autogenerated by mailcow postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 @@ -457,6 +492,7 @@ else zen.spamhaus.org=127.0.0.3*4 zen.spamhaus.org=127.0.0.2*3 EOF + fi fi sed -i '/User overrides/q' /opt/postfix/conf/main.cf diff --git a/docker-compose.yml b/docker-compose.yml index a5a8f95b0..4ed115339 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -296,7 +296,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.68 + image: mailcow/postfix:1.69 depends_on: - mysql-mailcow volumes: @@ -316,6 +316,7 @@ services: - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-} - REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} + - SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-} cap_add: - NET_BIND_SERVICE ports: diff --git a/update.sh b/update.sh index be96f4f80..23c25becd 100755 --- a/update.sh +++ b/update.sh @@ -256,18 +256,20 @@ fi } detect_bad_asn() { - if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1); then + if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null ; then if [ -z "$SPAMHAUS_DQS_KEY" ]; then - echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." - echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" + echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" + echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m" + sleep 2 + echo "" + echo -e "\e[33mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account\e[0m" + echo -e "\e[33mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!\e[0m" echo "" - echo -e "\e[31mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account" - echo -e "\e[31mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!" sleep 2 else - echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." - echo -e "\e[33mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key..." + echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" + echo -e "\e[32mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key...\e[0m" fi fi } From 7b645303d6c3b2f30ed6d41cbceb83cceeed152e Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 15:54:49 +0200 Subject: [PATCH 008/174] Added Colorful Outputs for the Spamhaus info in PF --- data/Dockerfiles/postfix/postfix.sh | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index b1c575c30..10f047359 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -394,8 +394,8 @@ query = SELECT goto FROM spamalias EOF if [ -n "$SPAMHAUS_DQS_KEY" ]; then - echo "Detected SPAMHAUS_DQS_KEY variable from mailcow.conf..." - echo "Using DQS Blocklists from Spamhaus!" + echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m" + echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m" cat < /opt/postfix/conf/dns_blocklists.cf # Autogenerated by mailcow postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 @@ -429,8 +429,8 @@ EOF else if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then - echo "The AS of your IP is listed as a banned AS from Spamhaus!" - echo "No SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!" + echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m" + echo -e "\e[33mNo SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!\e[0m" cat < /opt/postfix/conf/dns_blocklists.cf # Autogenerated by mailcow postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 @@ -459,8 +459,8 @@ else dnsbl.sorbs.net=127.0.0.9*2 EOF else - echo "The AS of your IP is NOT listed as a banned AS from Spamhaus!" - echo "Using the open Spamhaus blocklists." + echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m" + echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m" cat < /opt/postfix/conf/dns_blocklists.cf # Autogenerated by mailcow postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 From 689856b186f9d26cc0e0275ad2f1069966632538 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 16:13:25 +0200 Subject: [PATCH 009/174] New Symbols defined for Security ClamAV DBs --- data/conf/rspamd/local.d/composites.conf | 30 ++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/data/conf/rspamd/local.d/composites.conf b/data/conf/rspamd/local.d/composites.conf index 02ff955b4..b342bca61 100644 --- a/data/conf/rspamd/local.d/composites.conf +++ b/data/conf/rspamd/local.d/composites.conf @@ -68,3 +68,33 @@ WL_FWD_HOST { ENCRYPTED_CHAT { expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP"; } + +CLAMD_SPAM_FOUND { + expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE"; + description = "Probably Spam, Securite Spam Flag set through ClamAV"; + weight = 4.5; +} + +CLAMD_BAD_PDF { + expression = "CLAM_SECI_PDF & !MAILCOW_WHITE"; + description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV"; + score = 6; +} + +CLAMD_BAD_JPG { + expression = "CLAM_SECI_JPG & !MAILCOW_WHITE"; + description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV"; + score = 3; +} + +CLAMD_BAD_HTML { + expression = "CLAM_SECI_HTML & !MAILCOW_WHITE"; + description = "Bad HTML Found, Securite bad HTML Flag set through ClamAV"; + score = 8; +} + +CLAMD_BAD_JS { + expression = "CLAM_SECI_JS & !MAILCOW_WHITE"; + description = "Bad JS Found, Securite bad JS Flag set through ClamAV"; + score = 8; +} \ No newline at end of file From 8cd4ae1e349f926b0a738e2165e54ead5c5b129a Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 23 Jun 2023 16:19:37 +0200 Subject: [PATCH 010/174] Improved Scores --- data/conf/rspamd/local.d/composites.conf | 24 +++++++++++++++--------- 1 file changed, 15 insertions(+), 9 deletions(-) diff --git a/data/conf/rspamd/local.d/composites.conf b/data/conf/rspamd/local.d/composites.conf index b342bca61..cc458ea06 100644 --- a/data/conf/rspamd/local.d/composites.conf +++ b/data/conf/rspamd/local.d/composites.conf @@ -78,23 +78,29 @@ CLAMD_SPAM_FOUND { CLAMD_BAD_PDF { expression = "CLAM_SECI_PDF & !MAILCOW_WHITE"; description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV"; - score = 6; + score = 8; } CLAMD_BAD_JPG { expression = "CLAM_SECI_JPG & !MAILCOW_WHITE"; description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV"; - score = 3; -} - -CLAMD_BAD_HTML { - expression = "CLAM_SECI_HTML & !MAILCOW_WHITE"; - description = "Bad HTML Found, Securite bad HTML Flag set through ClamAV"; score = 8; } -CLAMD_BAD_JS { +CLAMD_ASCII_MALWARE { + expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE"; + description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV"; + score = 8; +} + +CLAMD_HTML_MALWARE { + expression = "CLAM_SECI_HTML & !MAILCOW_WHITE"; + description = "HTML malware found, Securite HTML malware Flag set through ClamAV"; + score = 8; +} + +CLAMD_JS_MALWARE { expression = "CLAM_SECI_JS & !MAILCOW_WHITE"; - description = "Bad JS Found, Securite bad JS Flag set through ClamAV"; + description = "JS malware found, Securite JS malware Flag set through ClamAV"; score = 8; } \ No newline at end of file From 6e9c024b3c30f58d8e080490688baec6a84c3deb Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 27 Jun 2023 10:28:52 +0200 Subject: [PATCH 011/174] Changed weight to score for CLAMD_SPAM --- data/conf/rspamd/local.d/composites.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/rspamd/local.d/composites.conf b/data/conf/rspamd/local.d/composites.conf index cc458ea06..cde34b574 100644 --- a/data/conf/rspamd/local.d/composites.conf +++ b/data/conf/rspamd/local.d/composites.conf @@ -72,7 +72,7 @@ ENCRYPTED_CHAT { CLAMD_SPAM_FOUND { expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE"; description = "Probably Spam, Securite Spam Flag set through ClamAV"; - weight = 4.5; + score = 5; } CLAMD_BAD_PDF { From 5619175108c89df9f488067f60fafe9a80ac9081 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 27 Jun 2023 10:36:53 +0200 Subject: [PATCH 012/174] Upate SOGo to 5.8.4 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index a5a8f95b0..2dd1304cc 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -169,7 +169,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.117 + image: mailcow/sogo:1.118 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From b903cf38881364fffacf445dad32a51b343ac458 Mon Sep 17 00:00:00 2001 From: SnailShea Date: Tue, 11 Jul 2023 19:00:05 -0400 Subject: [PATCH 013/174] Fixes several instances of missing , extra role='tabpanel' and misspelled 'collapse' --- data/web/templates/admin/tab-config-admins.twig | 4 ++-- data/web/templates/admin/tab-config-customize.twig | 4 ++-- data/web/templates/admin/tab-config-dkim.twig | 4 ++-- data/web/templates/admin/tab-config-f2b.twig | 4 ++-- data/web/templates/admin/tab-config-fwdhosts.twig | 4 ++-- data/web/templates/admin/tab-config-oauth2.twig | 4 ++-- data/web/templates/admin/tab-config-password-policy.twig | 4 ++-- data/web/templates/admin/tab-config-quarantine.twig | 4 ++-- data/web/templates/admin/tab-config-quota.twig | 4 ++-- data/web/templates/admin/tab-config-rsettings.twig | 4 ++-- data/web/templates/admin/tab-config-rspamd.twig | 4 ++-- data/web/templates/admin/tab-globalfilter-regex.twig | 4 ++-- data/web/templates/admin/tab-ldap.twig | 4 ++-- data/web/templates/admin/tab-routing.twig | 6 +++--- data/web/templates/admin/tab-sys-mails.twig | 4 ++-- data/web/templates/mailbox/tab-bcc.twig | 2 +- data/web/templates/mailbox/tab-domain-aliases.twig | 2 +- data/web/templates/mailbox/tab-domains.twig | 2 +- data/web/templates/mailbox/tab-filters.twig | 2 +- data/web/templates/mailbox/tab-mailboxes.twig | 2 +- data/web/templates/mailbox/tab-mbox-aliases.twig | 2 +- data/web/templates/mailbox/tab-resources.twig | 2 +- data/web/templates/mailbox/tab-syncjobs.twig | 2 +- data/web/templates/mailbox/tab-templates-domains.twig | 2 +- data/web/templates/mailbox/tab-templates-mbox.twig | 2 +- data/web/templates/mailbox/tab-tls-policy.twig | 2 +- data/web/templates/user/AppPasswds.twig | 4 ++-- data/web/templates/user/Pushover.twig | 4 ++-- data/web/templates/user/SpamAliases.twig | 4 ++-- data/web/templates/user/Spamfilter.twig | 4 ++-- data/web/templates/user/Syncjobs.twig | 4 ++-- data/web/templates/user/tab-user-auth.twig | 4 ++-- data/web/templates/user/tab-user-details.twig | 4 ++-- data/web/templates/user/tab-user-settings.twig | 4 ++-- 34 files changed, 58 insertions(+), 58 deletions(-) diff --git a/data/web/templates/admin/tab-config-admins.twig b/data/web/templates/admin/tab-config-admins.twig index 0221a8e71..7325bbe4f 100644 --- a/data/web/templates/admin/tab-config-admins.twig +++ b/data/web/templates/admin/tab-config-admins.twig @@ -1,4 +1,4 @@ -
+
{{ lang.admin.domain_admins }} diff --git a/data/web/templates/admin/tab-config-customize.twig b/data/web/templates/admin/tab-config-customize.twig index 766c0b6a9..e458eeb3b 100644 --- a/data/web/templates/admin/tab-config-customize.twig +++ b/data/web/templates/admin/tab-config-customize.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.customize }} diff --git a/data/web/templates/admin/tab-config-dkim.twig b/data/web/templates/admin/tab-config-dkim.twig index 8dbccf799..96dccc66c 100644 --- a/data/web/templates/admin/tab-config-dkim.twig +++ b/data/web/templates/admin/tab-config-dkim.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.dkim_keys }} diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index c15fb72f7..2eb5ff276 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.f2b_parameters }} diff --git a/data/web/templates/admin/tab-config-fwdhosts.twig b/data/web/templates/admin/tab-config-fwdhosts.twig index 0f77048fe..31de20364 100644 --- a/data/web/templates/admin/tab-config-fwdhosts.twig +++ b/data/web/templates/admin/tab-config-fwdhosts.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.forwarding_hosts }} diff --git a/data/web/templates/admin/tab-config-oauth2.twig b/data/web/templates/admin/tab-config-oauth2.twig index 07f9e7723..4fa4cf523 100644 --- a/data/web/templates/admin/tab-config-oauth2.twig +++ b/data/web/templates/admin/tab-config-oauth2.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.oauth2_apps }} diff --git a/data/web/templates/admin/tab-config-password-policy.twig b/data/web/templates/admin/tab-config-password-policy.twig index fb6ec7fbc..dd77f3a3e 100644 --- a/data/web/templates/admin/tab-config-password-policy.twig +++ b/data/web/templates/admin/tab-config-password-policy.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.password_policy }} diff --git a/data/web/templates/admin/tab-config-quarantine.twig b/data/web/templates/admin/tab-config-quarantine.twig index 91d9d5396..be2d59a51 100644 --- a/data/web/templates/admin/tab-config-quarantine.twig +++ b/data/web/templates/admin/tab-config-quarantine.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.quarantine }} diff --git a/data/web/templates/admin/tab-config-quota.twig b/data/web/templates/admin/tab-config-quota.twig index c8f2e9292..03f3f3831 100644 --- a/data/web/templates/admin/tab-config-quota.twig +++ b/data/web/templates/admin/tab-config-quota.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.quota_notifications }} diff --git a/data/web/templates/admin/tab-config-rsettings.twig b/data/web/templates/admin/tab-config-rsettings.twig index 8cd690e92..bf5296329 100644 --- a/data/web/templates/admin/tab-config-rsettings.twig +++ b/data/web/templates/admin/tab-config-rsettings.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.rspamd_settings_map }} diff --git a/data/web/templates/admin/tab-config-rspamd.twig b/data/web/templates/admin/tab-config-rspamd.twig index 5cbdc5917..928eb1704 100644 --- a/data/web/templates/admin/tab-config-rspamd.twig +++ b/data/web/templates/admin/tab-config-rspamd.twig @@ -1,7 +1,7 @@ -
+
- Rspamd UI diff --git a/data/web/templates/admin/tab-globalfilter-regex.twig b/data/web/templates/admin/tab-globalfilter-regex.twig index e59705701..086ce533f 100644 --- a/data/web/templates/admin/tab-globalfilter-regex.twig +++ b/data/web/templates/admin/tab-globalfilter-regex.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.rspamd_global_filters }} diff --git a/data/web/templates/admin/tab-ldap.twig b/data/web/templates/admin/tab-ldap.twig index b69817c16..89542d1af 100644 --- a/data/web/templates/admin/tab-ldap.twig +++ b/data/web/templates/admin/tab-ldap.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.admins_ldap }} diff --git a/data/web/templates/admin/tab-routing.twig b/data/web/templates/admin/tab-routing.twig index 9b5842891..5eca7eb10 100644 --- a/data/web/templates/admin/tab-routing.twig +++ b/data/web/templates/admin/tab-routing.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.relayhosts }} @@ -47,7 +47,7 @@
- {{ lang.admin.transport_maps }} diff --git a/data/web/templates/admin/tab-sys-mails.twig b/data/web/templates/admin/tab-sys-mails.twig index 056d193b9..1b842ff88 100644 --- a/data/web/templates/admin/tab-sys-mails.twig +++ b/data/web/templates/admin/tab-sys-mails.twig @@ -1,7 +1,7 @@ -
+
- {{ lang.admin.sys_mails }} diff --git a/data/web/templates/mailbox/tab-bcc.twig b/data/web/templates/mailbox/tab-bcc.twig index 76845c3d6..25844e48e 100644 --- a/data/web/templates/mailbox/tab-bcc.twig +++ b/data/web/templates/mailbox/tab-bcc.twig @@ -1,4 +1,4 @@ -
+
- {{ lang.user.app_passwds }} + {{ lang.user.app_passwds }}
diff --git a/data/web/templates/user/Pushover.twig b/data/web/templates/user/Pushover.twig index d3304dbe2..61c91ea6a 100644 --- a/data/web/templates/user/Pushover.twig +++ b/data/web/templates/user/Pushover.twig @@ -1,10 +1,10 @@ -
+
- Pushover API + Pushover API
diff --git a/data/web/templates/user/SpamAliases.twig b/data/web/templates/user/SpamAliases.twig index 54c76863c..40b3ec77d 100644 --- a/data/web/templates/user/SpamAliases.twig +++ b/data/web/templates/user/SpamAliases.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.spam_aliases }} + {{ lang.user.spam_aliases }}
diff --git a/data/web/templates/user/Spamfilter.twig b/data/web/templates/user/Spamfilter.twig index 7a3baf322..144ead61c 100644 --- a/data/web/templates/user/Spamfilter.twig +++ b/data/web/templates/user/Spamfilter.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.spamfilter }} + {{ lang.user.spamfilter }}

{{ lang.user.spamfilter_behavior }}

diff --git a/data/web/templates/user/Syncjobs.twig b/data/web/templates/user/Syncjobs.twig index 322e85362..1267b4f4d 100644 --- a/data/web/templates/user/Syncjobs.twig +++ b/data/web/templates/user/Syncjobs.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.sync_jobs }} + {{ lang.user.sync_jobs }}
diff --git a/data/web/templates/user/tab-user-auth.twig b/data/web/templates/user/tab-user-auth.twig index 646c79102..735b04cdd 100644 --- a/data/web/templates/user/tab-user-auth.twig +++ b/data/web/templates/user/tab-user-auth.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.mailbox_general }} + {{ lang.user.mailbox_general }}
{% if mailboxdata.attributes.force_pw_update == '1' %} diff --git a/data/web/templates/user/tab-user-details.twig b/data/web/templates/user/tab-user-details.twig index 573cd498c..00fd72114 100644 --- a/data/web/templates/user/tab-user-details.twig +++ b/data/web/templates/user/tab-user-details.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.mailbox_details }} + {{ lang.user.mailbox_details }}
diff --git a/data/web/templates/user/tab-user-settings.twig b/data/web/templates/user/tab-user-settings.twig index 1dcfed988..3a2ee5ff7 100644 --- a/data/web/templates/user/tab-user-settings.twig +++ b/data/web/templates/user/tab-user-settings.twig @@ -1,10 +1,10 @@ -
+
- {{ lang.user.mailbox_settings }} + {{ lang.user.mailbox_settings }}
{# Show tagging options #} From ec8d298c362c13ad575e1e48d287cce17927f4d0 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 13 Jul 2023 16:42:59 +0200 Subject: [PATCH 014/174] Update postfix.sh to include pbl for dqs --- data/Dockerfiles/postfix/postfix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 10f047359..d0ba8aac0 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -423,6 +423,9 @@ if [ -n "$SPAMHAUS_DQS_KEY" ]; then dnsbl.sorbs.net=127.0.0.6*2 dnsbl.sorbs.net=127.0.0.9*2 ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.[10;11]*8 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.3*4 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.2*3 ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 EOF From 521120a448899b5fd7bdfeef65a8fa0b01c96622 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 24 Jul 2023 10:43:00 +0200 Subject: [PATCH 015/174] Update dependency nextcloud/server to v27.0.1 (#5324) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 71cd17098..1b08a554b 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.0.0 +NEXTCLOUD_VERSION=27.0.1 echo -ne "Checking prerequisites..." sleep 1 From d8fd023cdbe35c72e5201aeb5d3e0d2acb312e13 Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 24 Jul 2023 17:39:41 +0200 Subject: [PATCH 016/174] Update rebuild_backup_image.yml --- .github/workflows/rebuild_backup_image.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index 21c218a8f..226dbdfc2 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -29,6 +29,7 @@ jobs: uses: docker/build-push-action@v4 with: context: . + platforms: linux/amd64,linux/arm64 file: data/Dockerfiles/backup/Dockerfile push: true tags: mailcow/backup:latest From 03831149f824f0a31eb9a325b7936abdb972c18c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 11:28:49 +0200 Subject: [PATCH 017/174] [Web] fix visual bug #5322 --- data/web/templates/user/tab-user-details.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/templates/user/tab-user-details.twig b/data/web/templates/user/tab-user-details.twig index 00fd72114..cc7d44790 100644 --- a/data/web/templates/user/tab-user-details.twig +++ b/data/web/templates/user/tab-user-details.twig @@ -46,7 +46,7 @@

{% if user_get_alias_details.aliases_also_send_as == '*' %} - {{ lang.user.sender_acl_disabled }} + {{ lang.user.sender_acl_disabled | raw }} {% elseif user_get_alias_details.aliases_also_send_as %} {{ user_get_alias_details.aliases_also_send_as }} {% else %} From cd635ec81362c63e6df263fe63e74cd16fe1250a Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 11:30:47 +0200 Subject: [PATCH 018/174] [Dockerapi] Update to 2.05 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 4c854aeb9..1537da7dd 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -511,7 +511,7 @@ services: - watchdog dockerapi-mailcow: - image: mailcow/dockerapi:2.04 + image: mailcow/dockerapi:2.05 security_opt: - label=disable restart: always From 9c44b5e546d4c0e4c76a148575aa3104684be3ca Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 12:10:01 +0200 Subject: [PATCH 019/174] [Web] display is_catch_all and aliases_send_as_all if not empty #5320 --- data/web/templates/user/tab-user-details.twig | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/templates/user/tab-user-details.twig b/data/web/templates/user/tab-user-details.twig index cc7d44790..62842fc9b 100644 --- a/data/web/templates/user/tab-user-details.twig +++ b/data/web/templates/user/tab-user-details.twig @@ -58,13 +58,13 @@

{{ lang.user.aliases_send_as_all }}:
-

{% if not user_get_alias_details.aliases_send_as_all %}{% endif %}

+

{% if not user_get_alias_details.aliases_send_as_all %}{% else %}{{ user_get_alias_details.aliases_send_as_all }}{% endif %}

{{ lang.user.is_catch_all }}:
-

{% if not user_get_alias_details.is_catch_all %}{% endif %}

+

{% if not user_get_alias_details.is_catch_all %}{% else %}{{ user_get_alias_details.is_catch_all }}{% endif %}

From 3814c3294f74ca1ba926f40a2096e5bff0ea0717 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 13:45:57 +0200 Subject: [PATCH 020/174] [Web] add edit/cors api endpoint to swagger --- data/web/api/openapi.yaml | 46 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 46 insertions(+) diff --git a/data/web/api/openapi.yaml b/data/web/api/openapi.yaml index 661611534..1d2621689 100644 --- a/data/web/api/openapi.yaml +++ b/data/web/api/openapi.yaml @@ -5602,6 +5602,50 @@ paths: description: You can list all mailboxes existing in system for a specific domain. operationId: Get mailboxes of a domain summary: Get mailboxes of a domain + /api/v1/edit/cors: + post: + responses: + "401": + $ref: "#/components/responses/Unauthorized" + "200": + content: + application/json: + examples: + response: + value: + - type: "success" + log: ["cors", "edit", {"allowed_origins": ["*", "mail.mailcow.tld"], "allowed_methods": ["POST", "GET", "DELETE", "PUT"]}] + msg: "cors_headers_edited" + description: OK + headers: { } + tags: + - Cross-Origin Resource Sharing (CORS) + description: >- + This endpoint allows you to manage Cross-Origin Resource Sharing (CORS) settings for the API. + CORS is a security feature implemented by web browsers to prevent unauthorized cross-origin requests. + By editing the CORS settings, you can specify which domains and which methods are permitted to access the API resources from outside the mailcow domain. + operationId: Edit Cross-Origin Resource Sharing (CORS) settings + requestBody: + content: + application/json: + schema: + example: + attr: + allowed_origins: ["*", "mail.mailcow.tld"] + allowed_methods: ["POST", "GET", "DELETE", "PUT"] + properties: + attr: + type: object + properties: + allowed_origins: + type: array + items: + type: string + allowed_methods: + type: array + items: + type: string + summary: Edit Cross-Origin Resource Sharing (CORS) settings tags: - name: Domains @@ -5646,3 +5690,5 @@ tags: description: Get the status of your cow - name: Ratelimits description: Edit domain ratelimits + - name: Cross-Origin Resource Sharing (CORS) + description: Manage Cross-Origin Resource Sharing (CORS) settings From b9867e3fe0e9d1afd53a83e115560713b32734fb Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 14:16:11 +0200 Subject: [PATCH 021/174] [Web] change style of f2b active ban actions --- data/web/templates/admin/tab-config-f2b.twig | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index 2eb5ff276..d9b2fa479 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -92,16 +92,16 @@ {% endif %} {% for active_ban in f2b_data.active_bans %}

- + {{ active_ban.network }} ({{ active_ban.banned_until }}) - {% if active_ban.queued_for_unban == 0 %} - [{{ lang.admin.queue_unban }}] - [whitelist] - [blacklist (needs restart)] + [{{ lang.admin.queue_unban }}] + [whitelist] + [blacklist (needs restart)] {% else %} {{ lang.admin.unban_pending }} {% endif %} From 11407973b10af8d9f79735a44f1f3f33b9d9aa33 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 27 Jul 2023 14:19:18 +0200 Subject: [PATCH 022/174] [Web] change style of f2b active ban actions --- data/web/templates/admin/tab-config-f2b.twig | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index d9b2fa479..4336591ad 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -99,9 +99,9 @@ ({{ active_ban.banned_until }}) - {% if active_ban.queued_for_unban == 0 %} - [{{ lang.admin.queue_unban }}] - [whitelist] - [blacklist (needs restart)] + [{{ lang.admin.queue_unban }}] + [whitelist] + [blacklist (needs restart)] {% else %} {{ lang.admin.unban_pending }} {% endif %} From c10be77a1be259cbf0a4c9004394c27d3614806b Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 28 Jul 2023 12:13:07 +0200 Subject: [PATCH 023/174] Fixed Syntax error in generate_config.sh --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index ce550e46f..e42a68fc4 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -59,7 +59,7 @@ else fi detect_bad_asn() { - if [[ curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) ]]; then + if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then if ! $SPAMHAUS_DQS_KEY; then echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" From 731fabef58726a9f8d6ffdb2fb81e9bbe0da1757 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 28 Jul 2023 12:13:07 +0200 Subject: [PATCH 024/174] Fixed Syntax error in generate_config.sh --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index ce550e46f..e42a68fc4 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -59,7 +59,7 @@ else fi detect_bad_asn() { - if [[ curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) ]]; then + if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then if ! $SPAMHAUS_DQS_KEY; then echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" From 525364ba6541b59f98b4a6becdd09ab541b02729 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 28 Jul 2023 20:27:38 +0200 Subject: [PATCH 025/174] Implemented remote Bad AS lookup --- data/Dockerfiles/postfix/postfix.sh | 37 +++++++++++++++++++++++++++-- generate_config.sh | 28 +++++++++++++++------- update.sh | 12 ++++++++-- 3 files changed, 64 insertions(+), 13 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index d0ba8aac0..1b5b383c2 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -393,6 +393,7 @@ query = SELECT goto FROM spamalias AND validity >= UNIX_TIMESTAMP() EOF +echo -e "\e[33mChecking if ASN for your IP is listed for Spamhaus Bad ASN List...\e[0m" if [ -n "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m" echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m" @@ -431,7 +432,8 @@ if [ -n "$SPAMHAUS_DQS_KEY" ]; then EOF else - if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then + response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 403 ]; then echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m" echo -e "\e[33mNo SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!\e[0m" cat < /opt/postfix/conf/dns_blocklists.cf @@ -461,7 +463,7 @@ else dnsbl.sorbs.net=127.0.0.6*2 dnsbl.sorbs.net=127.0.0.9*2 EOF - else + elif [ "$response" -eq 200 ]; then echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m" echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m" cat < /opt/postfix/conf/dns_blocklists.cf @@ -495,6 +497,37 @@ EOF zen.spamhaus.org=127.0.0.3*4 zen.spamhaus.org=127.0.0.2*3 EOF + + else + echo -e "\e[31mWe couldn't determine your AS... (maybe DNS/Network issue?) Response Code: $response\e[0m" + echo -e "\e[33mDeactivating Spamhaus DNS Blocklists to be on the safe site!\e[0m" + cat < /opt/postfix/conf/dns_blocklists.cf + # Autogenerated by mailcow + postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 +EOF fi fi diff --git a/generate_config.sh b/generate_config.sh index e42a68fc4..e62b6db57 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -21,7 +21,7 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox grep if cp --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""; exit 1; fi if sed --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox sed detected, please install gnu sed, \"apk add --no-cache --upgrade sed\""; exit 1; fi -for bin in openssl curl docker git awk sha1sum grep cut whois; do +for bin in openssl curl docker git awk sha1sum grep cut; do if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi done @@ -59,19 +59,29 @@ else fi detect_bad_asn() { - if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then - if ! $SPAMHAUS_DQS_KEY; then - echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." - echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!" + echo -e "\e[33mDetecting if your IP is listed on Spamhaus Bad ASN List...\e[0m" + response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 403 ]; then + if [ -z "$SPAMHAUS_DQS_KEY" ]; then + echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" + echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m" + sleep 2 + echo "" + echo -e "\e[33mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account\e[0m" + echo -e "\e[33mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!\e[0m" echo "" - echo -e "\e[31mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account" - echo -e "\e[31mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!" sleep 2 else - echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix." - echo -e "\e[33mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key..." + echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" + echo -e "\e[32mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key...\e[0m" fi + elif [ "$response" -eq 200 ]; then + echo -e "\e[33mCheck completed! Your IP is \e[32mclean\e[0m" + elif [ "$response" -eq 429 ]; then + echo -e "\e[33mCheck completed! \e[31mYour IP seems to be rate limited on the ASN Check service... please try again later!\e[0m" + else + echo -e "\e[31mCheck failed! \e[0mMaybe a DNS or Network problem?\e[0m" fi } diff --git a/update.sh b/update.sh index 23c25becd..5b8aa9e87 100755 --- a/update.sh +++ b/update.sh @@ -256,7 +256,9 @@ fi } detect_bad_asn() { - if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null ; then + echo -e "\e[33mDetecting if your IP is listed on Spamhaus Bad ASN List...\e[0m" + response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 403 ]; then if [ -z "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m" @@ -271,6 +273,12 @@ detect_bad_asn() { echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" echo -e "\e[32mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key...\e[0m" fi + elif [ "$response" -eq 200 ]; then + echo -e "\e[33mCheck completed! Your IP is \e[32mclean\e[0m" + elif [ "$response" -eq 429 ]; then + echo -e "\e[33mCheck completed! \e[31mYour IP seems to be rate limited on the ASN Check service... please try again later!\e[0m" + else + echo -e "\e[31mCheck failed! \e[0mMaybe a DNS or Network problem?\e[0m" fi } @@ -320,7 +328,7 @@ umask 0022 unset COMPOSE_COMMAND unset DOCKER_COMPOSE_VERSION -for bin in curl docker git awk sha1sum grep cut whois; do +for bin in curl docker git awk sha1sum grep cut; do if [[ -z $(command -v ${bin}) ]]; then echo "Cannot find ${bin}, exiting..." exit 1; From 34d990a80038e88122f8ff6b9d4f235416d8cef1 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 28 Jul 2023 20:35:28 +0200 Subject: [PATCH 026/174] Removed obsolete whois package --- data/Dockerfiles/postfix/Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/data/Dockerfiles/postfix/Dockerfile b/data/Dockerfiles/postfix/Dockerfile index 4a894fd4f..bda6e07f2 100644 --- a/data/Dockerfiles/postfix/Dockerfile +++ b/data/Dockerfiles/postfix/Dockerfile @@ -17,10 +17,10 @@ RUN groupadd -g 102 postfix \ ca-certificates \ curl \ dirmngr \ - dnsutils \ + dnsutils \ gnupg \ libsasl2-modules \ - mariadb-client \ + mariadb-client \ perl \ postfix \ postfix-mysql \ @@ -32,8 +32,7 @@ RUN groupadd -g 102 postfix \ syslog-ng \ syslog-ng-core \ syslog-ng-mod-redis \ - tzdata \ - whois \ + tzdata \ && rm -rf /var/lib/apt/lists/* \ && touch /etc/default/locale \ && printf '#!/bin/bash\n/usr/sbin/postconf -c /opt/postfix/conf "$@"' > /usr/local/sbin/postconf \ From 952ddb18fd59707b3d68b7908cc599d17aadadc5 Mon Sep 17 00:00:00 2001 From: Christian Hailer Date: Sun, 30 Jul 2023 18:56:52 +0200 Subject: [PATCH 027/174] dns_blocklists.cf isn't appended to main.cf and therefore ineffective #5340 --- data/Dockerfiles/postfix/postfix.sh | 3 +++ 1 file changed, 3 insertions(+) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 1b5b383c2..9696fa9f2 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -539,6 +539,9 @@ echo -e "myhostname = ${MAILCOW_HOSTNAME}\n$(cat /opt/postfix/conf/extra.cf)" > cat /opt/postfix/conf/extra.cf >> /opt/postfix/conf/main.cf +# Append postscreen dnsbl sites to main.cf +cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf + if [ ! -f /opt/postfix/conf/custom_transport.pcre ]; then echo "Creating dummy custom_transport.pcre" touch /opt/postfix/conf/custom_transport.pcre From 6cf2775e7e03a01436d4f6f07145d24d1b80fa48 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 31 Jul 2023 12:01:34 +0200 Subject: [PATCH 028/174] Fix Reponse Code for ASN Checks --- generate_config.sh | 4 ++-- update.sh | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index e62b6db57..d09dae9e6 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -60,8 +60,8 @@ fi detect_bad_asn() { echo -e "\e[33mDetecting if your IP is listed on Spamhaus Bad ASN List...\e[0m" - response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") - if [ "$response" -eq 403 ]; then + response=$(curl --connect-timeout 15 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 503 ]; then if [ -z "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m" diff --git a/update.sh b/update.sh index 5b8aa9e87..8c5a4fb5c 100755 --- a/update.sh +++ b/update.sh @@ -257,8 +257,8 @@ fi detect_bad_asn() { echo -e "\e[33mDetecting if your IP is listed on Spamhaus Bad ASN List...\e[0m" - response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") - if [ "$response" -eq 403 ]; then + response=$(curl --connect-timeout 15 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 503 ]; then if [ -z "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m" echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m" From 0f337971ff12b89805bb58b14b858c74e8fdb7dd Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 31 Jul 2023 12:03:07 +0200 Subject: [PATCH 029/174] Reimplemented option for custom dnsbls --- data/Dockerfiles/postfix/postfix.sh | 137 +++++----------------------- docker-compose.yml | 2 +- 2 files changed, 22 insertions(+), 117 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 9696fa9f2..8450bbe61 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -397,136 +397,40 @@ echo -e "\e[33mChecking if ASN for your IP is listed for Spamhaus Bad ASN List.. if [ -n "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m" echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m" - cat < /opt/postfix/conf/dns_blocklists.cf - # Autogenerated by mailcow - postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.[10;11]*8 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.3*4 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.2*3 - ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 - ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 + cat < /tmp/spamhaus.cf +# Autogenerated by mailcow, using Spamhaus DQS lists + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.[10;11]*8 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.3*4 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.2*3 + ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 + ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 EOF else - response=$(curl --connect-timeout 15 --retry 5 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") - if [ "$response" -eq 403 ]; then + response=$(curl --connect-timeout 15 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") + if [ "$response" -eq 503 ]; then echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m" echo -e "\e[33mNo SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!\e[0m" - cat < /opt/postfix/conf/dns_blocklists.cf - # Autogenerated by mailcow - postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 + cat < /tmp/spamhaus.cf +# Autogenerated by mailcow, using no Spamhaus DNSBL EOF elif [ "$response" -eq 200 ]; then echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m" echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m" - cat < /opt/postfix/conf/dns_blocklists.cf - # Autogenerated by mailcow - postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 - zen.spamhaus.org=127.0.0.[10;11]*8 - zen.spamhaus.org=127.0.0.[4..7]*6 - zen.spamhaus.org=127.0.0.3*4 - zen.spamhaus.org=127.0.0.2*3 + cat < /tmp/spamhaus.cf +# Autogenerated by mailcow, using public spamhaus lists + zen.spamhaus.org=127.0.0.[10;11]*8 + zen.spamhaus.org=127.0.0.[4..7]*6 + zen.spamhaus.org=127.0.0.3*4 + zen.spamhaus.org=127.0.0.2*3 EOF else echo -e "\e[31mWe couldn't determine your AS... (maybe DNS/Network issue?) Response Code: $response\e[0m" echo -e "\e[33mDeactivating Spamhaus DNS Blocklists to be on the safe site!\e[0m" - cat < /opt/postfix/conf/dns_blocklists.cf - # Autogenerated by mailcow - postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 + cat < /tmp/spamhaus.cf +# Autogenerated by mailcow, using no Spamhaus DNSBL EOF fi fi @@ -541,6 +445,7 @@ cat /opt/postfix/conf/extra.cf >> /opt/postfix/conf/main.cf # Append postscreen dnsbl sites to main.cf cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf +cat /tmp/spamhaus.cf >> /opt/postfix/conf/main.cf if [ ! -f /opt/postfix/conf/custom_transport.pcre ]; then echo "Creating dummy custom_transport.pcre" diff --git a/docker-compose.yml b/docker-compose.yml index 865dacb2f..bd7c4acbb 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -297,7 +297,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.69 + image: mailcow/postfix:1.70 depends_on: - mysql-mailcow volumes: From 6d17b9f504c1356b31ddb997dfa751032e257410 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 31 Jul 2023 12:03:31 +0200 Subject: [PATCH 030/174] Added dns_blocklists.cf for customizations --- data/conf/postfix/dns_blocklists.cf | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) create mode 100644 data/conf/postfix/dns_blocklists.cf diff --git a/data/conf/postfix/dns_blocklists.cf b/data/conf/postfix/dns_blocklists.cf new file mode 100644 index 000000000..9fc9e70f8 --- /dev/null +++ b/data/conf/postfix/dns_blocklists.cf @@ -0,0 +1,25 @@ +# Content loaded from dns_blocklists.cf, edit only if really necessary! +postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 From 31cb0f7db133bfbf3ebe7761032644ada6ec6683 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 31 Jul 2023 10:06:07 +0000 Subject: [PATCH 031/174] update postscreen_access.cidr --- data/conf/postfix/postscreen_access.cidr | 359 ++++++++++++++++------- 1 file changed, 252 insertions(+), 107 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 5509433ba..153cd6894 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,15 +1,20 @@ -# Whitelist generated by Postwhite v3.4 on Mon 21 Mar 2022 06:50:26 PM CET +# Whitelist generated by Postwhite v3.4 on Mon Jul 31 10:06:06 UTC 2023 # https://github.com/stevejenkins/postwhite/ -# 1898 total rules +# 2043 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit -2a01:111:f403::/48 permit -2a01:4180:4050:0400::/64 permit -2a01:4180:4050:0800::/64 permit -2a01:4180:4051:0400::/64 permit -2a01:4180:4051:0800::/64 permit +2a01:111:f403:8000::/50 permit +2a01:111:f403::/49 permit +2a01:111:f403:c000::/51 permit +2a01:111:f403:f000::/52 permit 2a02:a60:0:5::/64 permit 2c0f:fb50:4000::/36 permit +2.207.151.53 permit +3.14.230.16 permit +3.70.123.177 permit +3.93.157.0/24 permit +3.129.120.190 permit +3.210.190.0/24 permit 8.20.114.31 permit 8.25.194.0/23 permit 8.25.196.0/23 permit @@ -19,41 +24,53 @@ 13.70.32.43 permit 13.72.50.45 permit 13.74.143.28 permit -13.77.161.179 permit 13.78.233.182 permit 13.92.31.129 permit 13.110.208.0/21 permit +13.110.209.0/24 permit 13.110.216.0/22 permit 13.110.224.0/20 permit 13.111.0.0/16 permit -17.41.0.0/16 permit +15.200.21.50 permit +15.200.44.248 permit +15.200.201.185 permit 17.57.155.0/24 permit 17.57.156.0/24 permit 17.58.0.0/16 permit -17.110.0.0/15 permit -17.142.0.0/15 permit -17.162.0.0/15 permit -17.164.0.0/16 permit -17.171.37.0/24 permit -17.172.0.0/16 permit -17.179.168.0/23 permit +18.156.89.250 permit +18.157.243.190 permit 18.194.95.56 permit 18.198.96.88 permit -20.47.149.138 permit -20.48.0.0/12 permit +18.208.124.128/25 permit +18.216.232.154 permit +18.234.1.244 permit +18.236.40.242 permit +20.51.6.32/30 permit 20.52.52.2 permit 20.52.128.133 permit +20.59.80.4/30 permit 20.63.210.192/28 permit -20.64.0.0/10 permit +20.69.8.108/30 permit +20.70.246.20 permit +20.76.201.171 permit +20.83.222.104/30 permit +20.88.157.184/30 permit 20.94.180.64/28 permit +20.97.34.220/30 permit +20.98.148.156/30 permit +20.98.194.68/30 permit +20.105.209.76/30 permit +20.107.239.64/30 permit +20.112.250.133 permit +20.118.139.208/30 permit 20.185.213.160/27 permit 20.185.213.224/27 permit 20.185.214.0/27 permit 20.185.214.2 permit 20.185.214.32/27 permit 20.185.214.64/27 permit -20.192.0.0/10 permit -23.100.85.1 permit +20.231.239.246 permit +20.236.44.162 permit 23.103.224.0/19 permit 23.249.208.0/20 permit 23.251.224.0/19 permit @@ -78,46 +95,38 @@ 27.123.206.56/29 permit 27.123.206.76/30 permit 27.123.206.80/28 permit -34.194.25.167 permit -34.194.144.120 permit +31.25.48.222 permit +34.195.217.107 permit +34.202.239.6 permit 34.212.163.75 permit +34.215.104.144 permit 34.225.212.172 permit 34.247.168.44 permit +35.161.32.253 permit +35.167.93.243 permit 35.176.132.251 permit 35.190.247.0/24 permit 35.191.0.0/16 permit -37.188.97.188 permit 37.218.248.47 permit 37.218.249.47 permit 37.218.251.62 permit 39.156.163.64/29 permit 40.71.187.0/24 permit -40.76.4.15 permit -40.77.102.222 permit 40.92.0.0/15 permit -40.97.116.82 permit -40.97.128.194 permit -40.97.148.226 permit -40.97.153.146 permit -40.97.156.114 permit -40.97.160.2 permit -40.97.161.50 permit -40.97.164.146 permit 40.107.0.0/16 permit 40.112.65.63 permit -40.112.72.205 permit -40.113.200.201 permit 40.117.80.0/24 permit -40.121.71.46 permit 41.74.192.0/22 permit 41.74.196.0/22 permit 41.74.200.0/23 permit 41.74.204.0/23 permit 41.74.206.0/24 permit -42.159.163.81 permit -42.159.163.82 permit -42.159.163.83 permit 43.228.184.0/22 permit +44.206.138.57 permit +44.209.42.157 permit +44.236.56.93 permit +44.238.220.251 permit +46.19.168.0/23 permit 46.226.48.0/21 permit 46.228.36.37 permit 46.228.36.38/31 permit @@ -167,6 +176,8 @@ 46.243.88.175 permit 46.243.88.176 permit 46.243.88.177 permit +46.243.95.179 permit +46.243.95.180 permit 50.18.45.249 permit 50.18.121.236 permit 50.18.121.248 permit @@ -178,11 +189,6 @@ 50.31.32.0/19 permit 50.31.156.96/27 permit 50.31.205.0/24 permit -51.4.71.62 permit -51.4.72.0/24 permit -51.4.80.0/27 permit -51.5.72.0/24 permit -51.5.80.0/27 permit 51.137.58.21 permit 51.140.75.55 permit 51.144.100.179 permit @@ -191,17 +197,28 @@ 52.5.230.59 permit 52.27.5.72 permit 52.27.28.47 permit -52.33.191.91 permit +52.28.63.81 permit 52.36.138.31 permit 52.37.142.146 permit -52.38.191.253 permit -52.41.64.145 permit +52.58.216.183 permit +52.59.143.3 permit 52.60.41.5 permit 52.60.115.116 permit +52.61.91.9 permit +52.71.0.205 permit 52.82.172.0/22 permit 52.94.124.0/28 permit 52.95.48.152/29 permit 52.95.49.88/29 permit +52.96.91.34 permit +52.96.111.82 permit +52.96.172.98 permit +52.96.214.50 permit +52.96.222.194 permit +52.96.222.226 permit +52.96.223.2 permit +52.96.228.130 permit +52.96.229.242 permit 52.100.0.0/14 permit 52.119.213.144/28 permit 52.160.39.140 permit @@ -214,23 +231,29 @@ 52.222.73.83 permit 52.222.73.120 permit 52.222.75.85 permit +52.222.89.228 permit 52.234.172.96/28 permit 52.236.28.240/28 permit -52.237.141.173 permit 52.244.206.214 permit 52.247.53.144 permit 52.250.107.196 permit 52.250.126.174 permit -52.251.55.143 permit 54.90.148.255 permit -54.156.255.69 permit 54.172.97.247 permit +54.174.52.0/24 permit +54.174.53.128/30 permit +54.174.57.0/24 permit +54.174.59.0/24 permit +54.174.60.0/23 permit +54.174.63.0/24 permit 54.186.193.102 permit -54.191.223.5 permit +54.191.223.56 permit 54.194.61.95 permit 54.195.113.45 permit +54.213.20.246 permit 54.214.39.184 permit 54.216.77.168 permit +54.221.227.204 permit 54.240.0.0/18 permit 54.240.64.0/19 permit 54.240.96.0/19 permit @@ -238,7 +261,9 @@ 54.244.54.130 permit 54.244.242.0/24 permit 54.246.232.180 permit +54.255.61.23 permit 62.13.128.0/24 permit +62.13.128.150 permit 62.13.129.128/25 permit 62.13.136.0/22 permit 62.13.140.0/22 permit @@ -249,22 +274,29 @@ 62.17.146.128/26 permit 62.140.7.0/24 permit 62.140.10.21 permit +62.179.121.0/24 permit +62.201.172.0/27 permit +62.201.172.32/27 permit +62.253.227.114 permit 63.32.13.159 permit 63.80.14.0/23 permit +63.111.28.137 permit 63.128.21.0/24 permit 63.143.57.128/25 permit 63.143.59.128/25 permit 64.18.0.0/20 permit 64.20.241.45 permit -64.34.47.128/27 permit -64.34.57.192/26 permit +64.69.212.0/24 permit 64.71.149.160/28 permit 64.79.155.0/24 permit +64.79.155.192 permit +64.79.155.193 permit +64.79.155.205 permit +64.79.155.206 permit 64.89.44.85 permit 64.89.45.80 permit 64.89.45.194 permit 64.89.45.196 permit -64.95.144.196 permit 64.127.115.252 permit 64.132.88.0/23 permit 64.132.92.0/24 permit @@ -290,6 +322,7 @@ 64.207.219.71 permit 64.207.219.72 permit 64.207.219.73 permit +64.207.219.75 permit 64.207.219.77 permit 64.207.219.78 permit 64.207.219.79 permit @@ -300,9 +333,6 @@ 64.207.219.142 permit 64.207.219.143 permit 64.233.160.0/19 permit -65.38.115.76 permit -65.38.115.84 permit -65.39.215.0/24 permit 65.52.80.137 permit 65.54.51.64/26 permit 65.54.61.64/26 permit @@ -342,6 +372,10 @@ 66.111.4.225 permit 66.111.4.229 permit 66.111.4.230 permit +66.119.150.192/26 permit +66.135.202.0/27 permit +66.135.215.0/24 permit +66.135.222.1 permit 66.162.193.226/31 permit 66.163.184.0/21 permit 66.163.184.0/24 permit @@ -373,7 +407,8 @@ 66.196.81.234 permit 66.211.168.230/31 permit 66.211.170.86/31 permit -66.211.170.88/30 permit +66.211.170.88/29 permit +66.211.184.0/23 permit 66.218.74.64/30 permit 66.218.74.68/31 permit 66.218.75.112/30 permit @@ -445,6 +480,8 @@ 68.142.230.72/30 permit 68.142.230.76/31 permit 68.142.230.78 permit +68.232.140.138 permit +68.232.157.143 permit 68.232.192.0/20 permit 69.63.178.128/25 permit 69.63.181.0/24 permit @@ -452,6 +489,10 @@ 69.65.42.195 permit 69.65.49.192/29 permit 69.72.32.0/20 permit +69.72.40.93 permit +69.72.40.94/31 permit +69.72.40.96/30 permit +69.72.47.205 permit 69.147.84.227 permit 69.162.98.0/24 permit 69.169.224.0/20 permit @@ -460,7 +501,7 @@ 70.37.151.128/25 permit 70.42.149.0/24 permit 70.42.149.35 permit -72.3.185.0/24 permit +72.3.237.64/28 permit 72.14.192.0/18 permit 72.21.192.0/19 permit 72.21.217.142 permit @@ -522,15 +563,11 @@ 72.30.239.228/31 permit 72.30.239.244/30 permit 72.30.239.248/31 permit -72.32.154.0/24 permit -72.32.217.0/24 permit -72.32.243.0/24 permit 72.34.168.76 permit 72.34.168.80 permit 72.34.168.85 permit 72.34.168.86 permit 72.52.72.32/28 permit -72.52.72.36 permit 74.6.128.0/21 permit 74.6.128.0/24 permit 74.6.129.0/24 permit @@ -558,8 +595,11 @@ 74.112.67.243 permit 74.125.0.0/16 permit 74.202.227.40 permit +74.208.4.192/26 permit +74.208.5.64/26 permit +74.208.122.0/26 permit 74.209.250.0/24 permit -74.209.250.12 permit +76.223.128.0/19 permit 76.223.176.0/20 permit 77.238.176.0/22 permit 77.238.176.0/24 permit @@ -583,7 +623,13 @@ 77.238.189.146/31 permit 77.238.189.148/30 permit 81.223.46.0/27 permit -84.16.77.1 permit +82.165.159.0/24 permit +82.165.159.0/26 permit +82.165.229.31 permit +82.165.229.130 permit +82.165.230.21 permit +82.165.230.22 permit +84.116.36.0/24 permit 85.158.136.0/21 permit 86.61.88.25 permit 87.198.219.130 permit @@ -624,11 +670,11 @@ 87.248.117.201 permit 87.248.117.202 permit 87.248.117.205 permit -87.252.219.254 permit 87.253.232.0/21 permit 89.22.108.0/24 permit +91.194.248.0/23 permit +91.211.240.0/22 permit 91.220.42.0/24 permit -94.236.119.0/26 permit 94.245.112.0/27 permit 94.245.112.10/31 permit 95.131.104.0/21 permit @@ -638,6 +684,7 @@ 96.43.148.64/28 permit 96.43.148.64/31 permit 96.43.151.64/28 permit +98.97.248.0/21 permit 98.136.44.181 permit 98.136.44.182/31 permit 98.136.44.184 permit @@ -1142,23 +1189,21 @@ 98.139.245.212/31 permit 99.78.197.208/28 permit 103.2.140.0/22 permit -103.9.8.121 permit -103.9.8.122 permit -103.9.8.123 permit 103.9.96.0/22 permit 103.13.69.0/24 permit +103.28.42.0/24 permit 103.47.204.0/22 permit 103.96.21.0/24 permit +103.96.22.0/24 permit 103.96.23.0/24 permit 103.151.192.0/23 permit -103.237.104.0/22 permit +103.168.172.128/27 permit 104.43.243.237 permit +104.44.112.128/25 permit 104.47.0.0/17 permit 104.130.96.0/28 permit 104.130.122.0/23 permit 104.214.25.77 permit -104.215.148.63 permit -104.215.186.3 permit 104.245.209.192/26 permit 106.10.144.64/27 permit 106.10.144.100/31 permit @@ -1320,6 +1365,8 @@ 117.120.16.0/21 permit 119.42.242.52/31 permit 119.42.242.156 permit +121.244.91.48 permit +122.15.156.182 permit 123.126.78.64/29 permit 124.47.150.0/24 permit 124.47.189.0/24 permit @@ -1335,20 +1382,35 @@ 128.127.70.0/26 permit 128.245.0.0/20 permit 128.245.64.0/20 permit +128.245.176.0/20 permit +128.245.242.0/24 permit +128.245.242.16 permit +128.245.242.17 permit +128.245.242.18 permit +128.245.243.0/24 permit +128.245.244.0/24 permit +128.245.245.0/24 permit +128.245.246.0/24 permit +128.245.247.0/24 permit 129.41.77.70 permit 129.41.169.249 permit +129.80.5.164 permit +129.80.67.121 permit +129.146.88.28 permit +129.146.147.105 permit 129.146.236.58 permit +129.151.67.221 permit +129.153.62.216 permit +129.153.104.71 permit +129.153.168.146 permit +129.153.190.200 permit 129.153.194.228 permit 129.159.87.137 permit +129.213.195.191 permit 130.61.9.72 permit 130.211.0.0/22 permit -130.248.172.0/24 permit -130.248.173.0/24 permit -131.107.0.0/16 permit 131.253.30.0/24 permit 131.253.121.0/26 permit -131.253.121.20 permit -131.253.121.52 permit 132.145.13.209 permit 132.226.26.225 permit 132.226.49.32 permit @@ -1358,9 +1420,13 @@ 134.170.141.64/26 permit 134.170.143.0/24 permit 134.170.174.0/24 permit -135.84.80.192/26 permit +135.84.80.0/24 permit +135.84.81.0/24 permit 135.84.82.0/24 permit +135.84.83.0/24 permit 135.84.216.0/22 permit +136.143.160.0/24 permit +136.143.161.0/24 permit 136.143.182.0/23 permit 136.143.184.0/24 permit 136.143.188.0/24 permit @@ -1369,34 +1435,53 @@ 136.147.176.0/20 permit 136.147.176.0/24 permit 136.147.182.0/24 permit +136.179.50.206 permit 138.91.172.26 permit 139.60.152.0/22 permit -139.178.64.159 permit -139.178.64.195 permit +139.138.35.44 permit +139.138.46.121 permit +139.138.46.176 permit +139.138.46.219 permit +139.138.57.55 permit +139.138.58.119 permit +139.180.17.0/24 permit +141.148.159.229 permit 141.193.32.0/23 permit 143.55.224.0/21 permit 143.55.232.0/22 permit 143.55.236.0/22 permit +143.244.80.0/20 permit +144.24.6.140 permit +144.34.8.247 permit +144.34.9.247 permit +144.34.32.247 permit +144.34.33.247 permit 144.178.36.0/24 permit 144.178.38.0/24 permit +145.253.228.160/29 permit +145.253.239.128/29 permit 146.20.112.0/26 permit 146.20.113.0/24 permit 146.20.191.0/24 permit 146.20.215.0/24 permit +146.20.215.182 permit +146.88.28.0/24 permit 146.101.78.0/24 permit -147.75.65.173 permit -147.75.65.174 permit -147.75.98.190 permit +147.28.36.0/24 permit 147.160.158.0/24 permit 147.243.1.47 permit 147.243.1.48 permit 147.243.1.153 permit 147.243.128.24 permit 147.243.128.26 permit -148.105.0.14 permit +148.105.0.0/16 permit 148.105.8.0/21 permit 149.72.0.0/16 permit +149.97.173.180 permit +150.230.98.160 permit 152.67.105.195 permit +152.69.200.236 permit +155.248.208.51 permit 157.55.0.192/26 permit 157.55.1.128/26 permit 157.55.2.0/25 permit @@ -1412,32 +1497,43 @@ 157.56.232.0/21 permit 157.56.240.0/20 permit 157.56.248.0/21 permit +157.58.30.128/25 permit 157.58.196.96/29 permit 157.58.249.3 permit 157.151.208.65 permit 157.255.1.64/29 permit +158.101.211.207 permit +158.120.80.0/21 permit +158.247.16.0/20 permit 159.92.157.0/24 permit +159.92.157.16 permit +159.92.157.17 permit +159.92.157.18 permit 159.92.158.0/24 permit 159.92.159.0/24 permit 159.92.160.0/24 permit 159.92.161.0/24 permit 159.92.162.0/24 permit +159.112.240.0/20 permit +159.112.242.162 permit 159.135.132.128/25 permit 159.135.140.80/29 permit 159.135.224.0/20 permit +159.135.228.10 permit 159.183.0.0/16 permit +160.1.62.192 permit 161.38.192.0/20 permit 161.38.204.0/22 permit 161.71.32.0/19 permit 161.71.64.0/20 permit -162.208.119.181 permit 162.247.216.0/22 permit +163.47.180.0/22 permit 163.47.180.0/23 permit 163.114.130.16 permit 163.114.132.120 permit +165.173.128.0/24 permit 166.78.68.0/22 permit 166.78.68.221 permit -166.78.69.146 permit 166.78.69.169 permit 166.78.69.170 permit 166.78.71.131 permit @@ -1457,10 +1553,13 @@ 167.216.129.210 permit 167.216.131.180 permit 167.220.67.232/29 permit -167.220.67.238 permit 168.138.5.36 permit +168.138.73.51 permit 168.245.0.0/17 permit +169.148.129.0/24 permit +169.148.131.0/24 permit 170.10.68.0/22 permit +170.10.128.0/24 permit 170.10.129.0/24 permit 170.10.133.0/24 permit 172.217.0.0/19 permit @@ -1475,10 +1574,8 @@ 173.194.0.0/16 permit 173.203.79.182 permit 173.203.81.39 permit -173.224.160.128/25 permit -173.224.160.188 permit 173.224.161.128/25 permit -173.228.155.0/24 permit +173.224.165.0/26 permit 174.36.84.8/29 permit 174.36.84.16/29 permit 174.36.84.32/29 permit @@ -1491,6 +1588,7 @@ 174.36.114.152/29 permit 174.37.67.28/30 permit 174.129.203.189 permit +175.41.215.51 permit 176.32.105.0/24 permit 176.32.127.0/24 permit 178.236.10.128/26 permit @@ -1498,8 +1596,9 @@ 182.50.76.0/22 permit 182.50.78.64/28 permit 183.240.219.64/29 permit +185.4.120.0/23 permit +185.4.122.0/24 permit 185.12.80.0/22 permit -185.28.196.0/22 permit 185.58.84.93 permit 185.58.85.0/24 permit 185.58.86.0/24 permit @@ -1509,9 +1608,13 @@ 185.80.93.204 permit 185.80.93.227 permit 185.80.95.31 permit +185.90.20.0/22 permit 185.189.236.0/22 permit 185.211.120.0/22 permit 185.250.236.0/22 permit +185.250.239.148 permit +185.250.239.168 permit +185.250.239.190 permit 188.125.68.132 permit 188.125.68.152/31 permit 188.125.68.156 permit @@ -1563,7 +1666,7 @@ 188.125.85.238 permit 188.172.128.0/20 permit 192.0.64.0/18 permit -192.28.128.0/18 permit +192.18.139.154 permit 192.30.252.0/22 permit 192.64.236.0/24 permit 192.64.237.0/24 permit @@ -1579,16 +1682,21 @@ 192.254.113.10 permit 192.254.113.101 permit 192.254.114.176 permit -192.254.118.63 permit 193.7.206.0/25 permit 193.7.207.0/25 permit 193.109.254.0/23 permit 193.122.128.100 permit +194.64.234.128/27 permit 194.64.234.129 permit 194.104.109.0/24 permit +194.104.110.21 permit +194.104.110.240/28 permit 194.104.111.0/24 permit 194.106.220.0/23 permit +194.113.24.0/22 permit 194.154.193.192/27 permit +195.4.92.0/23 permit +195.54.172.0/23 permit 195.130.217.0/24 permit 195.234.109.226 permit 195.245.230.0/23 permit @@ -1605,19 +1713,23 @@ 198.37.144.0/20 permit 198.37.152.186 permit 198.61.254.0/23 permit +198.61.254.21 permit 198.61.254.231 permit -198.74.56.28 permit 198.178.234.57 permit +198.244.48.0/20 permit +198.244.60.0/22 permit 198.245.80.0/20 permit 198.245.81.0/24 permit 199.15.176.173 permit -199.15.212.0/22 permit 199.15.213.187 permit 199.15.226.37 permit 199.16.156.0/22 permit 199.33.145.1 permit 199.33.145.32 permit 199.59.148.0/22 permit +199.67.84.0/24 permit +199.67.86.0/24 permit +199.67.88.0/24 permit 199.101.161.130 permit 199.101.162.0/25 permit 199.122.120.0/21 permit @@ -1630,8 +1742,10 @@ 202.177.148.110 permit 203.31.36.0/22 permit 203.32.4.25 permit +203.55.21.0/24 permit 203.81.17.0/24 permit 203.122.32.250 permit +203.145.57.160/27 permit 203.188.194.32 permit 203.188.194.151 permit 203.188.194.203 permit @@ -1666,28 +1780,31 @@ 203.209.230.76/31 permit 204.11.168.0/21 permit 204.13.11.48/29 permit +204.13.11.48/30 permit 204.14.232.0/21 permit 204.14.232.64/28 permit 204.14.234.64/28 permit 204.29.186.0/23 permit +204.75.142.0/24 permit 204.79.197.212 permit 204.92.114.187 permit 204.92.114.203 permit 204.92.114.204/31 permit 204.141.32.0/23 permit 204.141.42.0/23 permit -204.153.121.0/24 permit 204.232.168.0/24 permit 205.139.110.0/24 permit 205.201.128.0/20 permit 205.201.131.128/25 permit 205.201.134.128/25 permit 205.201.136.0/23 permit +205.201.137.229 permit 205.201.139.0/24 permit 205.207.104.0/22 permit -205.207.104.108 permit 205.220.167.17 permit +205.220.167.98 permit 205.220.179.17 permit +205.220.179.98 permit 205.251.233.32 permit 205.251.233.36 permit 206.25.247.143 permit @@ -1723,6 +1840,7 @@ 207.211.31.0/25 permit 207.211.41.113 permit 207.218.90.0/24 permit +207.218.90.122 permit 207.250.68.0/24 permit 208.40.232.70 permit 208.43.21.28/30 permit @@ -1758,8 +1876,10 @@ 208.71.42.212/31 permit 208.71.42.214 permit 208.72.249.240/29 permit +208.74.204.0/22 permit 208.74.204.9 permit 208.75.120.0/22 permit +208.75.121.246 permit 208.75.122.246 permit 208.82.237.96/29 permit 208.82.237.104/31 permit @@ -1773,14 +1893,13 @@ 209.46.117.168 permit 209.46.117.179 permit 209.61.151.0/24 permit +209.61.151.236 permit +209.61.151.249 permit +209.61.151.251 permit 209.67.98.46 permit 209.67.98.59 permit 209.85.128.0/17 permit 212.4.136.0/26 permit -212.25.240.80 permit -212.25.240.83 permit -212.25.240.84/31 permit -212.25.240.88 permit 212.82.96.0/24 permit 212.82.96.32/27 permit 212.82.96.64/29 permit @@ -1821,6 +1940,12 @@ 212.82.111.228/31 permit 212.82.111.230 permit 212.123.28.40 permit +212.227.15.0/24 permit +212.227.15.0/25 permit +212.227.17.0/27 permit +212.227.126.128/25 permit +213.46.255.0/24 permit +213.165.64.0/23 permit 213.167.75.0/25 permit 213.167.81.0/25 permit 213.199.128.139 permit @@ -1861,6 +1986,10 @@ 216.46.168.0/24 permit 216.58.192.0/19 permit 216.66.217.240/29 permit +216.71.138.33 permit +216.71.152.207 permit +216.71.154.29 permit +216.71.155.89 permit 216.74.162.13 permit 216.74.162.14 permit 216.82.240.0/20 permit @@ -1870,33 +1999,49 @@ 216.109.114.0/24 permit 216.109.114.32/27 permit 216.109.114.64/29 permit +216.113.160.0/24 permit +216.113.172.0/25 permit +216.113.175.0/24 permit 216.128.126.97 permit 216.136.162.65 permit 216.136.162.120/29 permit 216.136.168.80/28 permit +216.145.217.0/24 permit +216.145.221.0/24 permit 216.198.0.0/18 permit 216.203.30.55 permit 216.203.33.178/31 permit 216.205.24.0/24 permit 216.239.32.0/19 permit +217.72.192.64/26 permit +217.72.192.248/29 permit +217.72.207.0/27 permit 217.77.141.52 permit 217.77.141.59 permit +217.175.194.0/24 permit 222.73.195.64/29 permit 223.165.113.0/24 permit 223.165.115.0/24 permit 223.165.118.0/23 permit 223.165.120.0/23 permit +2001:0868:0100:0600::/64 permit 2001:4860:4000::/36 permit +2001:748:100:40::2:0/112 permit 2404:6800:4000::/36 permit +2603:1010:3:3::5b permit +2603:1020:201:10::10f permit +2603:1030:20e:3::23c permit +2603:1030:b:3::152 permit +2603:1030:c02:8::14 permit 2607:f8b0:4000::/36 permit -2620:109:c003:104::215 permit 2620:109:c003:104::/64 permit -2620:109:c006:104::215 permit +2620:109:c003:104::215 permit 2620:109:c006:104::/64 permit +2620:109:c006:104::215 permit 2620:109:c00d:104::/64 permit 2620:10d:c090:450::120 permit -2620:10d:c091:450::16 permit -2620:119:50c0:207::215 permit +2620:10d:c091:400::8:1 permit 2620:119:50c0:207::/64 permit +2620:119:50c0:207::215 permit 2800:3f0:4000::/36 permit 194.25.134.0/24 permit # t-online.de From 3000da6b880da04d4621bc9b1a93d86f1b6112e4 Mon Sep 17 00:00:00 2001 From: "Hailer, Christian" Date: Mon, 31 Jul 2023 13:50:36 +0200 Subject: [PATCH 032/174] Fix spamhaus query domains (.net only) --- data/Dockerfiles/postfix/postfix.sh | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 8450bbe61..fb408ce9a 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -400,9 +400,9 @@ if [ -n "$SPAMHAUS_DQS_KEY" ]; then cat < /tmp/spamhaus.cf # Autogenerated by mailcow, using Spamhaus DQS lists ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.[10;11]*8 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.3*4 - ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.2*3 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[10;11]*8 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.3*4 + ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.2*3 ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 EOF From 5e7583c5e622ee264edb188b6259d668b8ad6b85 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20RICCIO?= Date: Tue, 1 Aug 2023 10:49:26 +0200 Subject: [PATCH 033/174] Fix main.cf merging order Now the dnsbl files are merged before extra.cf --- data/Dockerfiles/postfix/postfix.sh | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index fb408ce9a..fd149e5b5 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -435,6 +435,10 @@ EOF fi fi +# Append postscreen dnsbl sites to main.cf +cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf +cat /tmp/spamhaus.cf >> /opt/postfix/conf/main.cf + sed -i '/User overrides/q' /opt/postfix/conf/main.cf echo >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf @@ -443,10 +447,6 @@ echo -e "myhostname = ${MAILCOW_HOSTNAME}\n$(cat /opt/postfix/conf/extra.cf)" > cat /opt/postfix/conf/extra.cf >> /opt/postfix/conf/main.cf -# Append postscreen dnsbl sites to main.cf -cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf -cat /tmp/spamhaus.cf >> /opt/postfix/conf/main.cf - if [ ! -f /opt/postfix/conf/custom_transport.pcre ]; then echo "Creating dummy custom_transport.pcre" touch /opt/postfix/conf/custom_transport.pcre From 7cda9f063f900f216e32785bdbb2ddb7bdc3814b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9bastien=20RICCIO?= Date: Tue, 1 Aug 2023 13:59:23 +0200 Subject: [PATCH 034/174] Fix for fix I did not paid attention to the "User overrides" sed/q --- data/Dockerfiles/postfix/postfix.sh | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index fd149e5b5..4177682ef 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -435,11 +435,13 @@ EOF fi fi +sed -i '/User overrides/q' /opt/postfix/conf/main.cf + # Append postscreen dnsbl sites to main.cf cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf cat /tmp/spamhaus.cf >> /opt/postfix/conf/main.cf -sed -i '/User overrides/q' /opt/postfix/conf/main.cf +# Append user overrides echo >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf sed -i '/myhostname/d' /opt/postfix/conf/extra.cf From 9f39af46aa9952d192cb1aaea47a3785eb088fc7 Mon Sep 17 00:00:00 2001 From: Christian Hailer Date: Tue, 1 Aug 2023 16:12:44 +0200 Subject: [PATCH 035/174] Add postscreen_dnsbl_reply_map to avoid disclosure of DQS key with Spamhaus setup --- data/Dockerfiles/postfix/postfix.sh | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index fb408ce9a..8099301a7 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -405,6 +405,17 @@ if [ -n "$SPAMHAUS_DQS_KEY" ]; then ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.2*3 ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 +postscreen_dnsbl_reply_map = texthash:/opt/postfix/conf/dnsbl_reply +EOF + + cat < /opt/postfix/conf/dnsbl_reply +# Autogenerated by mailcow, using Spamhaus DQS lists +${SPAMHAUS_DQS_KEY}.sbl.dq.spamhaus.net sbl.spamhaus.org +${SPAMHAUS_DQS_KEY}.xbl.dq.spamhaus.net xbl.spamhaus.org +${SPAMHAUS_DQS_KEY}.pbl.dq.spamhaus.net pbl.spamhaus.org +${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net zen.spamhaus.org +${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net dbl.spamhaus.org +${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net zrd.spamhaus.org EOF else From c45684b986fbe2f11a492ba44a82351acb097fed Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 2 Aug 2023 16:36:59 +0200 Subject: [PATCH 036/174] [Postfix] rework dns_blocklists.cf generation --- data/Dockerfiles/postfix/postfix.sh | 74 +++++++++++++++++++---------- data/conf/postfix/dns_blocklists.cf | 25 ---------- data/conf/postfix/main.cf | 2 +- 3 files changed, 51 insertions(+), 50 deletions(-) delete mode 100644 data/conf/postfix/dns_blocklists.cf diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 4177682ef..ce7888723 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -393,12 +393,43 @@ query = SELECT goto FROM spamalias AND validity >= UNIX_TIMESTAMP() EOF +if [ ! -f /opt/postfix/conf/dns_blocklists.cf ]; then + cat < /opt/postfix/conf/dns_blocklists.cf +# This file can be edited. +# Delete this file and restart postfix container to revert any changes. +postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 + hostkarma.junkemailfilter.com=127.0.0.1*-2 + list.dnswl.org=127.0.[0..255].0*-2 + list.dnswl.org=127.0.[0..255].1*-4 + list.dnswl.org=127.0.[0..255].2*-6 + list.dnswl.org=127.0.[0..255].3*-8 + ix.dnsbl.manitu.net*2 + bl.spamcop.net*2 + bl.suomispam.net*2 + hostkarma.junkemailfilter.com=127.0.0.2*3 + hostkarma.junkemailfilter.com=127.0.0.4*2 + hostkarma.junkemailfilter.com=127.0.1.2*1 + backscatter.spameatingmonkey.net*2 + bl.ipv6.spameatingmonkey.net*2 + bl.spameatingmonkey.net*2 + b.barracudacentral.org=127.0.0.2*7 + bl.mailspike.net=127.0.0.2*5 + bl.mailspike.net=127.0.0.[10;11;12]*4 + dnsbl.sorbs.net=127.0.0.10*8 + dnsbl.sorbs.net=127.0.0.5*6 + dnsbl.sorbs.net=127.0.0.7*3 + dnsbl.sorbs.net=127.0.0.8*2 + dnsbl.sorbs.net=127.0.0.6*2 + dnsbl.sorbs.net=127.0.0.9*2 +EOF +fi +DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S') + echo -e "\e[33mChecking if ASN for your IP is listed for Spamhaus Bad ASN List...\e[0m" if [ -n "$SPAMHAUS_DQS_KEY" ]; then echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m" echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m" - cat < /tmp/spamhaus.cf -# Autogenerated by mailcow, using Spamhaus DQS lists + SPAMHAUS_DNSBL_CONFIG=$(cat < /tmp/spamhaus.cf -# Autogenerated by mailcow, using no Spamhaus DNSBL -EOF + echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m" + echo -e "\e[33mNo SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!\e[0m" + SPAMHAUS_DNSBL_CONFIG="" elif [ "$response" -eq 200 ]; then - echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m" - echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m" - cat < /tmp/spamhaus.cf -# Autogenerated by mailcow, using public spamhaus lists + echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m" + echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m" + SPAMHAUS_DNSBL_CONFIG=$(cat < /tmp/spamhaus.cf -# Autogenerated by mailcow, using no Spamhaus DNSBL -EOF + echo -e "\e[31mWe couldn't determine your AS... (maybe DNS/Network issue?) Response Code: $response\e[0m" + echo -e "\e[33mDeactivating Spamhaus DNS Blocklists to be on the safe site!\e[0m" + SPAMHAUS_DNSBL_CONFIG="" fi fi -sed -i '/User overrides/q' /opt/postfix/conf/main.cf - -# Append postscreen dnsbl sites to main.cf -cat /opt/postfix/conf/dns_blocklists.cf >> /opt/postfix/conf/main.cf -cat /tmp/spamhaus.cf >> /opt/postfix/conf/main.cf - -# Append user overrides +# Reset main.cf +sed -i '/Overrides/q' /opt/postfix/conf/main.cf echo >> /opt/postfix/conf/main.cf +# Append postscreen dnsbl sites to main.cf +echo -e "${DNSBL_CONFIG}\n${SPAMHAUS_DNSBL_CONFIG}" >> /opt/postfix/conf/main.cf +# Append user overrides +echo -e "\n# User Overrides" >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf sed -i '/myhostname/d' /opt/postfix/conf/extra.cf echo -e "myhostname = ${MAILCOW_HOSTNAME}\n$(cat /opt/postfix/conf/extra.cf)" > /opt/postfix/conf/extra.cf - cat /opt/postfix/conf/extra.cf >> /opt/postfix/conf/main.cf if [ ! -f /opt/postfix/conf/custom_transport.pcre ]; then diff --git a/data/conf/postfix/dns_blocklists.cf b/data/conf/postfix/dns_blocklists.cf deleted file mode 100644 index 9fc9e70f8..000000000 --- a/data/conf/postfix/dns_blocklists.cf +++ /dev/null @@ -1,25 +0,0 @@ -# Content loaded from dns_blocklists.cf, edit only if really necessary! -postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 - hostkarma.junkemailfilter.com=127.0.0.1*-2 - list.dnswl.org=127.0.[0..255].0*-2 - list.dnswl.org=127.0.[0..255].1*-4 - list.dnswl.org=127.0.[0..255].2*-6 - list.dnswl.org=127.0.[0..255].3*-8 - ix.dnsbl.manitu.net*2 - bl.spamcop.net*2 - bl.suomispam.net*2 - hostkarma.junkemailfilter.com=127.0.0.2*3 - hostkarma.junkemailfilter.com=127.0.0.4*2 - hostkarma.junkemailfilter.com=127.0.1.2*1 - backscatter.spameatingmonkey.net*2 - bl.ipv6.spameatingmonkey.net*2 - bl.spameatingmonkey.net*2 - b.barracudacentral.org=127.0.0.2*7 - bl.mailspike.net=127.0.0.2*5 - bl.mailspike.net=127.0.0.[10;11;12]*4 - dnsbl.sorbs.net=127.0.0.10*8 - dnsbl.sorbs.net=127.0.0.5*6 - dnsbl.sorbs.net=127.0.0.7*3 - dnsbl.sorbs.net=127.0.0.8*2 - dnsbl.sorbs.net=127.0.0.6*2 - dnsbl.sorbs.net=127.0.0.9*2 diff --git a/data/conf/postfix/main.cf b/data/conf/postfix/main.cf index a5751c65c..237b42635 100644 --- a/data/conf/postfix/main.cf +++ b/data/conf/postfix/main.cf @@ -169,4 +169,4 @@ smtps_smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1 parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,qmqpd_authorized_clients # DO NOT EDIT ANYTHING BELOW # -# User overrides # +# Overrides # From 5d3491c80192b14abce7ff71585a0c3b8b786855 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 2 Aug 2023 16:48:22 +0200 Subject: [PATCH 037/174] [Postfix] only apply DNSBL if dns_blocklists.cf is not empty --- data/Dockerfiles/postfix/postfix.sh | 49 +++++++++++++++-------------- 1 file changed, 26 insertions(+), 23 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index ce7888723..c0fb7eb0b 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -425,11 +425,12 @@ EOF fi DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S') -echo -e "\e[33mChecking if ASN for your IP is listed for Spamhaus Bad ASN List...\e[0m" -if [ -n "$SPAMHAUS_DQS_KEY" ]; then - echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m" - echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m" - SPAMHAUS_DNSBL_CONFIG=$(cat <> /opt/postfix/conf/main.cf # Append postscreen dnsbl sites to main.cf -echo -e "${DNSBL_CONFIG}\n${SPAMHAUS_DNSBL_CONFIG}" >> /opt/postfix/conf/main.cf +if [ ! -z "$DNSBL_CONFIG" ]; then + echo -e "${DNSBL_CONFIG}\n${SPAMHAUS_DNSBL_CONFIG}" >> /opt/postfix/conf/main.cf +fi # Append user overrides echo -e "\n# User Overrides" >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf From 003eecf131f15b86f5ace52f7441cbd141dc1ce7 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 2 Aug 2023 17:08:55 +0200 Subject: [PATCH 038/174] [Postfix] remove spamhaus dbl and zrd from postscreen_dnsbl_sites --- data/Dockerfiles/postfix/postfix.sh | 2 -- docker-compose.yml | 2 +- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index c0fb7eb0b..731328d38 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -435,8 +435,6 @@ if [ ! -z "$DNSBL_CONFIG" ]; then ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[10;11]*8 ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.3*4 ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.2*3 - ${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4 - ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3 EOF ) else diff --git a/docker-compose.yml b/docker-compose.yml index 289ed7615..ac45857fe 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -297,7 +297,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.70 + image: mailcow/postfix:1.71 depends_on: - mysql-mailcow volumes: From b050cb9864c09bb78d747c4e0243f2ba4c144b43 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 3 Aug 2023 09:00:08 +0200 Subject: [PATCH 039/174] [Postfix] remove dnsbl_reply.map if not required --- .gitignore | 1 + data/Dockerfiles/postfix/postfix.sh | 9 ++++++--- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/.gitignore b/.gitignore index 0169c439a..3595ecb1e 100644 --- a/.gitignore +++ b/.gitignore @@ -37,6 +37,7 @@ data/conf/postfix/sni.map data/conf/postfix/sni.map.db data/conf/postfix/sql data/conf/postfix/dns_blocklists.cf +data/conf/postfix/dnsbl_reply.map data/conf/rspamd/custom/* data/conf/rspamd/local.d/* data/conf/rspamd/override.d/* diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index ba87aaa26..f981bff6e 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -435,10 +435,10 @@ if [ ! -z "$DNSBL_CONFIG" ]; then ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[10;11]*8 ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.3*4 ${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.2*3 -postscreen_dnsbl_reply_map = texthash:/opt/postfix/conf/dnsbl_reply +postscreen_dnsbl_reply_map = texthash:/opt/postfix/conf/dnsbl_reply.map EOF - cat < /opt/postfix/conf/dnsbl_reply + cat < /opt/postfix/conf/dnsbl_reply.map # Autogenerated by mailcow, using Spamhaus DQS reply domains ${SPAMHAUS_DQS_KEY}.sbl.dq.spamhaus.net sbl.spamhaus.org ${SPAMHAUS_DQS_KEY}.xbl.dq.spamhaus.net xbl.spamhaus.org @@ -449,6 +449,9 @@ ${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net zrd.spamhaus.org EOF ) else + if [ -f "/opt/postfix/conf/dnsbl_reply.map" ]; then + rm /opt/postfix/conf/dnsbl_reply.map + fi response=$(curl --connect-timeout 15 --max-time 30 -s -o /dev/null -w "%{http_code}" "https://asn-check.mailcow.email") if [ "$response" -eq 503 ]; then echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m" @@ -519,4 +522,4 @@ if [[ $? != 0 ]]; then else postfix -c /opt/postfix/conf start sleep 126144000 -fi \ No newline at end of file +fi From 5bf29e6ac1ecf365828ef8e7bf13833b0ec4fc63 Mon Sep 17 00:00:00 2001 From: Habetdin <15926758+Habetdin@users.noreply.github.com> Date: Sat, 5 Aug 2023 00:25:19 +0300 Subject: [PATCH 040/174] [Postfix] fix extra.cf updating --- data/Dockerfiles/postfix/postfix.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index f981bff6e..b3098d3af 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -486,7 +486,7 @@ fi # Append user overrides echo -e "\n# User Overrides" >> /opt/postfix/conf/main.cf touch /opt/postfix/conf/extra.cf -sed -i '/myhostname/d' /opt/postfix/conf/extra.cf +sed -i '/\$myhostname/! { /myhostname/d }' /opt/postfix/conf/extra.cf echo -e "myhostname = ${MAILCOW_HOSTNAME}\n$(cat /opt/postfix/conf/extra.cf)" > /opt/postfix/conf/extra.cf cat /opt/postfix/conf/extra.cf >> /opt/postfix/conf/main.cf From 533bd36572dc0e6476425717499f1c2248160ec4 Mon Sep 17 00:00:00 2001 From: Michael Stilkerich Date: Sat, 5 Aug 2023 20:58:34 +0200 Subject: [PATCH 041/174] Fix CPU load of dockerapi container Previously the handle_pubsub_messages() loop was executing every 10ms when there was no message available. Now reading from the redis network socket will block (the coroutine) for up to 30s before it returns when no message is available. Using channel.listen() would be even better, but it lacks the ignore_subscribe_messages option and I could not figure out how to filter the returned messages. --- data/Dockerfiles/dockerapi/main.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/dockerapi/main.py b/data/Dockerfiles/dockerapi/main.py index 59d1a8adb..453a059dc 100644 --- a/data/Dockerfiles/dockerapi/main.py +++ b/data/Dockerfiles/dockerapi/main.py @@ -198,8 +198,8 @@ async def handle_pubsub_messages(channel: aioredis.client.PubSub): while True: try: - async with async_timeout.timeout(1): - message = await channel.get_message(ignore_subscribe_messages=True) + async with async_timeout.timeout(60): + message = await channel.get_message(ignore_subscribe_messages=True, timeout=30) if message is not None: # Parse message data_json = json.loads(message['data'].decode('utf-8')) From 340ef866d20439cef748dea95fb59b3a7f409418 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sun, 6 Aug 2023 16:39:26 +0200 Subject: [PATCH 042/174] Update thollander/actions-comment-pull-request action to v2.4.1 (#5377) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/check_prs_if_on_staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_prs_if_on_staging.yml b/.github/workflows/check_prs_if_on_staging.yml index bb0d09386..93cd5e325 100644 --- a/.github/workflows/check_prs_if_on_staging.yml +++ b/.github/workflows/check_prs_if_on_staging.yml @@ -10,7 +10,7 @@ jobs: if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging steps: - name: Send message - uses: thollander/actions-comment-pull-request@v2.4.0 + uses: thollander/actions-comment-pull-request@v2.4.1 with: GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }} message: | From e468c59dfcdba37e57bec54bd5789eb709006da8 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 7 Aug 2023 06:46:07 +0200 Subject: [PATCH 043/174] Update thollander/actions-comment-pull-request action to v2.4.2 (#5379) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/check_prs_if_on_staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_prs_if_on_staging.yml b/.github/workflows/check_prs_if_on_staging.yml index 93cd5e325..c28454f65 100644 --- a/.github/workflows/check_prs_if_on_staging.yml +++ b/.github/workflows/check_prs_if_on_staging.yml @@ -10,7 +10,7 @@ jobs: if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging steps: - name: Send message - uses: thollander/actions-comment-pull-request@v2.4.1 + uses: thollander/actions-comment-pull-request@v2.4.2 with: GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }} message: | From 025fd0331038422327a29e699ed9252db2187eb4 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 7 Aug 2023 14:26:30 +0200 Subject: [PATCH 044/174] [Rspamd] remove X-Moo-Tag header if unnecessary --- data/conf/rspamd/lua/rspamd.local.lua | 23 +++++++++++++++++++++-- 1 file changed, 21 insertions(+), 2 deletions(-) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 5b08dc934..b29a24461 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -221,6 +221,16 @@ rspamd_config:register_symbol({ local tagged_rcpt = task:get_symbol("TAGGED_RCPT") local mailcow_domain = task:get_symbol("RCPT_MAILCOW_DOMAIN") + local function remove_moo_tag() + local moo_tag_header = task:get_header('X-Moo-Tag', false) + if moo_tag_header then + task:set_milter_reply({ + remove_headers = {['X-Moo-Tag'] = 0}, + }) + end + return true + end + if tagged_rcpt and tagged_rcpt[1].options and mailcow_domain then local tag = tagged_rcpt[1].options[1] rspamd_logger.infox("found tag: %s", tag) @@ -229,6 +239,7 @@ rspamd_config:register_symbol({ if action ~= 'no action' and action ~= 'greylist' then rspamd_logger.infox("skipping tag handler for action: %s", action) + remove_moo_tag() return true end @@ -243,6 +254,7 @@ rspamd_config:register_symbol({ local function tag_callback_subfolder(err, data) if err or type(data) ~= 'string' then rspamd_logger.infox(rspamd_config, "subfolder tag handler for rcpt %s returned invalid or empty data (\"%s\") or error (\"%s\")", body, data, err) + remove_moo_tag() else rspamd_logger.infox("Add X-Moo-Tag header") task:set_milter_reply({ @@ -261,6 +273,7 @@ rspamd_config:register_symbol({ ) if not redis_ret_subfolder then rspamd_logger.infox(rspamd_config, "cannot make request to load tag handler for rcpt") + remove_moo_tag() end else @@ -268,7 +281,10 @@ rspamd_config:register_symbol({ local sbj = task:get_header('Subject') new_sbj = '=?UTF-8?B?' .. tostring(util.encode_base64('[' .. tag .. '] ' .. sbj)) .. '?=' task:set_milter_reply({ - remove_headers = {['Subject'] = 1}, + remove_headers = { + ['Subject'] = 1, + ['X-Moo-Tag'] = 0 + }, add_headers = {['Subject'] = new_sbj} }) end @@ -284,6 +300,7 @@ rspamd_config:register_symbol({ ) if not redis_ret_subject then rspamd_logger.infox(rspamd_config, "cannot make request to load tag handler for rcpt") + remove_moo_tag() end end @@ -295,6 +312,7 @@ rspamd_config:register_symbol({ if #rcpt_split == 2 then if rcpt_split[1] == 'postmaster' then rspamd_logger.infox(rspamd_config, "not expanding postmaster alias") + remove_moo_tag() else rspamd_http.request({ task=task, @@ -307,7 +325,8 @@ rspamd_config:register_symbol({ end end end - + else + remove_moo_tag() end end, priority = 19 From 1db899027197cec65ce98b34b2a31cd1fb5679da Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 10 Aug 2023 13:51:40 +0200 Subject: [PATCH 045/174] Fixed Branch checkout in generate_config.sh --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index d09dae9e6..127496051 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -189,7 +189,7 @@ if [[ ${SKIP_BRANCH} != y ]]; then done git fetch --all - git checkout -f $git_branch + git checkout -f $MAILCOW_BRANCH elif [[ ${SKIP_BRANCH} == y ]]; then echo -e "\033[33mEnabled Dev Mode.\033[0m" From 930473a980051ef1931ae5c4f57bedb24d56745e Mon Sep 17 00:00:00 2001 From: Michael Stilkerich Date: Sat, 12 Aug 2023 07:20:56 +0200 Subject: [PATCH 046/174] Set asyncio timeout to 0 for yielding --- data/Dockerfiles/dockerapi/main.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/dockerapi/main.py b/data/Dockerfiles/dockerapi/main.py index 453a059dc..f9f02b63f 100644 --- a/data/Dockerfiles/dockerapi/main.py +++ b/data/Dockerfiles/dockerapi/main.py @@ -244,7 +244,7 @@ async def handle_pubsub_messages(channel: aioredis.client.PubSub): else: dockerapi.logger.error("Unknwon PubSub recieved - %s" % json.dumps(data_json)) - await asyncio.sleep(0.01) + await asyncio.sleep(0.0) except asyncio.TimeoutError: pass From 1a2f145b288583fd0e4caf517c4e0c9960b52a03 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Fr=C3=B6hle?= Date: Sat, 12 Aug 2023 16:45:09 +0200 Subject: [PATCH 047/174] Update site.conf: server_names_hash_bucket_size 128 --- data/conf/nginx/site.conf | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/data/conf/nginx/site.conf b/data/conf/nginx/site.conf index 1b46d2b9c..fb40de879 100644 --- a/data/conf/nginx/site.conf +++ b/data/conf/nginx/site.conf @@ -1,5 +1,6 @@ proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g; -server_names_hash_bucket_size 64; +server_names_hash_max_size 512; +server_names_hash_bucket_size 128; map $http_x_forwarded_proto $client_req_scheme { default $scheme; From 095d59c01b8e0e8c52777a978f618ec511e5128a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20Fr=C3=B6hle?= Date: Sat, 12 Aug 2023 16:46:02 +0200 Subject: [PATCH 048/174] Update listen_ssl.template deprecated http2 on listener --- data/conf/nginx/templates/listen_ssl.template | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/data/conf/nginx/templates/listen_ssl.template b/data/conf/nginx/templates/listen_ssl.template index 93ec80c6d..40c402d04 100644 --- a/data/conf/nginx/templates/listen_ssl.template +++ b/data/conf/nginx/templates/listen_ssl.template @@ -1,2 +1,3 @@ -listen ${HTTPS_PORT} ssl http2; -listen [::]:${HTTPS_PORT} ssl http2; +listen ${HTTPS_PORT} ssl; +listen [::]:${HTTPS_PORT} ssl; +http2 on; From 2c52753adb28517d54e579fc1973ccacc5b4d5fb Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 14 Aug 2023 15:21:07 +0000 Subject: [PATCH 049/174] Update dependency nextcloud/server to v27.0.2 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 1b08a554b..6d7c7953c 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.0.1 +NEXTCLOUD_VERSION=27.0.2 echo -ne "Checking prerequisites..." sleep 1 From 30e241babe1c0d28bc27ddb9043b545f2782b36f Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 19 Aug 2023 21:47:23 +0200 Subject: [PATCH 050/174] Translations update from Weblate (#5390) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.de-de.json Co-authored-by: Peter Co-authored-by: milkmaker * [Web] Updated lang.es-es.json Co-authored-by: Marco Truffat Co-authored-by: milkmaker * [Web] Updated lang.hu-hu.json [Web] Updated lang.hu-hu.json [Web] Updated lang.hu-hu.json Co-authored-by: 0xAndrewBlack <0xandrewblack@gmail.com> Co-authored-by: Kántor Attila Co-authored-by: Mihály Szilágyi Co-authored-by: milkmaker * [Web] Updated lang.ro-ro.json Co-authored-by: Vlad M Co-authored-by: milkmaker * [Web] Updated lang.ru-ru.json Co-authored-by: Oleksii Kruhlenko Co-authored-by: milkmaker * [Web] Updated lang.gr-gr.json [Web] Added lang.gr-gr.json Co-authored-by: Nik Beaver Co-authored-by: Peter Co-authored-by: milkmaker * [Web] Updated lang.fr-fr.json Co-authored-by: Adrien Kara Co-authored-by: milkmaker * [Web] Updated lang.en-gb.json Co-authored-by: Philipp E Co-authored-by: milkmaker * [Web] Updated lang.ca-es.json Co-authored-by: Marco Truffat Co-authored-by: milkmaker * [Web] Updated lang.it-it.json Co-authored-by: Michele Caputo Co-authored-by: milkmaker * [Web] Updated lang.uk-ua.json Co-authored-by: Oleksii Kruhlenko Co-authored-by: milkmaker * [Web] Updated lang.si-si.json [Web] Updated lang.si-si.json [Web] Updated lang.si-si.json [Web] Added lang.si-si.json Co-authored-by: Peter Co-authored-by: gomiunik Co-authored-by: milkmaker * Add Greek + Slovenian --------- Co-authored-by: Peter Co-authored-by: Marco Truffat Co-authored-by: 0xAndrewBlack <0xandrewblack@gmail.com> Co-authored-by: Kántor Attila Co-authored-by: Mihály Szilágyi Co-authored-by: Vlad M Co-authored-by: Oleksii Kruhlenko Co-authored-by: Nik Beaver Co-authored-by: Adrien Kara Co-authored-by: Philipp E Co-authored-by: Michele Caputo Co-authored-by: gomiunik --- data/web/inc/vars.inc.php | 2 + data/web/lang/lang.ca-es.json | 24 ++- data/web/lang/lang.de-de.json | 6 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.es-es.json | 16 +- data/web/lang/lang.fr-fr.json | 3 +- data/web/lang/lang.gr-gr.json | 20 ++ data/web/lang/lang.hu-hu.json | 17 +- data/web/lang/lang.it-it.json | 7 +- data/web/lang/lang.ro-ro.json | 30 ++- data/web/lang/lang.ru-ru.json | 32 ++- data/web/lang/lang.si-si.json | 396 ++++++++++++++++++++++++++++++++++ data/web/lang/lang.uk-ua.json | 105 ++++++++- 13 files changed, 625 insertions(+), 35 deletions(-) create mode 100644 data/web/lang/lang.gr-gr.json create mode 100644 data/web/lang/lang.si-si.json diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 5e6d72e78..3f726934a 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -90,6 +90,7 @@ $AVAILABLE_LANGUAGES = array( 'es-es' => 'Español (Spanish)', 'fi-fi' => 'Suomi (Finish)', 'fr-fr' => 'Français (French)', + 'gr-gr' => 'Ελληνικά (Greek)', 'hu-hu' => 'Magyar (Hungarian)', 'it-it' => 'Italiano (Italian)', 'ko-kr' => '한국어 (Korean)', @@ -99,6 +100,7 @@ $AVAILABLE_LANGUAGES = array( 'pt-pt' => 'Português (Portuguese)', 'ro-ro' => 'Română (Romanian)', 'ru-ru' => 'Pусский (Russian)', + 'si-si' => 'Slovenščina (Slovenian)', 'sk-sk' => 'Slovenčina (Slovak)', 'sv-se' => 'Svenska (Swedish)', 'tr-tr' => 'Türkçe (Turkish)', diff --git a/data/web/lang/lang.ca-es.json b/data/web/lang/lang.ca-es.json index 26a30afd9..877b46cdb 100644 --- a/data/web/lang/lang.ca-es.json +++ b/data/web/lang/lang.ca-es.json @@ -3,7 +3,23 @@ "bcc_maps": "BCC maps", "filters": "Filtres", "recipient_maps": "Recipient maps", - "syncjobs": "Feines de sincronització" + "syncjobs": "Feines de sincronització", + "quarantine_category": "Canvia la categoria de les notificacions de quarantena", + "quarantine_notification": "Canvia les notificacions de quarantena", + "sogo_profile_reset": "Restableix el prefil SOGo", + "alias_domains": "Afegir àlies de domini", + "app_passwds": "Gestiona les contrasenyes de les aplicacions", + "domain_desc": "Canvia la descripció del domini", + "eas_reset": "Restableix els dispositius EAS", + "login_as": "Inicia sessió com a usuari de la bústia de correu", + "prohibited": "Prohibit per ACL", + "protocol_access": "Canvia el protocol d'accés", + "quarantine": "Accions de quarantena", + "quarantine_attachments": "Fitxers adjunts en quarantena", + "spam_alias": "Àlies temporals", + "spam_score": "Puntuació de correu brossa", + "tls_policy": "Política TLS", + "unlimited_quota": "Quota ilimitada per bústies de correo" }, "add": { "activate_filter_warn": "All other filters will be deactivated, when active is checked.", @@ -55,7 +71,9 @@ "target_domain": "Domini destí:", "username": "Username", "validate": "Validar", - "validation_success": "Validated successfully" + "validation_success": "Validated successfully", + "app_name": "Nom de l'aplicació", + "app_password": "Afegir contrasenya a l'aplicació" }, "admin": { "access": "Accés", @@ -259,7 +277,7 @@ }, "footer": { "cancel": "Cancel·lar", - "confirm_delete": "Confirma l'esborrat ", + "confirm_delete": "Confirma l'esborrat", "delete_now": "Esborrar ara", "delete_these_items": "Si et plau confirma els canvis al objecte amb id:", "loading": "Si et plau espera ...", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index d6f79dc58..43d2b6c50 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -343,7 +343,9 @@ "api_read_only": "Schreibgeschützter Zugriff", "api_read_write": "Lese-Schreib-Zugriff", "oauth2_apps": "OAuth2 Apps", - "queue_unban": "entsperren" + "queue_unban": "entsperren", + "allowed_methods": "Access-Control-Allow-Methods", + "allowed_origins": "Access-Control-Allow-Origin" }, "danger": { "access_denied": "Zugriff verweigert oder unvollständige/ungültige Daten", @@ -482,7 +484,7 @@ "info": "_START_ bis _END_ von _TOTAL_ Einträgen", "infoEmpty": "0 bis 0 von 0 Einträgen", "infoFiltered": "(gefiltert von _MAX_ Einträgen)", - "infoPostFix": "", + "infoPostFix": "datatables.infoPostFix", "thousands": ".", "lengthMenu": "_MENU_ Einträge anzeigen", "loadingRecords": "Wird geladen...", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 28ff19b81..a4d06da3a 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -484,7 +484,7 @@ "info": "Showing _START_ to _END_ of _TOTAL_ entries", "infoEmpty": "Showing 0 to 0 of 0 entries", "infoFiltered": "(filtered from _MAX_ total entries)", - "infoPostFix": "", + "infoPostFix": "datatables.infoPostFix", "thousands": ",", "lengthMenu": "Show _MENU_ entries", "loadingRecords": "Loading...", diff --git a/data/web/lang/lang.es-es.json b/data/web/lang/lang.es-es.json index e56e6bdd6..78580cccf 100644 --- a/data/web/lang/lang.es-es.json +++ b/data/web/lang/lang.es-es.json @@ -20,7 +20,9 @@ "tls_policy": "Póliza de TLS", "unlimited_quota": "Cuota ilimitada para buzones", "app_passwds": "Gestionar las contraseñas de aplicaciones", - "domain_desc": "Cambiar descripción del dominio" + "domain_desc": "Cambiar descripción del dominio", + "protocol_access": "Cambiar protocolo de acceso", + "quarantine_category": "Cambiar categoría de las notificaciones de cuarentena" }, "add": { "activate_filter_warn": "Todos los demás filtros se desactivarán cuando este filtro se active.", @@ -85,7 +87,13 @@ "timeout2": "Tiempo de espera para la conexión al host local", "username": "Usuario", "validate": "Validar", - "validation_success": "Validado exitosamente" + "validation_success": "Validado exitosamente", + "inactive": "Inactivo", + "app_name": "Nombre de la App", + "app_password": "Añadir contraseña para la app", + "public_comment": "Comentarios públicos", + "disable_login": "Desactivar login (el correo entrante seguirá activo)", + "comment_info": "Los comentarios privados no son visibles al usuario, mientras que los comentarios públicos aparecerán sobre la información general del usuario" }, "admin": { "access": "Acceso", @@ -114,7 +122,7 @@ "app_name": "Nombre de la app", "apps_name": "Nombre \"mailcow Apps\"", "arrival_time": "Tiempo de llegada (hora del servidor)", - "ban_list_info": "La lista de IPs bloqueadas sigue a continuación: red (tiempo de prohibición restante) - [acciones].
Las IPs en cola para ser desbloquadas se eliminarán de la lista de bloqueos en unos pocos segundos.
Las etiquetas rojas indican bloqueos permanentes permanentes mediante la inclusión en una lista negra.", + "ban_list_info": "Lista de IPs bloqueadas: red (tiempo de prohibición restante) - [acciones].
Las IPs en cola para ser desbloqueadas se eliminarán de la lista de bloqueos en unos pocos segundos.
Las etiquetas rojas indican bloqueos permanentes mediante la inclusión en la lista negra.", "change_logo": "Cambiar logo", "configuration": "Configuración", "credentials_transport_warning": "Advertencia: al agregar una nueva entrada de ruta de transporte se actualizarán las credenciales para todas las entradas con una columna de \"siguiente destino\" coincidente.", @@ -432,7 +440,7 @@ }, "header": { "administration": "Administración", - "debug": "Información del sistema", + "debug": "Información", "email": "E-Mail", "mailcow_config": "Configuración", "quarantine": "Cuarentena", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 0bc0ba02d..484205504 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -1096,7 +1096,8 @@ "weeks": "semaines", "months": "mois", "year": "année", - "years": "années" + "years": "années", + "with_app_password": "avec le mot de passe de l'application" }, "warning": { "cannot_delete_self": "Impossible de supprimer l’utilisateur connecté", diff --git a/data/web/lang/lang.gr-gr.json b/data/web/lang/lang.gr-gr.json new file mode 100644 index 000000000..df9127aec --- /dev/null +++ b/data/web/lang/lang.gr-gr.json @@ -0,0 +1,20 @@ +{ + "user": { + "verify": "Επαλήθευση", + "week": "εβδομάδα", + "weekly": "Εβδομαδιαία", + "weeks": "Εβδομάδες", + "with_app_password": "με κωδικό εφαρμογής", + "year": "χρόνος", + "years": "χρόνια" + }, + "warning": { + "cannot_delete_self": "Αδυναμία διαγραφής συνδεδεμένου χρήστη", + "dovecot_restart_failed": "Απέτυχε η επανεκκίνηση του Dovecot, παρακαλώ ελέγξτε τα αρχεία καταγραφής.", + "no_active_admin": "Αδυναμία απενεργοποίησης του τελευταίου ενεργού διαχειριστή", + "domain_added_sogo_failed": "Προστέθηκε το όνομα χώρου αλλά απέτυχε η επανεκκίνηση του SOGo.", + "hash_not_found": "Η κατακερματισμένη τιμή (hash value) δεν βρέθηκε ή έχει είδη διαγραφεί.", + "ip_invalid": "Παραλείφθηκε μη έγκυρη διεύθυνση IP: %s", + "is_not_primary_alias": "Παραλείφθηκε μη πρωτεύον ψευδώνυμο %s" + } +} diff --git a/data/web/lang/lang.hu-hu.json b/data/web/lang/lang.hu-hu.json index f04cf9c51..327f07526 100644 --- a/data/web/lang/lang.hu-hu.json +++ b/data/web/lang/lang.hu-hu.json @@ -18,7 +18,11 @@ "transport_dest_format": "Szintaxis: pelda.hu, .pelda.hu, *, fiok@pelda.hu (több érték esetén vesszővel elválasztva)", "upload": "Feltöltés", "username": "Felhasználónév", - "verify": "Ellenőrzés" + "verify": "Ellenőrzés", + "activate_api": "API aktiválása", + "activate_send": "Küldés gomb aktiválása", + "add": "Hozzáad", + "active": "Aktív" }, "edit": { "active": "Aktív", @@ -385,9 +389,18 @@ "acl": { "delimiter_action": "Elhatárolás", "alias_domains": "Alias domainek hozzáadása", - "app_passwds": "Alkalmazás jelszavak kezelése" + "app_passwds": "Alkalmazás jelszavak kezelése", + "domain_desc": "Domain leírás módosítása", + "filters": "Szűrők", + "login_as": "Bejelentkezés mint", + "quarantine": "Karantén műveletek", + "bcc_maps": "BCC címek" }, "diagnostics": { "dns_records": "DNS bejegyzések" + }, + "add": { + "username": "Felhasználónév", + "validation_success": "Sikeres ellenőrzés" } } diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 0d5b3f252..84f6e2666 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -134,10 +134,10 @@ "admins_ldap": "Amministratori LDAP", "advanced_settings": "Impostazioni avanzate", "api_allow_from": "Allow API access from these IPs/CIDR network notations", - "api_info": "The API is a work in progress. The documentation can be found at /api", + "api_info": "Questa API è in modifica. La documentazione può essere trovata su /api", "api_key": "Chiave API", "api_skip_ip_check": "Salta il controllo dell'IP per l'API", - "app_links": "App links", + "app_links": "Link dell'app", "app_name": "Nome dell'app", "apps_name": "Nome \"mailcow Apps\"", "arrival_time": "Ora di arrivo (ora del server)", @@ -338,7 +338,8 @@ "oauth2_apps": "App OAuth2", "oauth2_add_client": "Aggiungere il client OAuth2", "rsettings_preset_4": "Disattivare Rspamd per un dominio", - "options": "Opzioni" + "options": "Opzioni", + "cors_settings": "Impostazioni CORS" }, "danger": { "access_denied": "Accesso negato o form di login non corretto", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index e6315db02..62585058f 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -106,7 +106,8 @@ "timeout2": "Timeout pentru conectarea la gazda locală", "username": "Nume de utilizator", "validate": "Validează", - "validation_success": "Validat cu succes" + "validation_success": "Validat cu succes", + "tags": "Etichete" }, "admin": { "access": "Acces", @@ -334,7 +335,15 @@ "username": "Nume de utilizator", "validate_license_now": "Validează GUID cu serverul de licență", "verify": "Verifică", - "yes": "✓" + "yes": "✓", + "cors_settings": "Setări CORS", + "f2b_ban_time_increment": "Timpul de blocare creşte cu fiecare blocare", + "f2b_max_ban_time": "Max. timp de blocare (s)", + "ip_check": "Verificaţie IP", + "ip_check_disabled": "Verificarea IP este dezactivată. Puteţi activa la
Sistem > Configuraţie > Opţiuni > Personalizează", + "ip_check_opt_in": "Alegeţi să folosiţi servicile ipv4.mailcow.email şi ipv6.mailcow.email să rezolvaţi addrese IP externale.", + "options": "Opţiuni", + "queue_unban": "retractează interzicere" }, "danger": { "access_denied": "Accesul a fost respins sau datele formularului sunt invalide", @@ -453,7 +462,16 @@ "username_invalid": "Numele de utilizator %s nu poate fi utilizat", "validity_missing": "Atribuie o perioadă de valabilitate", "value_missing": "Furnizează toate valorile", - "yotp_verification_failed": "Verificarea Yubico OTP a eșuat: %s" + "yotp_verification_failed": "Verificarea Yubico OTP a eșuat: %s", + "cors_invalid_method": "Aveţi specificaţi 'Allow-Method' invalid", + "webauthn_authenticator_failed": "Authentificator selectat nu a fost găsit", + "webauthn_publickey_failed": "Nici-o cheie publică a fost salvată pentru authenticatorul selectat", + "webauthn_username_failed": "Authenticatorul selectat aparţine la alt cont", + "demo_mode_enabled": "Mod de demonstraţie este activ", + "extended_sender_acl_denied": "lipseşte ACL pentru setarea adrese externe", + "template_exists": "Şablon %s deja există", + "template_id_invalid": "Şablon ID %s este invalid", + "template_name_invalid": "Nume de şablon este invalid" }, "debug": { "chart_this_server": "Grafic (acest server)", @@ -641,7 +659,7 @@ "header": { "administration": "Configurație și detalii", "apps": "Aplicații", - "debug": "Informații Sistem", + "debug": "Informaţie", "email": "E-Mail", "mailcow_config": "Configurație", "quarantine": "Carantină", @@ -1187,5 +1205,9 @@ "quota_exceeded_scope": "Cota de spațiu a domeniului depășită: Numai căsuțe poștale nelimitate pot fi create pe acest domeniu.", "session_token": "Token formular invalid: Nepotrivire token", "session_ua": "Token formular invalid: Eroare validare utilizator-agent" + }, + "datatables": { + "expand_all": "Expandează tot", + "decimal": "," } } diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index bad64184c..0783710ca 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -338,7 +338,13 @@ "yes": "✓", "queue_unban": "разблокировать", "f2b_ban_time_increment": "Время бана увеличивается с каждым баном", - "f2b_max_ban_time": "Максимальное время блокировки" + "f2b_max_ban_time": "Максимальное время блокировки", + "allowed_origins": "Access-Control-Allow-Origin", + "cors_settings": "Настройки CORS", + "allowed_methods": "Access-Control-Allow-Methods", + "ip_check": "Проверить IP", + "ip_check_disabled": "Проверка IP отключена. Вы можете включить его в разделе
Система > Конфигурация > Параметры > Настроить.", + "ip_check_opt_in": "Согласие на использование сторонних служб ipv4.mailcow.email и ipv6.mailcow.email для разрешения внешних IP-адресов." }, "danger": { "access_denied": "Доступ запрещён, или указаны неверные данные", @@ -457,7 +463,10 @@ "username_invalid": "Имя пользователя %s нельзя использовать", "validity_missing": "Пожалуйста, назначьте срок действия", "value_missing": "Пожалуйста заполните все поля", - "yotp_verification_failed": "Ошибка валидации Yubico OTP: %s" + "yotp_verification_failed": "Ошибка валидации Yubico OTP: %s", + "cors_invalid_method": "Указан недопустимый метод разрешения", + "demo_mode_enabled": "Демонстрационный режим включен", + "cors_invalid_origin": "Указан неверный Allow-Origin" }, "debug": { "chart_this_server": "Диаграмма (текущий сервер)", @@ -542,7 +551,7 @@ "inactive": "Неактивный", "kind": "Тип", "last_modified": "Последние изменения", - "lookup_mx": "Назначение на основе резовинга MX записи по регулярному выражению (.*\\.example\\.com$ для маршрутизации всей почты через этот хост, если MX заканчивающийся на example.com)", + "lookup_mx": "Назначение на основе резолвинга MX записи по регулярному выражению (.*\\.example\\.com$ для маршрутизации всей почты через этот хост, если MX заканчивающийся на example.com)", "mailbox": "Изменение почтового аккаунта", "mailbox_quota_def": "Квота по умолчанию", "mailbox_relayhost_info": "Применяется только к почтовому ящику и личным псевдонимам, вне зависимости от настроек маршрутизации на уровне домена.", @@ -607,7 +616,9 @@ "title": "Изменение объекта", "unchanged_if_empty": "Если без изменений - оставьте пустым", "username": "Имя пользователя", - "validate_save": "Подтвердить и сохранить" + "validate_save": "Подтвердить и сохранить", + "sogo_access_info": "Единый вход из интерфейса почты продолжает работать. Эта настройка не влияет на доступ ко всем другим службам, а также не удаляет или изменяет существующий профиль пользователя SOGo.", + "app_passwd_protocols": "Разрешенные протоколы для пароля приложения" }, "fido2": { "confirm": "Подтвердить", @@ -987,7 +998,8 @@ "verified_fido2_login": "Авторизация FIDO2 пройдена", "verified_totp_login": "Авторизация TOTP пройдена", "verified_webauthn_login": "Авторизация WebAuthn пройдена", - "verified_yotp_login": "Авторизация Yubico OTP пройдена" + "verified_yotp_login": "Авторизация Yubico OTP пройдена", + "cors_headers_edited": "Настройки CORS сохранены" }, "tfa": { "api_register": "%s использует Yubico Cloud API. Пожалуйста, получите ключ API для вашего ключа здесь", @@ -1169,7 +1181,12 @@ "weekly": "Раз в неделю", "weeks": "недели", "year": "год", - "years": "лет" + "years": "лет", + "allowed_protocols": "Разрешенные протоколы", + "apple_connection_profile_with_app_password": "Новый пароль приложения генерируется и добавляется в профиль, поэтому при настройке устройства не требуется вводить пароль. Не предоставляйте доступ к файлу, поскольку он предоставляет полный доступ к вашему почтовому ящику.", + "direct_protocol_access": "Этот пользователь почтового ящика имеет прямой, внешний доступ к следующим протоколам и приложениям. Эта настройка контролируется вашим администратором. Для предоставления доступа к отдельным протоколам и приложениям могут быть созданы пароли приложений.
Кнопка \"Вход в веб-почту\" обеспечивает единый вход в SOGo и всегда доступна.", + "with_app_password": "с паролем приложения", + "change_password_hint_app_passwords": "В вашей учетной записи есть {{number_of_app_passwords}} паролей приложений, которые не будут изменены. Чтобы управлять ими, перейдите на вкладку \"Пароли приложений\"." }, "warning": { "cannot_delete_self": "Вы не можете удалить сами себя", @@ -1183,5 +1200,8 @@ "quota_exceeded_scope": "Квота домена превышена: могут быть созданы только почтовые ящики без лимита.", "session_token": "Неверный токен формы: несоответствие токена", "session_ua": "Неверный токен формы: ошибка проверки User-Agent" + }, + "datatables": { + "infoPostFix": "datatables.infoPostFix" } } diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json new file mode 100644 index 000000000..7c3ddbfdc --- /dev/null +++ b/data/web/lang/lang.si-si.json @@ -0,0 +1,396 @@ +{ + "acl": { + "app_passwds": "Upravljaj gesla aplikacij", + "bcc_maps": "Preslikave SKP (BCC)", + "delimiter_action": "Dejanje ločila", + "domain_relayhost": "Spremeni gostitelja relay za domeno", + "eas_reset": "Ponastavi EAS naprave", + "filters": "Filtri", + "login_as": "Prijavi se kot uporabnik poštnega predala", + "mailbox_relayhost": "Spremeni gostitelja relay za poštni predal", + "prohibited": "Prepovedano z ACL", + "protocol_access": "Spremeni dostop do protokola", + "pushover": "Pushover", + "quarantine": "Dejanja karantene", + "quarantine_attachments": "Priponke v karanteno", + "quarantine_notification": "Spremeni obvestila o karanteni", + "ratelimit": "Omejitev pošiljanja", + "recipient_maps": "Preslikave prejemnikov", + "smtp_ip_access": "Spremeni dovoljene gostitelje za SMTP", + "sogo_access": "Dovoli upravljanje SOGo dostopov", + "sogo_profile_reset": "Ponastavi SOGo profil", + "spam_alias": "Začasni aliasi", + "spam_policy": "Blacklist/Whitelist", + "spam_score": "Ocena neželene pošte", + "tls_policy": "Politika TLS", + "unlimited_quota": "Neomejena kvota za poštne predale", + "alias_domains": "Dodaj alias domene", + "domain_desc": "Spremeni opis domene", + "extend_sender_acl": "Dovoli razširitev pošiljateljevega ACL z zunanjimi e-poštnimi naslovi", + "quarantine_category": "Spremeni kategorijo obvestil o karanteni", + "syncjobs": "Opravila sinhronizacije" + }, + "add": { + "active": "Aktivno", + "add": "Dodaj", + "add_domain_only": "Dodaj samo domeno", + "add_domain_restart": "Dodaj domeno in ponovno zaženi SOGo", + "alias_address": "Alias naslov/i", + "alias_domain": "Alias domena", + "alias_domain_info": "Samo veljavne domene (ločene z vejico).", + "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.)", + "backup_mx_options": "Možnosti posredovanja (relay)", + "comment_info": "Zasebni komentarji niso vidni uporabnikom, javni komentarji pa so prikazani kot tooltip, ko se z miško postavimo nad uporabnika v pregledu", + "custom_params": "Parametri po meri", + "custom_params_hint": "Pravilno: --param=xy, napačno: --param xy", + "delete1": "Izbriši na viru, ko je končano", + "delete2": "Izbriši sporočila na cilju, ki niso na viru", + "delete2duplicates": "Izbriši dvojnike na cilju", + "description": "Opis", + "destination": "Cilj", + "domain": "Domena", + "domain_matches_hostname": "Domena %s se ujema z nazivom gostitelja (hostname)", + "domain_quota_m": "Kvota za celotno domeno (MiB)", + "enc_method": "Metoda kriptiranja", + "exclude": "Izključi objekte (regex)", + "full_name": "Polno ime", + "gal": "Globalni seznam stikov (GAL)", + "generate": "generiraj", + "goto_ham": "Prepoznaj kot ham", + "goto_null": "Odstrani e-poštno sporočilo brez obvestila", + "goto_spam": "Prepoznaj kot spam", + "hostname": "Gostitelj", + "inactive": "Neaktivno", + "kind": "Tip", + "mailbox_quota_def": "Privzeta kvota za poštni predal", + "mailbox_username": "Uporabniško ime (levi del e-poštnega naslova)", + "max_aliases": "Največje število dovoljenih aliasov", + "max_mailboxes": "Največje dovoljeno število poštnih predalov", + "mins_interval": "Interval preverjanja (minute)", + "multiple_bookings": "Več rezervacij", + "nexthop": "Naslednji korak", + "password_repeat": "Potrditev gesla (ponovi)", + "port": "Vrata (port)", + "private_comment": "Zasebni komentar", + "public_comment": "Javni komentar", + "quota_mb": "Kvota (MiB)", + "relay_all": "Posreduj vse prejemnike (relay)", + "relay_all_info": "↪ Če izberete da ne posredujete vse prejemnike, morate ustvariti (\"slepi\") poštni predal za vsakega prejemnika, za katerega želite posredovati e-pošto.", + "relay_domain": "Posreduj to domeno (relay)", + "relay_unknown_only": "Posreduj samo neobstoječe poštne predale. V obstoječe poštne predale bo e-pošta dostavljena lokalno.", + "relayhost_wrapped_tls_info": "Prosim ne uporabljajte TLS-wrapped vrata (večinoma uporabljeno na vratih 465).
\nUporabite katera koli non-wrapped vrata in ustvarite STARTTLS. TLS politika za obvezno uporabo TLS se lahko ustvari pod \"Preslikave TLS politik\"", + "select": "Prosim izberite...", + "select_domain": "Prosim najprej izberite domeno", + "sieve_desc": "Kratek opis", + "sieve_type": "Vrsta filtra", + "skipcrossduplicates": "Preskoči podvojena sporočila po mapah (prvi pride, prvi melje)", + "subscribeall": "Prijavi vse mape", + "syncjob": "Dodaj opravilo sinhronizacije", + "tags": "Oznake", + "target_address": "Goto naslov", + "target_address_info": "Polni e-poštni naslov/i (ločeni z vejico).", + "target_domain": "Ciljna domena", + "timeout1": "Časovna omejitev za povezavo do oddaljenega gostitelja", + "username": "Uporabniško ime", + "validate": "Preveri", + "validation_success": "Uspešno preverjeno", + "activate_filter_warn": "Ko je aktivni izbran, bodo vsi ostali filtri deaktivirani.", + "alias_address_info": "Polni email naslov/i oziroma @example.com za zajem vseh sporočil domene (ločeno z vejico), samo domene mailcow.", + "bcc_dest_format": "BCC naslov mora biti en veljaven e-poštni naslov.
Če morate poslati kopijo na več naslov, ustvarite alias in ga uporabite tukaj.", + "disable_login": "Prepovej vpis (vhodna e-pošta je še vedno sprejeta)", + "gal_info": "GAL vsebuje vse objekte domene in ga uporabniki ne morejo urejati. Informacija o zasedenosti v SOGo ni na voljo, če je onemogočena! Ponovno zaženi SOGo za uveljavitev sprememb.", + "mailbox_quota_m": "Najvišja kvota na poštni predal (MiB)", + "password": "Geslo", + "post_domain_add": "SOGo container \"sogo-mailcow\" mora biti ponovno zagnan po dodajanju nove domene!

Dodatno se mora preveriti DNS konfiguracija domene. Ko je DNS konfiguracija domene odobrena, ponovno zaženite \"acme-mailcow\" za samodejno generiranje certifikatov za novo domeno (autoconfig.<domain>, autodiscover.<domain>).
Ta korak je opcijski in se ponovno poskuša vsakih 24 ur.", + "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 plain-text!", + "timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja" + }, + "admin": { + "access": "Dostop", + "action": "Dejanje", + "activate_api": "Aktiviraj API", + "activate_send": "Aktiviraj gumb \"Pošlji\"", + "active": "Aktivno", + "active_rspamd_settings_map": "Aktivna preslikava nastavitev", + "add": "Dodaj", + "add_domain_admin": "Dodaj skrbnika domene", + "add_forwarding_host": "Dodaj gostitelja za posredovanje", + "add_relayhost": "Dodaj transport odvisen od pošiljatelja", + "add_row": "Dodaj vrstico", + "add_settings_rule": "Dodaj pravilo nastavitev", + "add_transport": "Dodaj transport", + "add_transports_hint": "Prosimo zavedajte se, da se podatki za avtentikacijo, če obstajajo, shranijo v plain text.", + "additional_rows": " nove vrstice so bile dodane", + "admin_details": "Uredi podrobnosti skrbnika", + "admin_domains": "Dodeljene domene", + "admins": "Skrbniki", + "admins_ldap": "LDAP skrbniki", + "advanced_settings": "Napredne nastavitve", + "api_info": "API je v razvoju. Dokumentacija je na voljo na naslovu /api", + "api_key": "API ključ", + "api_read_only": "Dostop samo za branje", + "api_read_write": "Dostop za branje in urejanje", + "api_skip_ip_check": "Preskoči preverjanje IP za API", + "app_links": "Povezave aplikacij", + "app_name": "Ime aplikacije", + "arrival_time": "Čas prispetja (strežniški čas)", + "authed_user": "Prij. uporabnik", + "ays": "Ste prepričani, da želite nadaljevati?", + "change_logo": "Zamenjaj logotip", + "configuration": "Konfiguracija", + "convert_html_to_text": "Pretvori HTML v golo besedilo", + "credentials_transport_warning": "Opozorilo: Dodajanje nove preslikave transporta bo posodobilo poverilnice za vse vnose, ki imajo enako vrednost v stolpcu naslednji skok.", + "customer_id": "ID stranke", + "customize": "Prilagodi", + "destination": "Cilj", + "dkim_add_key": "Dodaj ARC/DKIM ključ", + "dkim_domains_selector": "Izbira", + "dkim_domains_wo_keys": "Izberi domene z manjkajočimi ključi", + "dkim_from": "Od", + "dkim_from_title": "Izvorna domena od katere prekopiram podatke", + "dkim_key_missing": "Manjka ključ", + "dkim_key_unused": "Ključ ni v rabi", + "dkim_key_valid": "Veljaven ključ", + "dkim_keys": "ARC/DKIM ključi", + "dkim_overwrite_key": "Prepiši obstoječi DKIM ključ", + "dkim_private_key": "Zasebni ključ", + "dkim_to": "Za", + "domain": "Domena", + "domain_admin": "Skrbnik domene", + "domain_admins": "Skrbniki domene", + "domain_s": "Domena/e", + "duplicate": "Podvoji", + "duplicate_dkim": "Podvoji DKIM zapis", + "edit": "Uredi", + "empty": "Ni rezultatov", + "excludes": "Izključuje te prejemnike", + "f2b_ban_time": "Čas blokade (s)", + "f2b_ban_time_increment": "Čas blokade se poveča z vsako blokado", + "f2b_blacklist": "Mreže/gostitelji na blacklisti", + "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_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", + "f2b_whitelist": "Mreže/gostitelji na whitelisti", + "filter_table": "Filtriraj tabelo", + "from": "Od", + "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)", + "host": "Gostitelj", + "html": "HTML", + "import": "Uvozi", + "import_private_key": "Uvozi zasebni ključ", + "in_use_by": "V uporabi", + "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", + "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.", + "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_record": "Ni zapisa", + "oauth2_apps": "OAuth2 aplikacije", + "oauth2_add_client": "Dodaj OAuth2 klienta", + "oauth2_client_id": "ID klienta", + "oauth2_client_secret": "Skrivnost (secret)", + "oauth2_redirect_uri": "URI za preusmeritev", + "oauth2_renew_secret": "Generiraj nov client secret", + "oauth2_revoke_tokens": "Zavrni vse tokene klientov", + "optional": "opcijsko", + "options": "Možnosti", + "password": "Geslo", + "password_length": "Dolžina gesla", + "password_policy": "Politika gesel", + "password_policy_chars": "Mora vsebovati vsaj eno črko", + "password_policy_length": "Minimalna dolžina gesla je %d", + "password_policy_lowerupper": "Mora vsebovati male in velike črke", + "password_policy_numbers": "Mora vsebovati vsaj eno številko", + "password_policy_special_chars": "Mora vsebovati posebne znake", + "password_repeat": "Potrditev gesla (ponovite)", + "priority": "Prioriteta", + "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_release_format_att": "Kot priponka", + "quarantine_release_format_raw": "Nespremenjen original", + "quarantine_retention_size": "Število zadržanj 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.", + "queue_unban": "odblokiraj", + "r_active": "Aktivne omejitve", + "r_inactive": "Neaktivne omejitve", + "rate_name": "Ime omejitve", + "recipients": "Prejemniki", + "refresh": "Osveži", + "regen_api_key": "Ponovno generiraj API ključ", + "regex_maps": "Regex preslikave", + "relay_from": "\"Od:\" naslov", + "relay_rcpt": "\"Za:\" naslov", + "relay_run": "Izvedi test", + "relayhosts": "Transporti glede na pošiljatelja", + "remove": "Odstrani", + "remove_row": "Odstrani vrstico", + "reset_default": "Ponastavi na privzeto", + "reset_limit": "Odstrani hash", + "routing": "Routing", + "rsetting_add_rule": "Dodaj pravilo", + "rsetting_content": "Vsebina pravila", + "rsetting_desc": "Kratek opis", + "rsetting_no_selection": "Prosim izberite pravilo", + "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_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_global_filters": "Globalne preslikave filtrov", + "rspamd_global_filters_agree": "Previden bom!", + "rspamd_global_filters_info": "Globalne preslikave filtrov vsebujejo različne vrste globalnih blacklist in whitelist.", + "add_admin": "Dodaj skrbnika", + "add_relayhost_hint": "Prosimo zavedajte se, da se podatki za avtentikacijo, če obstajajo, shranijo v plain text.", + "admin": "Skrbnik", + "api_allow_from": "Dovoli API dostop s teh IP naslovov / CIDR mrežnih zapisov", + "apps_name": "Ime aplikacije v mailcow", + "ban_list_info": "Oglejte si seznam blokiranih IP naslovov spodaj: network (remaining ban time) - [actions].
. IPji v vrsti za odstranitev blokade bodo odstranjeni iz aktivnega seznama blokad v nekaj sekundah.
Rdeče oznake prikazujejo trajne blokade z blacklisto.", + "dkim_key_length": "Dolžina DKIM ključa (v bitih)", + "dkim_to_title": "Ciljne domene bodo prepisane", + "f2b_list_info": "Gostitelj ali omrežje na blacklisti bo vedno prevladal zapis na whitelisti. Apliciranje sprememb seznama traja nekaj sekund.", + "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)", + "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.", + "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 z Blackliste 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", + "source": "Vir", + "spamfilter": "Spam filter", + "subject": "Predmet", + "success": "Uspešno", + "sys_mails": "Sistemska pošta", + "text": "Besedilo", + "time": "Čas", + "title": "Naziv", + "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\".", + "ui_footer": "Noga (HTML dovoljen)", + "ui_header_announcement": "Obvestila", + "ui_header_announcement_active": "Nastavi obvestilo kot aktivno", + "ui_header_announcement_content": "Besedilo (HTML dovoljen)", + "ui_header_announcement_help": "Obvestilo je vidno za vse prijavljene uporabnike in na vmesniku za prijavo.", + "ui_header_announcement_select": "Izberite vrsto obvestila", + "ui_header_announcement_type": "Vrsta", + "ui_header_announcement_type_danger": "Zelo pomembno", + "ui_header_announcement_type_info": "Info", + "ui_header_announcement_type_warning": "Pomembno", + "ui_texts": "Oznake in besedila UI", + "unban_pending": "unban v postopku", + "unchanged_if_empty": "Če je nespremenjeno, pustite prazno", + "upload": "Naloži", + "username": "Uporabniško ime", + "validate_license_now": "Potrdi GUID z licenčnim strežnikom", + "verify": "Preveri", + "yes": "✓" + }, + "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", + "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", + "global_map_write_error": "Ni mogoče zapisati ID globalne preslikave %s: %s", + "img_tmp_missing": "Ni mogoče preveriti slikovne datoteke: začasne datoteke ni mogoče najti", + "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", + "comment_too_long": "Komentar je predolg, dovoljeno je največ 100 znakov.", + "defquota_empty": "Privzeta kvota na poštni predal ne more biti 0", + "description_invalid": "Opis resursa za %s ni veljaven", + "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_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", + "filter_type": "Napačna vrsta filtra", + "from_invalid": "Pošiljatelj 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", + "ham_learn_error": "Napaka pri učenju Ham: %s", + "imagick_exception": "Napaka: Imagick napaka pri branju 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" + } +} diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 0a5c71b87..93545aa34 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -335,7 +335,17 @@ "transport_test_rcpt_info": "• Використовуйте null@hosted.mailcow.de для перевірки пересилання на зовнішній пункт призначення.", "transports_hint": "• Глобальні правила маршрутизації переважають над маршрутами на основі відправника.
\n• Переважно використовувати транспорти на основі резолвінгу MX.
\n• Користувацькі політики TLS для вихідної пошти будуть проігноровані та використовуватимуть політику TLS, налаштовану тут.
\n• Протокол для доставки завжди \"smtp:\" і тому намагатиметься використовувати TLS, якщо наступний хост підтримує його. SMTPS (TLS, найчастіше порту 465) не підтримується.
\n• Адреси відповідні \"/localhost$/\" завжди будуть доставлені \"local:\", отже політика \"*\" не поширюється на них.
\n• Щоб визначити облікові дані для наступного вузла \"[host]:25\", Postfix завжди шукає дані для \"host\" перед тим як шукати \"[host]:25\". Така поведінка унеможливлює використання \"host\" and \"[host]:25\" одночасно.", "ui_header_announcement_help": "Оголошення видно на екрані входу в mailcow UI і всім користувачам, що ввійшли в систему.", - "unchanged_if_empty": "Якщо не змінено, залиште порожнім" + "unchanged_if_empty": "Якщо не змінено, залиште порожнім", + "allowed_methods": "Access-Control-Allow-Methods", + "f2b_max_ban_time": "Максимальний час блокування (с)", + "f2b_ban_time_increment": "Час бану збільшується з кожним баном", + "allowed_origins": "Access-Control-Allow-Origin", + "cors_settings": "Налаштування CORS", + "ip_check": "Перевірка IP", + "ip_check_disabled": "Перевірка IP вимкнена. Ви можете ввімкнути його в меню
Система > Конфігурація > Параметри > Налаштувати", + "ip_check_opt_in": "Згода на використання сторонніх служб ipv4.mailcow.email і ipv6.mailcow.email для визначення зовнішніх IP-адрес.", + "options": "Параметри", + "queue_unban": "розблокувати" }, "danger": { "alias_domain_invalid": "Неприпустимий псевдонім домену: %s", @@ -454,7 +464,17 @@ "tls_policy_map_dest_invalid": "Неприпустиме значення призначення політики", "tls_policy_map_parameter_invalid": "Неприпустиме значення параметра політики", "unlimited_quota_acl": "Необмежена квота заборонена політикою доступу", - "yotp_verification_failed": "Помилка валідації Yubico OTP: %s" + "yotp_verification_failed": "Помилка валідації Yubico OTP: %s", + "cors_invalid_method": "Вказано недійсний Allow-Method", + "webauthn_authenticator_failed": "Обраний автентифікатор не знайдено", + "webauthn_publickey_failed": "Для вибраного автентифікатора не було збережено відкритого ключа", + "webauthn_username_failed": "Обраний автентифікатор належить іншому акаунту", + "cors_invalid_origin": "Вказано недійсний Allow-Origin", + "demo_mode_enabled": "Демонстраційний режим увімкнено", + "extended_sender_acl_denied": "відсутній ACL для встановлення зовнішніх адрес відправників", + "template_exists": "Шаблон %s вже існує", + "template_id_invalid": "Ідентифікатор шаблону %s недійсний", + "template_name_invalid": "Ім'я шаблону невірне" }, "debug": { "chart_this_server": "Діаграма (цей сервер)", @@ -481,7 +501,21 @@ "username": "Ім'я користувача", "external_logs": "Зовнішні журнали", "jvm_memory_solr": "Використання оперативної пам'яті JVM", - "log_info": "

Журнали контейнерів mailcow зберігаються в Redis, і раз на хвилину рядки журналу за межами LOG_LINES (%d) видаляються, щоб зменшити навантаження на сервер.\n
Самі журнали контейнерів не зберігаються після перезавантаження контейнера. Усі контейнери додатково пишуть логи у службу Docker, і, отже, використовують драйвер логування за промовчанням. Журнали контейнерів призначені лише для налагодження дрібних проблем. Для інших завдань, будь ласка, настройте драйвер логування Docker самостійно.

\n

Зовнішні журнали збираються через API програм.

\n

Статичні журнали – це в основному журнали активності, які не записуються в Dockerd, але все одно повинні бути постійними (за винятком журналів API).

" + "log_info": "

Журнали контейнерів mailcow зберігаються в Redis, і раз на хвилину рядки журналу за межами LOG_LINES (%d) видаляються, щоб зменшити навантаження на сервер.\n
Самі журнали контейнерів не зберігаються після перезавантаження контейнера. Усі контейнери додатково пишуть логи у службу Docker, і, отже, використовують драйвер логування за промовчанням. Журнали контейнерів призначені лише для налагодження дрібних проблем. Для інших завдань, будь ласка, настройте драйвер логування Docker самостійно.

\n

Зовнішні журнали збираються через API програм.

\n

Статичні журнали – це в основному журнали активності, які не записуються в Dockerd, але все одно повинні бути постійними (за винятком журналів API).

", + "error_show_ip": "Не вдалося розпізнати публічні IP-адреси", + "no_update_available": "Система працює на останній версії", + "architecture": "Архітектура", + "container_running": "Працює", + "container_disabled": "Контейнер зупинено або вимкнено", + "container_stopped": "Зупинено", + "cores": "Ядра", + "current_time": "Системний час", + "memory": "Пам'ять", + "show_ip": "Показати загальнодоступну IP-адресу", + "timezone": "Часовий пояс", + "update_available": "Доступне оновлення", + "update_failed": "Не вдалося перевірити наявність оновлень", + "wip": "Наразі робота триває" }, "diagnostics": { "cname_from_a": "Значення, отримане із запису A/AAAA. Це підтримується, поки запис вказує на правильний ресурс.", @@ -607,7 +641,8 @@ "sender_acl_info": "Врахуйте, що якщо користувачеві поштового облікового запису А дозволено відправляти від імені користувача Б, то адреса користувача Б не з'явиться автоматично у списку \"Відправник\" при написанні листів у SOGo.
\n Користувач поштового облікового запису Б повинен створити делегування в SOGo, щоб користувач поштового облікового запису А міг вибрати його адресу як відправника. Делегування знаходиться в меню (три крапки) праворуч від імені поштового облікового запису у вікні пошти SOGo. Ця поведінка не відноситься до псевдонімів.", "sogo_visible_info": "Впливає лише на об'єкти, які можуть відображатися в SOGo (персональні або загальні псевдоніми, що вказують щонайменше на один локальний поштовий обліковий запис). Зверніть увагу, що якщо функцію вимкнено, користувач не зможе вибрати адресу псевдоніма як відправника в SOGo.", "target_address": "Власники псевдоніма, (розділені комами)", - "timeout2": "Тайм-аут для підключення до локального хоста" + "timeout2": "Тайм-аут для підключення до локального хоста", + "pushover_sound": "Звук" }, "fido2": { "confirm": "Підтвердити", @@ -648,7 +683,8 @@ "restart_netfilter": "Перезапустити netfilter", "restart_sogo": "Перезапустити SOGo", "user_settings": "Налаштування користувача", - "mailcow_config": "Конфігурація" + "mailcow_config": "Конфігурація", + "mailcow_system": "Система" }, "info": { "no_action": "Дій не передбачено", @@ -831,7 +867,13 @@ "target_address": "Власники псевдоніму", "tls_map_dest_info": "Приклади: example.org, .example.org, [mail.example.org]:25", "tls_map_parameters_info": "Залиште поле порожнім або вкажіть параметри, наприклад: protocols=!SSLv2 ciphers=medium exclude=3DES", - "tls_policy_maps_enforced_tls": "Для вихідних повідомлень від користувачів із включеною примусовою політикою шифрування вихідних з'єднань не описані глобальною політикою, будуть застосовані значення за замовчуванням, зазначені в smtp_tls_mandatory_protocols та smtp_tls_mandatory_ciphers." + "tls_policy_maps_enforced_tls": "Для вихідних повідомлень від користувачів із включеною примусовою політикою шифрування вихідних з'єднань не описані глобальною політикою, будуть застосовані значення за замовчуванням, зазначені в smtp_tls_mandatory_protocols та smtp_tls_mandatory_ciphers.", + "add_template": "Додати шаблон", + "domain_templates": "Шаблони доменів", + "relay_unknown": "Ретрансляція невідомих поштових скриньок", + "mailbox_templates": "Шаблони поштових скриньок", + "templates": "Шаблони", + "template": "Шаблон" }, "oauth2": { "authorize_app": "Авторизація додатка", @@ -896,7 +938,20 @@ "table_size_show_n": "Відображати %s полів" }, "queue": { - "queue_manager": "Черга на відправлення" + "queue_manager": "Черга на відправлення", + "delete": "Видалити все", + "info": "Поштова черга містить усі електронні листи, які очікують на доставку. Якщо електронний лист застряг у черзі на тривалий час, він автоматично видаляється системою.
Повідомлення про помилку відповідного листа містить інформацію про те, чому лист не може бути доставлено.", + "unhold_mail": "Зняти утримування", + "unhold_mail_legend": "Звільняє вибрані листи для доставки. (Потрібне попереднє утримання)", + "flush": "Очистити чергу", + "legend": "Функції дій з поштовими чергами:", + "ays": "Підтвердьте, що ви хочете видалити всі елементи з поточної черги.", + "deliver_mail": "Доставити", + "deliver_mail_legend": "проби повторної доставки вибраних листів.", + "hold_mail": "Утримати", + "hold_mail_legend": "Утримує вибрані листи. (Запобігає подальшим спробам доставки)", + "show_message": "Показати повідомлення", + "unban": "розблокувати чергу" }, "ratelimit": { "disabled": "Вимкнено", @@ -988,7 +1043,12 @@ "settings_map_added": "Правило додано", "tls_policy_map_entry_deleted": "Політику TLS ID %s видалено", "verified_totp_login": "Авторизацію TOTP пройдено", - "domain_add_dkim_available": "Ключ DKIM вже існує" + "domain_add_dkim_available": "Ключ DKIM вже існує", + "template_added": "Додано шаблон %s", + "template_modified": "Зміни до шаблону %s збережено", + "cors_headers_edited": "Налаштування CORS збережено", + "ip_check_opt_in_modified": "Перевірка IP-адреси успішно збережено", + "template_removed": "Шаблону із ID %s видалено" }, "tfa": { "confirm": "Підтвердьте", @@ -1176,7 +1236,8 @@ "tag_help_explain": "Перемістити до підпапки: буде створено нову підпапку в INBOX з ім'ям тега, наприклад: \"INBOX/Facebook\".
\n Додати до теми листа: ім'я тега буде додано до теми листа, наприклад: \"[Facebook] My News\".", "tls_policy_warning": "Попередження: якщо ви увімкнете примусове шифрування пошти, ви можете зіткнутися з втратою листів.
Повідомлення, які не відповідають політиці, будуть відкидатися з повідомленням поштовим сервером про серйозний збій.
Цей параметр застосовується до вашої основної адреси електронної пошти (логіну), усім особистим псевдонімам та псевдонімам доменів. Маються на увазі лише псевдоніми з однією поштовою скринькою, як одержувач.", "year": "рік", - "years": "років" + "years": "років", + "pushover_sound": "Звук" }, "warning": { "domain_added_sogo_failed": "Домен був доданий, але перезавантажити SOGo не вдалося, будь ласка, перевірте журнали сервера.", @@ -1190,5 +1251,31 @@ "hash_not_found": "Хеш не знайдено або вже видалено", "ip_invalid": "Пропущено недійсний IP: %s", "is_not_primary_alias": "Пропущено неосновний псевдонім %s" + }, + "datatables": { + "decimal": ".", + "infoPostFix": "datatables.infoPostFix", + "zeroRecords": "Відповідних записів не знайдено", + "aria": { + "sortAscending": ": активувати для сортування стовпців за зростанням", + "sortDescending": ": активувати для сортування стовпців за спаданням" + }, + "emptyTable": "У таблиці немає даних", + "expand_all": "Розгорнути всі", + "info": "Показано від _START_ до _END_ of _TOTAL_ записів", + "infoEmpty": "Показано від 0 до 0 із 0 записів", + "infoFiltered": "(відфільтровано з _MAX_ всіх записів)", + "thousands": ",", + "lengthMenu": "Показати записи _MENU_", + "loadingRecords": "Завантаження...", + "processing": "Будь ласка, зачекайте...", + "search": "Пошук:", + "paginate": { + "first": "Перший", + "last": "Останній", + "next": "Наступний", + "previous": "Попередній" + }, + "collapse_all": "Згорнути все" } } From 718dcb69be97c39f33d1ccb69378f7d1894ccbbb Mon Sep 17 00:00:00 2001 From: AlexHuebi <39099705+AlexHuebi@users.noreply.github.com> Date: Sat, 2 Sep 2023 02:53:55 +0200 Subject: [PATCH 051/174] improved "FQDN" check --- update.sh | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/update.sh b/update.sh index 8c5a4fb5c..54ddcbc48 100755 --- a/update.sh +++ b/update.sh @@ -418,10 +418,23 @@ detect_docker_compose_command [[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing! Is mailcow installed?"; exit 1;} DOTS=${MAILCOW_HOSTNAME//[^.]}; -if [ ${#DOTS} -lt 2 ]; then +if [ ${#DOTS} -lt 1 ]; then echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!" echo "Please change it to a FQDN and run $COMPOSE_COMMAND down followed by $COMPOSE_COMMAND up -d" exit 1 +elif [[ "${MAILCOW_HOSTNAME: -1}" == "." ]]; then + echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is ending with a dot. This is not a valid FQDN!" + exit 1 +elif [ ${#DOTS} -eq 1 ]; then + echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) does not contain a Subdomain. This is not fully tested and may cause issues." + echo "Find more information about why this message exists here: https://github.com/mailcow/mailcow-dockerized/issues/1572" + read -r -p "Do you want to proceed anyway? [y/N] " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + echo "OK. Procceding." + else + echo "OK. Exiting." + exit 1 + fi fi if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox grep detected, please install gnu grep, \"apk add --no-cache --upgrade grep\""; exit 1; fi From 1e3766e2f113b440c566a20e2bfdf08c56470fed Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sat, 8 Apr 2023 15:03:49 +0200 Subject: [PATCH 052/174] [Web] revisited dark mode theme, enhanced colors Signed-off-by: Kristian Feldsam --- data/web/css/themes/mailcow-darkmode.css | 303 ++++++++++++++--------- 1 file changed, 180 insertions(+), 123 deletions(-) diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index abaa7499a..330169172 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -1,90 +1,123 @@ body { - background-color: #414141; - color: #e0e0e0; + background-color: #1c1c1e; + color: #f2f2f7; } .card { - border: 1px solid #1c1c1c; - background-color: #3a3a3a; + border: 1px solid #2c2c2e; + background-color: #2c2c2e; } + legend { - color: #f5f5f5; + color: #f2f2f7; } + .card-header { - color: #bbb; - background-color: #2c2c2c; + color: #8e8e93; + background-color: #1c1c1e; border-color: transparent; } + .btn-secondary, .paginate_button, .page-link, .btn-light { - color: #fff !important; - background-color: #7a7a7a !important; - border-color: #5c5c5c !important; + color: #f2f2f7 !important; + background-color: #5e5e5e !important; + border-color: #4c4c4e !important; } + .btn-dark { - color: #000 !important;; - background-color: #f6f6f6 !important;; - border-color: #ddd !important;; -} -.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { - border-color: #7a7a7a !important; -} -.alert-secondary { - color: #fff !important; - background-color: #7a7a7a !important; - border-color: #5c5c5c !important; -} -.bg-secondary { - color: #fff !important; - background-color: #7a7a7a !important; -} -.alert-secondary, .alert-secondary a, .alert-secondary .alert-link { - color: #fff; -} -.page-item.active .page-link { - background-color: #158cba !important; - border-color: #127ba3 !important; + color: #f2f2f7 !important; + background-color: #242424 !important; + border-color: #1c1c1e !important; } + .btn-secondary:focus, .btn-secondary:hover, .btn-group.open .dropdown-toggle.btn-secondary { - background-color: #7a7a7a; - border-color: #5c5c5c !important; - color: #fff; + background-color: #444444; + border-color: #4c4c4e !important; + color: #f2f2f7; } + +.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle { + border-color: #5e5e5e !important; +} + +.alert-secondary { + color: #f2f2f7 !important; + background-color: #5e5e5e !important; + border-color: #4c4c4e !important; +} + +.bg-secondary { + color: #f2f2f7 !important; + background-color: #5e5e5e !important; +} + +.alert-secondary, .alert-secondary a, .alert-secondary .alert-link { + color: #f2f2f7; +} + +.page-item.active .page-link { + background-color: #3e3e3e !important; + border-color: #3e3e3e !important; +} + +.btn-secondary:focus, .btn-secondary:hover, .btn-group.open .dropdown-toggle.btn-secondary { + background-color: #5e5e5e; + border-color: #4c4c4e !important; + color: #f2f2f7; +} + .btn-secondary:disabled, .btn-secondary.disabled { - border-color: #7a7a7a !important; + border-color: #5e5e5e !important; } + .modal-content { - background-color: #414141; + background-color: #1c1c1e; } + .modal-header { - border-bottom: 1px solid #161616; + border-bottom: 1px solid #2c2c2e; } + .modal-title { - color: white; + color: #f2f2f7; } + .modal .btn-close { filter: invert(1) grayscale(100%) brightness(200%); } + .navbar.bg-light { - background-color: #222222 !important; - border-color: #181818; + background-color: #1c1c1e !important; + border-color: #2c2c2e; } + .nav-link { - color: #ccc !important; + color: #8e8e93 !important; } + .nav-tabs .nav-link.active, .nav-tabs .nav-item.show .nav-link { background: none; } + +.nav-tabs, .nav-tabs .nav-link { + border-color: #444444 !important; +} + .nav-tabs .nav-link:not(.disabled):hover, .nav-tabs .nav-link:not(.disabled):focus, .nav-tabs .nav-link.active { - border-bottom-color: #414141; + border-bottom-color: #1c1c1e !important; +} + +.card .nav-tabs .nav-link:not(.disabled):hover, .card .nav-tabs .nav-link:not(.disabled):focus, .card .nav-tabs .nav-link.active { + border-bottom-color: #2c2c2e !important; } .table, .table-striped>tbody>tr:nth-of-type(odd)>*, tbody tr { - color: #ccc !important; + color: #f2f2f7 !important; } .dropdown-menu { - background-color: #585858; - border: 1px solid #333; + background-color: #424242; + border: 1px solid #282828; } .dropdown-menu>li>a:focus, .dropdown-menu>li>a:hover { color: #fafafa; @@ -97,7 +130,7 @@ legend { color: #d4d4d4 !important; } tbody tr { - color: #555; + color: #ccc; } .navbar-default .navbar-nav>.open>a, .navbar-default .navbar-nav>.open>a:focus, .navbar-default .navbar-nav>.open>a:hover { color: #ccc; @@ -106,18 +139,15 @@ tbody tr { color: #ccc; } .list-group-item { - background-color: #333; + background-color: #282828; border: 1px solid #555; } .table-striped>tbody>tr:nth-of-type(odd) { - background-color: #333; + background-color: #424242; } table.dataTable>tbody>tr.child ul.dtr-details>li { border-bottom: 1px solid rgba(255, 255, 255, 0.13); } -tbody tr { - color: #ccc; -} .label.label-last-login { color: #ccc !important; background-color: #555 !important; @@ -133,20 +163,20 @@ div.numberedtextarea-number { } .well { border: 1px solid #555; - background-color: #333; + background-color: #282828; } pre { color: #ccc; - background-color: #333; + background-color: #282828; border: 1px solid #555; } input.form-control, textarea.form-control { color: #e2e2e2 !important; - background-color: #555 !important; + background-color: #424242 !important; border: 1px solid #999; } input.form-control:focus, textarea.form-control { - background-color: #555 !important; + background-color: #424242 !important; } input.form-control:disabled, textarea.form-disabled { color: #a8a8a8 !important; @@ -154,16 +184,14 @@ input.form-control:disabled, textarea.form-disabled { } .input-group-addon { color: #ccc; - background-color: #555 !important; + background-color: #424242 !important; border: 1px solid #999; } .input-group-text { color: #ccc; - background-color: #242424; + background-color: #1c1c1c; } - - .list-group-item { color: #ccc; } @@ -175,11 +203,11 @@ input.form-control:disabled, textarea.form-disabled { } .dropdown-item.active:hover { color: #fff !important; - background-color: #31b1e4; + background-color: #007aff; } .form-select { color: #e2e2e2!important; - background-color: #555!important; + background-color: #424242!important; border: 1px solid #999; } @@ -191,31 +219,6 @@ input.form-control:disabled, textarea.form-disabled { color: #fff !important; } - -.table-secondary { - --bs-table-bg: #7a7a7a; - --bs-table-striped-bg: #e4e4e4; - --bs-table-striped-color: #000; - --bs-table-active-bg: #d8d8d8; - --bs-table-active-color: #000; - --bs-table-hover-bg: #dedede; - --bs-table-hover-color: #000; - color: #000; - border-color: #d8d8d8; -} - -.table-light { - --bs-table-bg: #f6f6f6; - --bs-table-striped-bg: #eaeaea; - --bs-table-striped-color: #000; - --bs-table-active-bg: #dddddd; - --bs-table-active-color: #000; - --bs-table-hover-bg: #e4e4e4; - --bs-table-hover-color: #000; - color: #000; - border-color: #dddddd; -} - .form-control-plaintext { color: #e0e0e0; } @@ -289,12 +292,12 @@ a:hover { } .tag-box { - background-color: #555; - border: 1px solid #999; + background-color: #282828; + border: 1px solid #555; } .tag-input { color: #fff; - background-color: #555; + background-color: #282828; } .tag-add { color: #ccc; @@ -303,43 +306,20 @@ a:hover { color: #d1d1d1; } - -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { - background-color: #7a7a7a !important; -} -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { - background-color: #7a7a7a !important; - border: 1.5px solid #5c5c5c !important; - color: #fff !important; -} -table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, -table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { - background-color: #949494; -} -table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { - background-color: #444444; -} - .btn-check-label { color: #fff; } .btn-outline-secondary:hover { - background-color: #c3c3c3; + background-color: #5c5c5c; } .btn.btn-outline-secondary { - color: #fff !important; + color: #e0e0e0 !important; border-color: #7a7a7a !important; } .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { - background-color: #9b9b9b !important; + background-color: #7a7a7a !important; } - - .btn-input-missing, .btn-input-missing:hover, .btn-input-missing:active, @@ -347,27 +327,104 @@ table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { .btn-input-missing:active:hover, .btn-input-missing:active:focus { color: #fff !important; - background-color: #ff2f24 !important; - border-color: #e21207 !important; + background-color: #ff3b30 !important; + border-color: #ff3b30 !important; } .inputMissingAttr { - border-color: #FF4136 !important; + border-color: #ff4136 !important; } - .list-group-details { - background: #444444; + background: #555; } .list-group-header { - background: #333; + background: #444; } span.mail-address-item { - background-color: #333; + background-color: #444; border-radius: 4px; border: 1px solid #555; padding: 2px 7px; display: inline-block; margin: 2px 6px 2px 0; } + +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before:hover, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before:hover { + background-color: #7a7a7a !important; +} + +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before { + background-color: #7a7a7a !important; + border: 1.5px solid #5c5c5c !important; + color: #e0e0e0 !important; +} + +table.dataTable.dtr-inline.collapsed>tbody>tr.parent>td.dtr-control:before, +table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before { + background-color: #949494; +} + +table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, +table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { + background-color: #414141; +} + +table.table, .table-striped>tbody>tr:nth-of-type(odd)>*, tbody tr { + color: #ccc !important; +} + +.table-secondary { + --bs-table-bg: #282828; + --bs-table-striped-bg: #343434; + --bs-table-striped-color: #f2f2f7; + --bs-table-active-bg: #4c4c4c; + --bs-table-active-color: #f2f2f7; + --bs-table-hover-bg: #3a3a3a; + --bs-table-hover-color: #f2f2f7; + color: #ccc; + border-color: #3a3a3a; +} + +.table-light { + --bs-table-bg: #3a3a3a; + --bs-table-striped-bg: #444444; + --bs-table-striped-color: #f2f2f7; + --bs-table-active-bg: #5c5c5c; + --bs-table-active-color: #f2f2f7; + --bs-table-hover-bg: #4c4c4c; + --bs-table-hover-color: #f2f2f7; + color: #ccc; + border-color: #4c4c4c; +} + +.table-bordered { + border-color: #3a3a3a; +} + +.table-bordered th, +.table-bordered td { + border-color: #3a3a3a !important; +} + +.table-bordered thead th, +.table-bordered thead td { + border-bottom-width: 2px; +} + +.table-striped>tbody>tr:nth-of-type(odd)>td, +.table-striped>tbody>tr:nth-of-type(odd)>th { + background-color: #282828; +} + +.table-hover>tbody>tr:hover { + background-color: #343434; +} + +.table>:not(caption)>*>* { + border-color: #5c5c5c; +} \ No newline at end of file From 1822d56efb00822ce194c513edfa3665e0d0beea Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Fri, 1 Sep 2023 14:14:51 +0200 Subject: [PATCH 053/174] [Web] fixed new mailbox settings buttons styling Signed-off-by: Kristian Feldsam Fixed input with btn in input group styling Signed-off-by: Kristian Feldsam --- data/web/css/build/014-mailcow.css | 9 +++++++++ data/web/css/themes/mailcow-darkmode.css | 10 +++++++--- data/web/templates/edit/domain.twig | 8 ++------ data/web/templates/modals/mailbox.twig | 18 +++++++++--------- data/web/templates/user/Spamfilter.twig | 8 ++------ 5 files changed, 29 insertions(+), 24 deletions(-) diff --git a/data/web/css/build/014-mailcow.css b/data/web/css/build/014-mailcow.css index 374d484dc..86c02ac74 100644 --- a/data/web/css/build/014-mailcow.css +++ b/data/web/css/build/014-mailcow.css @@ -370,3 +370,12 @@ button[aria-expanded='true'] > .caret { .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { background-color: #f0f0f0 !important; } +.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle { + color: #fff; + background-color: #555; + border-color: #4d4d4d; +} +.btn-check:checked+.btn-light:focus, .btn-check:active+.btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show>.btn-light.dropdown-toggle:focus, +.btn-check:focus+.btn-light, .btn-light:focus { + box-shadow: none; +} \ No newline at end of file diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index 330169172..ccba786ba 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -71,11 +71,11 @@ legend { } .modal-content { - background-color: #1c1c1e; + background-color: #2c2c2e; } .modal-header { - border-bottom: 1px solid #2c2c2e; + border-bottom: 1px solid #999; } .modal-title { @@ -319,7 +319,11 @@ a:hover { .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { background-color: #7a7a7a !important; } - +.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle { + color: #f2f2f7 !important; + background-color: #242424 !important; + border-color: #1c1c1e !important; +} .btn-input-missing, .btn-input-missing:hover, .btn-input-missing:active, diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 0c424887d..700445dd6 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -166,9 +166,7 @@
- - - +
@@ -185,9 +183,7 @@
- - - +
diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 25185de0e..aa98074bd 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -78,16 +78,16 @@
- + - + - + - +

{{ lang.user.quarantine_notification_info }}

@@ -97,13 +97,13 @@
- + - + - +

{{ lang.user.quarantine_category_info }}

@@ -113,10 +113,10 @@
- + - +
diff --git a/data/web/templates/user/Spamfilter.twig b/data/web/templates/user/Spamfilter.twig index 144ead61c..280b90032 100644 --- a/data/web/templates/user/Spamfilter.twig +++ b/data/web/templates/user/Spamfilter.twig @@ -45,9 +45,7 @@
- - - +
@@ -69,9 +67,7 @@
- - - +
From 6d9805109aa83b53fff3f08a17d0bd9ad323d9d9 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Fri, 1 Sep 2023 18:10:34 +0200 Subject: [PATCH 054/174] [Web] styling enhancements Signed-off-by: Kristian Feldsam --- data/web/css/build/013-datatables.css | 5 ---- data/web/css/build/014-mailcow.css | 13 +++++++++- data/web/css/themes/mailcow-darkmode.css | 22 ++++++++++++++++- data/web/js/build/004-datatables.js | 2 +- data/web/templates/admin/tab-config-dkim.twig | 6 ++--- data/web/templates/admin/tab-config-f2b.twig | 18 +++++++------- .../templates/admin/tab-config-fwdhosts.twig | 2 +- data/web/templates/admin/tab-routing.twig | 2 +- data/web/templates/edit/mailbox.twig | 22 ++++++++--------- data/web/templates/mailbox/tab-domains.twig | 2 +- .../mailbox/tab-templates-domains.twig | 4 ++-- .../templates/mailbox/tab-templates-mbox.twig | 4 ++-- data/web/templates/modals/mailbox.twig | 18 +++++++------- .../web/templates/user/tab-user-settings.twig | 24 +++++++++---------- 14 files changed, 85 insertions(+), 59 deletions(-) diff --git a/data/web/css/build/013-datatables.css b/data/web/css/build/013-datatables.css index 13378460e..57e2b6d94 100644 --- a/data/web/css/build/013-datatables.css +++ b/data/web/css/build/013-datatables.css @@ -42,11 +42,6 @@ table.dataTable.dtr-inline.collapsed>tbody>tr.parent>th.dtr-control:before, table.dataTable td.dt-control:before { background-color: #979797 !important; } -table.dataTable.dtr-inline.collapsed>tbody>tr>td.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>th.child, -table.dataTable.dtr-inline.collapsed>tbody>tr>td.dataTables_empty { - background-color: #fbfbfb; -} table.dataTable.table-striped>tbody>tr>td { vertical-align: middle; } diff --git a/data/web/css/build/014-mailcow.css b/data/web/css/build/014-mailcow.css index 86c02ac74..edc6b3d78 100644 --- a/data/web/css/build/014-mailcow.css +++ b/data/web/css/build/014-mailcow.css @@ -357,6 +357,7 @@ button[aria-expanded='true'] > .caret { } .progress { + height: 16px; background-color: #d5d5d5; } @@ -370,12 +371,22 @@ button[aria-expanded='true'] > .caret { .btn-check:checked+.btn-outline-secondary, .btn-check:active+.btn-outline-secondary, .btn-outline-secondary:active, .btn-outline-secondary.active, .btn-outline-secondary.dropdown-toggle.show { background-color: #f0f0f0 !important; } -.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle { +.btn-check:checked+.btn-light, .btn-check:active+.btn-light, .btn-light:active, .btn-light.active, .show>.btn-light.dropdown-toggle { color: #fff; background-color: #555; + background-image: none; border-color: #4d4d4d; } .btn-check:checked+.btn-light:focus, .btn-check:active+.btn-light:focus, .btn-light:active:focus, .btn-light.active:focus, .show>.btn-light.dropdown-toggle:focus, .btn-check:focus+.btn-light, .btn-light:focus { box-shadow: none; +} +.btn-group>.btn:not(:last-of-type) { + border-top-right-radius: 0; + border-bottom-right-radius: 0; +} +.badge.bg-info > a, +.badge.bg-danger > a { + color: #fff !important; + text-decoration: none; } \ No newline at end of file diff --git a/data/web/css/themes/mailcow-darkmode.css b/data/web/css/themes/mailcow-darkmode.css index ccba786ba..ea95df970 100644 --- a/data/web/css/themes/mailcow-darkmode.css +++ b/data/web/css/themes/mailcow-darkmode.css @@ -18,6 +18,10 @@ legend { border-color: transparent; } +.card-body { + --bs-card-color: #bbb; +} + .btn-secondary, .paginate_button, .page-link, .btn-light { color: #f2f2f7 !important; background-color: #5e5e5e !important; @@ -71,6 +75,7 @@ legend { } .modal-content { + --bs-modal-color: #bbb; background-color: #2c2c2e; } @@ -79,7 +84,7 @@ legend { } .modal-title { - color: #f2f2f7; + color: #bbb; } .modal .btn-close { @@ -431,4 +436,19 @@ table.table, .table-striped>tbody>tr:nth-of-type(odd)>*, tbody tr { .table>:not(caption)>*>* { border-color: #5c5c5c; + --bs-table-color-state:#bbb; + --bs-table-bg: #3a3a3a; +} +.text-muted { + --bs-secondary-color: #8e8e93; +} +input::placeholder { + color: #8e8e93 !important; +} + +.form-select { + background-image: url("data:image/svg+xml,%3csvg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 16 16'%3e%3cpath fill='none' stroke='%238e8e93' stroke-linecap='round' stroke-linejoin='round' stroke-width='2' d='m2 5 6 6 6-6'/%3e%3c/svg%3e"); +} +.btn-light, .btn-light:hover { + background-image: none; } \ No newline at end of file diff --git a/data/web/js/build/004-datatables.js b/data/web/js/build/004-datatables.js index 9ece8ea57..8c791713f 100644 --- a/data/web/js/build/004-datatables.js +++ b/data/web/js/build/004-datatables.js @@ -15801,7 +15801,7 @@ DataTable.ext.renderer.pageButton.bootstrap = function ( settings, host, idx, bu paginationEl.empty(); } else { - paginationEl = hostEl.html('
    ').children('ul').addClass('pagination'); + paginationEl = hostEl.html('
      ').children('ul').addClass('pagination pagination-sm'); } attach( diff --git a/data/web/templates/admin/tab-config-dkim.twig b/data/web/templates/admin/tab-config-dkim.twig index 96dccc66c..857bfba29 100644 --- a/data/web/templates/admin/tab-config-dkim.twig +++ b/data/web/templates/admin/tab-config-dkim.twig @@ -114,7 +114,7 @@
- @@ -159,7 +159,7 @@
- diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index 4336591ad..de4a7c63b 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -92,28 +92,28 @@ {% endif %} {% for active_ban in f2b_data.active_bans %}

- + - + {{ active_ban.network }} - ({{ active_ban.banned_until }}) - + ({{ active_ban.banned_until }}) + - {% if active_ban.queued_for_unban == 0 %} - [{{ lang.admin.queue_unban }}] - [whitelist] - [blacklist (needs restart)] + [{{ lang.admin.queue_unban }}] + [whitelist] + [blacklist (needs restart)] {% else %} {{ lang.admin.unban_pending }} {% endif %} -

{% endfor %}
{% for perm_ban in f2b_data.perm_bans %}

- + - + {{ perm_ban.network }} diff --git a/data/web/templates/admin/tab-config-fwdhosts.twig b/data/web/templates/admin/tab-config-fwdhosts.twig index 31de20364..d3efddd8d 100644 --- a/data/web/templates/admin/tab-config-fwdhosts.twig +++ b/data/web/templates/admin/tab-config-fwdhosts.twig @@ -9,7 +9,7 @@

{{ lang.admin.forwarding_hosts_hint }}

-
+
{{ lang.mailbox.quick_actions }} diff --git a/data/web/templates/admin/tab-routing.twig b/data/web/templates/admin/tab-routing.twig index 5eca7eb10..c6e59601d 100644 --- a/data/web/templates/admin/tab-routing.twig +++ b/data/web/templates/admin/tab-routing.twig @@ -55,7 +55,7 @@

{{ lang.admin.transports_hint|raw }}

-
+
{{ lang.mailbox.quick_actions }} diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index f8cde7da6..c08ff74f6 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -109,25 +109,25 @@
- - - - - - -
-
+
@@ -252,7 +252,7 @@
{% endif %} -
+
diff --git a/data/web/templates/mailbox/tab-domains.twig b/data/web/templates/mailbox/tab-domains.twig index a30438d1a..8b2d61b7d 100644 --- a/data/web/templates/mailbox/tab-domains.twig +++ b/data/web/templates/mailbox/tab-domains.twig @@ -28,7 +28,7 @@
  • {{ lang.datatables.collapse_all }}
  • {% if mailcow_cc_role == 'admin' %} - {{ lang.mailbox.add_domain }} + {% endif %}
    diff --git a/data/web/templates/mailbox/tab-templates-domains.twig b/data/web/templates/mailbox/tab-templates-domains.twig index 64e72ce46..c339aaf01 100644 --- a/data/web/templates/mailbox/tab-templates-domains.twig +++ b/data/web/templates/mailbox/tab-templates-domains.twig @@ -24,7 +24,7 @@ {% endif %} {% if mailcow_cc_role == 'admin' %} - {{ lang.mailbox.add_template }} + {% endif %}
    @@ -42,7 +42,7 @@ {% endif %} {% if mailcow_cc_role == 'admin' %} - {{ lang.mailbox.add_template }} + {% endif %}
    diff --git a/data/web/templates/mailbox/tab-templates-mbox.twig b/data/web/templates/mailbox/tab-templates-mbox.twig index f71eb7fd0..631394bb9 100644 --- a/data/web/templates/mailbox/tab-templates-mbox.twig +++ b/data/web/templates/mailbox/tab-templates-mbox.twig @@ -24,7 +24,7 @@ {% endif %} {% if mailcow_cc_role == 'admin' %} - {{ lang.mailbox.add_template }} + {% endif %}
    @@ -42,7 +42,7 @@ {% endif %} {% if mailcow_cc_role == 'admin' %} - {{ lang.mailbox.add_template }} + {% endif %}
    diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index aa98074bd..44ba149fd 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -248,16 +248,16 @@
    - + - + - + - +

    {{ lang.user.quarantine_notification_info }}

    @@ -267,13 +267,13 @@
    - + - + - +

    {{ lang.user.quarantine_category_info }}

    @@ -283,10 +283,10 @@
    - + - +
    diff --git a/data/web/templates/user/tab-user-settings.twig b/data/web/templates/user/tab-user-settings.twig index 3a2ee5ff7..3fe0db33f 100644 --- a/data/web/templates/user/tab-user-settings.twig +++ b/data/web/templates/user/tab-user-settings.twig @@ -12,19 +12,19 @@
    {{ lang.user.tag_handling }}:
    - - -
    - -
    - - - -
    - - -
    '; - item.chkbox = ''; + item.chkbox = ''; }); } else if (table == 'queuetable') { $.each(data, function (i, item) { - item.chkbox = ''; + item.chkbox = ''; rcpts = $.map(item.recipients, function(i) { return escapeHtml(i); }); @@ -550,7 +550,7 @@ jQuery(function($){ item.action = ''; - item.chkbox = ''; + item.chkbox = ''; }); } else if (table == 'oauth2clientstable') { $.each(data, function (i, item) { @@ -560,13 +560,13 @@ jQuery(function($){ '
    '; item.scope = "profile"; item.grant_types = 'refresh_token password authorization_code'; - item.chkbox = ''; + item.chkbox = ''; }); } else if (table == 'domainadminstable') { $.each(data, function (i, item) { item.selected_domains = escapeHtml(item.selected_domains); item.selected_domains = item.selected_domains.toString().replace(/,/g, "
    "); - item.chkbox = ''; + item.chkbox = ''; item.action = '
    ' + ' ' + lang.edit + '' + ' ' + lang.remove + '' + @@ -580,7 +580,7 @@ jQuery(function($){ } else { item.usr = item.username; } - item.chkbox = ''; + item.chkbox = ''; item.action = '
    ' + ' ' + lang.edit + '' + ' ' + lang.remove + '' + diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js index 4680bdfaf..cd938cd84 100644 --- a/data/web/js/site/edit.js +++ b/data/web/js/site/edit.js @@ -93,10 +93,10 @@ jQuery(function($){ dataSrc: function(data){ $.each(data, function (i, item) { if (!validateEmail(item.object)) { - item.chkbox = ''; + item.chkbox = ''; } else { - item.chkbox = ''; + item.chkbox = ''; } }); @@ -154,10 +154,10 @@ jQuery(function($){ dataSrc: function(data){ $.each(data, function (i, item) { if (!validateEmail(item.object)) { - item.chkbox = ''; + item.chkbox = ''; } else { - item.chkbox = ''; + item.chkbox = ''; } }); diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 3ddeea944..50ce59df1 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -466,7 +466,7 @@ jQuery(function($){ item.def_quota_for_mbox = humanFileSize(item.def_quota_for_mbox); item.max_quota_for_mbox = humanFileSize(item.max_quota_for_mbox); - item.chkbox = ''; + item.chkbox = ''; item.action = '
    '; if (role == "admin") { item.action += ' ' + lang.edit + '' + @@ -650,7 +650,7 @@ jQuery(function($){ url: "/api/v1/get/domain/template/all", dataSrc: function(json){ $.each(json, function (i, item) { - item.chkbox = ''; + item.chkbox = ''; item.attributes.def_quota_for_mbox = humanFileSize(item.attributes.def_quota_for_mbox); item.attributes.max_quota_for_mbox = humanFileSize(item.attributes.max_quota_for_mbox); @@ -880,7 +880,7 @@ jQuery(function($){ } } */ - item.chkbox = ''; + item.chkbox = ''; if (item.attributes.passwd_update != '0') { var last_pw_change = new Date(item.attributes.passwd_update.replace(/-/g, "/")); item.last_pw_change = last_pw_change.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}); @@ -1148,7 +1148,7 @@ jQuery(function($){ url: "/api/v1/get/mailbox/template/all", dataSrc: function(json){ $.each(json, function (i, item) { - item.chkbox = ''; + item.chkbox = ''; item.template = escapeHtml(item.template); if (item.attributes.rl_frame === "s"){ @@ -1381,7 +1381,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; item.name = escapeHtml(item.name); item.description = escapeHtml(item.description); }); @@ -1521,7 +1521,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; item.local_dest = escapeHtml(item.local_dest); item.bcc_dest = escapeHtml(item.bcc_dest); if (item.type == 'sender') { @@ -1635,7 +1635,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; }); return json; @@ -1737,7 +1737,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; }); return json; @@ -1835,7 +1835,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; item.goto = escapeHtml(item.goto.replace(/,/g, " ")); if (item.public_comment !== null) { item.public_comment = escapeHtml(item.public_comment); @@ -1958,7 +1958,7 @@ jQuery(function($){ table.on('responsive-resize', function (e, datatable, columns){ hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); }); - + table.on( 'draw', function (){ $('#alias_table [data-bs-toggle="tooltip"]').tooltip(); }); @@ -1995,7 +1995,7 @@ jQuery(function($){ ' ' + lang.remove + '' + ' DNS
    ' + '
    '; - item.chkbox = ''; + item.chkbox = ''; if(item.parent_is_backupmx == '1') { item.target_domain = '' + item.target_domain + '
    ' + lang.alias_domain_backupmx + '
    '; } else { @@ -2096,7 +2096,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; if (item.is_running == 1) { item.is_running = '' + lang.running + ''; } else { @@ -2250,7 +2250,7 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = '' + item.chkbox = '' }); return json; @@ -2344,7 +2344,7 @@ jQuery(function($){ } }); }) - + observer.observe(element_object); }); } diff --git a/data/web/js/site/quarantine.js b/data/web/js/site/quarantine.js index 18d7a1d5d..8d7f22255 100644 --- a/data/web/js/site/quarantine.js +++ b/data/web/js/site/quarantine.js @@ -77,7 +77,7 @@ jQuery(function($){ ' ' + lang.show_item + '' + '
    '; } - item.chkbox = ''; + item.chkbox = ''; }); return data; diff --git a/data/web/js/site/queue.js b/data/web/js/site/queue.js index f37884a6f..26c15091d 100644 --- a/data/web/js/site/queue.js +++ b/data/web/js/site/queue.js @@ -48,7 +48,7 @@ jQuery(function($){ url: "/api/v1/get/mailq/all", dataSrc: function(data){ $.each(data, function (i, item) { - item.chkbox = ''; + item.chkbox = ''; rcpts = $.map(item.recipients, function(i) { return escapeHtml(i); }); diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js index 2227e0b05..088321cd3 100644 --- a/data/web/js/site/user.js +++ b/data/web/js/site/user.js @@ -127,7 +127,7 @@ jQuery(function($){ } } - + function createSortableDate(td, cellData, date_string = false) { if (date_string) var date = new Date(cellData); @@ -169,11 +169,11 @@ jQuery(function($){ item.action = ''; - item.chkbox = ''; + item.chkbox = ''; item.address = escapeHtml(item.address); } else { - item.chkbox = ''; + item.chkbox = ''; item.action = '-'; } }); @@ -263,11 +263,11 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; } else { item.action = '-'; - item.chkbox = ''; + item.chkbox = ''; } if (item.is_running == 1) { item.is_running = '' + lang.running + ''; @@ -420,11 +420,11 @@ jQuery(function($){ ' ' + lang.edit + '' + ' ' + lang.remove + '' + '
    '; - item.chkbox = ''; + item.chkbox = ''; } else { item.action = '-'; - item.chkbox = ''; + item.chkbox = ''; } }); @@ -503,13 +503,13 @@ jQuery(function($){ console.log(data); $.each(data, function (i, item) { if (validateEmail(item.object)) { - item.chkbox = ''; + item.chkbox = ''; } else { - item.chkbox = ''; + item.chkbox = ''; } if (acl_data.spam_policy === 0) { - item.chkbox = ''; + item.chkbox = ''; } }); @@ -574,13 +574,13 @@ jQuery(function($){ console.log(data); $.each(data, function (i, item) { if (validateEmail(item.object)) { - item.chkbox = ''; + item.chkbox = ''; } else { - item.chkbox = ''; + item.chkbox = ''; } if (acl_data.spam_policy === 0) { - item.chkbox = ''; + item.chkbox = ''; } }); diff --git a/data/web/templates/admin/tab-config-admins.twig b/data/web/templates/admin/tab-config-admins.twig index f33067f60..b672b8159 100644 --- a/data/web/templates/admin/tab-config-admins.twig +++ b/data/web/templates/admin/tab-config-admins.twig @@ -146,7 +146,7 @@
    @@ -159,7 +159,7 @@
    @@ -191,7 +191,7 @@
    @@ -204,7 +204,7 @@
    diff --git a/data/web/templates/admin/tab-config-customize.twig b/data/web/templates/admin/tab-config-customize.twig index e458eeb3b..88d1c6643 100644 --- a/data/web/templates/admin/tab-config-customize.twig +++ b/data/web/templates/admin/tab-config-customize.twig @@ -111,7 +111,7 @@

    -
    +
    diff --git a/data/web/templates/admin/tab-config-dkim.twig b/data/web/templates/admin/tab-config-dkim.twig index 857bfba29..85c6dc6ae 100644 --- a/data/web/templates/admin/tab-config-dkim.twig +++ b/data/web/templates/admin/tab-config-dkim.twig @@ -20,7 +20,7 @@ {% for domain, domain_data in dkim_domains %} {% if domain_data.dkim %}
    -
    +

    {{ lang.admin.domain }}: {{ domain }}

    {{ lang.admin.dkim_key_valid }}

    @@ -31,7 +31,7 @@
    - + {{ lang.admin.dkim_private_key }}
    @@ -50,7 +50,7 @@ {% for alias_domain, alias_domain_data in domain_data.alias_domains %} {% if alias_domain_data.dkim %}
    -
    +

    ↳ Alias-Domain: {{ alias_domain }}

    {{ lang.admin.dkim_key_valid }}

    @@ -78,7 +78,7 @@ {% endfor %} {% for blind, data in dkim_blind_domains|filter(data => data.dkim is not null) %}
    -
    +

    {{ lang.admin.domain }}: {{ blind }}

    {{ lang.admin.dkim_key_unused }}

    @@ -143,7 +143,7 @@
    diff --git a/data/web/templates/admin/tab-config-password-policy.twig b/data/web/templates/admin/tab-config-password-policy.twig index dd77f3a3e..8209ba542 100644 --- a/data/web/templates/admin/tab-config-password-policy.twig +++ b/data/web/templates/admin/tab-config-password-policy.twig @@ -21,7 +21,7 @@
    diff --git a/data/web/templates/admin/tab-config-rsettings.twig b/data/web/templates/admin/tab-config-rsettings.twig index bf5296329..38b0d593d 100644 --- a/data/web/templates/admin/tab-config-rsettings.twig +++ b/data/web/templates/admin/tab-config-rsettings.twig @@ -57,7 +57,7 @@
    diff --git a/data/web/templates/admin/tab-globalfilter-regex.twig b/data/web/templates/admin/tab-globalfilter-regex.twig index 086ce533f..386cffc1c 100644 --- a/data/web/templates/admin/tab-globalfilter-regex.twig +++ b/data/web/templates/admin/tab-globalfilter-regex.twig @@ -12,7 +12,7 @@
    diff --git a/data/web/templates/admin/tab-routing.twig b/data/web/templates/admin/tab-routing.twig index c6e59601d..07d979557 100644 --- a/data/web/templates/admin/tab-routing.twig +++ b/data/web/templates/admin/tab-routing.twig @@ -90,12 +90,12 @@

    {{ lang.admin.credentials_transport_warning|raw }}

    diff --git a/data/web/templates/admin/tab-sys-mails.twig b/data/web/templates/admin/tab-sys-mails.twig index 1b842ff88..105151f7a 100644 --- a/data/web/templates/admin/tab-sys-mails.twig +++ b/data/web/templates/admin/tab-sys-mails.twig @@ -60,7 +60,7 @@
    diff --git a/data/web/templates/edit/admin.twig b/data/web/templates/edit/admin.twig index 8806b068f..e2c6f66ed 100644 --- a/data/web/templates/edit/admin.twig +++ b/data/web/templates/edit/admin.twig @@ -27,15 +27,15 @@
    -
    - +
    +
    -
    - +
    +
    diff --git a/data/web/templates/edit/alias.twig b/data/web/templates/edit/alias.twig index 83a3760c5..48d19617b 100644 --- a/data/web/templates/edit/alias.twig +++ b/data/web/templates/edit/alias.twig @@ -19,19 +19,19 @@
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    {% if not skip_sogo %}
    -
    - +
    +

    {{ lang.edit.sogo_visible_info }}

    {% endif %} @@ -53,8 +53,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/aliasdomain.twig b/data/web/templates/edit/aliasdomain.twig index 808d128e9..e2ecd4875 100644 --- a/data/web/templates/edit/aliasdomain.twig +++ b/data/web/templates/edit/aliasdomain.twig @@ -17,8 +17,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/app-passwd.twig b/data/web/templates/edit/app-passwd.twig index fcd9d049c..46dc648db 100644 --- a/data/web/templates/edit/app-passwd.twig +++ b/data/web/templates/edit/app-passwd.twig @@ -26,8 +26,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/bcc.twig b/data/web/templates/edit/bcc.twig index f7d0c5ca7..fb7a538a2 100644 --- a/data/web/templates/edit/bcc.twig +++ b/data/web/templates/edit/bcc.twig @@ -24,8 +24,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/domain-templates.twig b/data/web/templates/edit/domain-templates.twig index 5a0cbb695..c58693b23 100644 --- a/data/web/templates/edit/domain-templates.twig +++ b/data/web/templates/edit/domain-templates.twig @@ -64,16 +64,16 @@
    -
    - +
    + {{ lang.edit.gal_info|raw }}
    -
    - +
    +
    @@ -111,12 +111,12 @@
    -
    - +
    +
    - +

    {{ lang.edit.relay_all_info|raw }}

    - +

    {{ lang.edit.relay_transport_info|raw }}

    diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 700445dd6..4ba25cf70 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -29,7 +29,7 @@
    {% for tag in domain_details.tags %} - + {{ tag }} {% endfor %} @@ -91,12 +91,12 @@
    -
    - +
    +
    - +

    {{ lang.edit.relay_all_info|raw }}

    - +

    {{ lang.edit.relay_transport_info|raw }}


    @@ -106,8 +106,8 @@ {% endif %}
    -
    - +
    + {{ lang.edit.gal_info|raw }}
    @@ -115,8 +115,8 @@
    -
    - +
    +
    @@ -211,8 +211,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/domainadmin.twig b/data/web/templates/edit/domainadmin.twig index d241fa535..2c40faaa3 100644 --- a/data/web/templates/edit/domainadmin.twig +++ b/data/web/templates/edit/domainadmin.twig @@ -40,15 +40,15 @@
    -
    - +
    +
    -
    - +
    +
    diff --git a/data/web/templates/edit/filter.twig b/data/web/templates/edit/filter.twig index ff4ac4ee7..124ecaf7b 100644 --- a/data/web/templates/edit/filter.twig +++ b/data/web/templates/edit/filter.twig @@ -28,8 +28,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig index fea99bdd2..28f45b569 100644 --- a/data/web/templates/edit/mailbox-templates.twig +++ b/data/web/templates/edit/mailbox-templates.twig @@ -9,8 +9,8 @@ - - + +
    @@ -61,10 +61,10 @@
    - + - +
    @@ -77,7 +77,7 @@
    - +
    @@ -97,7 +97,7 @@
    - @@ -140,8 +140,8 @@
    -
    - +
    + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}
    @@ -149,8 +149,8 @@ {% if not skip_sogo %}
    -
    - +
    + {{ lang.edit.sogo_access_info }}
    diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index c08ff74f6..c020cb0ac 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -28,7 +28,7 @@
    {% for tag in mailbox_details.tags %} - + {{ tag }} {% endfor %} @@ -236,8 +236,8 @@
    -
    - +
    + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}
    @@ -245,8 +245,8 @@ {% if not skip_sogo %}
    -
    - +
    + {{ lang.edit.sogo_access_info }}
    @@ -329,8 +329,8 @@
    -
    - +
    +
    @@ -343,11 +343,11 @@
    -
    - +
    +
    -
    - +
    +
    diff --git a/data/web/templates/edit/recipient_map.twig b/data/web/templates/edit/recipient_map.twig index 9af30a3b9..c7f3493c8 100644 --- a/data/web/templates/edit/recipient_map.twig +++ b/data/web/templates/edit/recipient_map.twig @@ -22,8 +22,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/relayhost.twig b/data/web/templates/edit/relayhost.twig index c66898168..31871707f 100644 --- a/data/web/templates/edit/relayhost.twig +++ b/data/web/templates/edit/relayhost.twig @@ -26,8 +26,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/resource.twig b/data/web/templates/edit/resource.twig index 4ba65bd26..7fdc556e6 100644 --- a/data/web/templates/edit/resource.twig +++ b/data/web/templates/edit/resource.twig @@ -38,8 +38,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/syncjob.twig b/data/web/templates/edit/syncjob.twig index d2172e647..40ae00fc2 100644 --- a/data/web/templates/edit/syncjob.twig +++ b/data/web/templates/edit/syncjob.twig @@ -101,50 +101,50 @@
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    diff --git a/data/web/templates/edit/tls_policy_map.twig b/data/web/templates/edit/tls_policy_map.twig index 199bbfef4..aa89575b8 100644 --- a/data/web/templates/edit/tls_policy_map.twig +++ b/data/web/templates/edit/tls_policy_map.twig @@ -32,8 +32,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/edit/transport.twig b/data/web/templates/edit/transport.twig index 2fc461f6f..4aedb53dd 100644 --- a/data/web/templates/edit/transport.twig +++ b/data/web/templates/edit/transport.twig @@ -32,15 +32,15 @@
    -
    - +
    +
    -
    - +
    +
    diff --git a/data/web/templates/modals/admin.twig b/data/web/templates/modals/admin.twig index 15971e593..2271ca7f5 100644 --- a/data/web/templates/modals/admin.twig +++ b/data/web/templates/modals/admin.twig @@ -22,8 +22,8 @@
    -
    - +
    +
    @@ -81,8 +81,8 @@
    -
    - +
    +
    @@ -181,8 +181,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 44ba149fd..e59d630ae 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -98,10 +98,10 @@
    - + - +
    @@ -114,7 +114,7 @@
    - +
    @@ -176,8 +176,8 @@
    -
    - +
    + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}
    @@ -185,8 +185,8 @@ {% if not skip_sogo %}
    -
    - +
    + {{ lang.edit.sogo_access_info }}
    @@ -216,7 +216,7 @@ - +
    @@ -268,10 +268,10 @@
    - + - +
    @@ -284,7 +284,7 @@
    - +
    @@ -304,7 +304,7 @@
    - @@ -347,8 +347,8 @@
    -
    - +
    + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }}
    @@ -356,8 +356,8 @@ {% if not skip_sogo %}
    -
    - +
    + {{ lang.edit.sogo_access_info }}
    @@ -445,8 +445,8 @@ {% if not skip_sogo %}
    -
    - +
    + {{ lang.edit.gal_info|raw }}
    @@ -454,8 +454,8 @@ {% endif %}
    -
    - +
    +
    @@ -491,12 +491,12 @@
    -
    - +
    +
    - +

    {{ lang.add.relay_all_info|raw }}

    - +

    {{ lang.add.relay_transport_info|raw }}

    @@ -584,16 +584,16 @@
    -
    - +
    + {{ lang.add.gal_info|raw }}
    -
    - +
    +
    @@ -633,12 +633,12 @@
    -
    - +
    +
    - +

    {{ lang.edit.relay_all_info|raw }}

    - +

    {{ lang.edit.relay_transport_info|raw }}

    @@ -708,8 +708,8 @@
    -
    - +
    +
    @@ -746,19 +746,19 @@

    {{ lang.add.target_address_info|raw }}

    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    {% if not skip_sogo %}
    -
    - +
    +

    {{ lang.edit.sogo_visible_info }}

    {% endif %} @@ -766,8 +766,8 @@
    -
    - +
    +
    @@ -811,8 +811,8 @@
    -
    - +
    +
    @@ -967,50 +967,50 @@
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    @@ -1068,8 +1068,8 @@
    -
    - +
    +
    @@ -1121,8 +1121,8 @@
    -
    - +
    +
    @@ -1162,8 +1162,8 @@
    -
    - +
    +
    @@ -1218,8 +1218,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/modals/user.twig b/data/web/templates/modals/user.twig index 8c96397f6..96605f709 100644 --- a/data/web/templates/modals/user.twig +++ b/data/web/templates/modals/user.twig @@ -127,50 +127,50 @@
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    -
    - +
    +
    @@ -228,8 +228,8 @@
    -
    - +
    +
    diff --git a/data/web/templates/user/Pushover.twig b/data/web/templates/user/Pushover.twig index 61c91ea6a..acc019cab 100644 --- a/data/web/templates/user/Pushover.twig +++ b/data/web/templates/user/Pushover.twig @@ -80,8 +80,8 @@
    -
    - +
    +
    @@ -95,11 +95,11 @@
    -
    - +
    +
    -
    - +
    +
    From 25d6e0bbd08d5c7539ad1064e7d03c5a1c6b48a2 Mon Sep 17 00:00:00 2001 From: Mirko Ceroni Date: Sat, 2 Sep 2023 11:34:29 +0200 Subject: [PATCH 056/174] enable search in bodies from EAS enable search in bodies from EAS --- data/conf/sogo/sogo.conf | 1 + 1 file changed, 1 insertion(+) diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf index 2c042c300..d12333a8b 100644 --- a/data/conf/sogo/sogo.conf +++ b/data/conf/sogo/sogo.conf @@ -83,6 +83,7 @@ //SoDebugBaseURL = YES; //ImapDebugEnabled = YES; //SOGoEASDebugEnabled = YES; + SOGoEASSearchInBody = YES //LDAPDebugEnabled = YES; //PGDebugEnabled = YES; //MySQL4DebugEnabled = YES; From 1a207f4d880c8e0669f6148ef038fe24c84950e5 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 00:18:11 +0200 Subject: [PATCH 057/174] [Web] translated datatables to CZ and SK Signed-off-by: Kristian Feldsam --- data/web/lang/lang.cs-cz.json | 23 +++++++++++++++++++++++ data/web/lang/lang.sk-sk.json | 24 ++++++++++++++++++++++++ 2 files changed, 47 insertions(+) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index d4f624959..b709de5ec 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -459,6 +459,29 @@ "value_missing": "Prosím, uveďte všechny hodnoty", "yotp_verification_failed": "Yubico OTP ověření selhalo: %s" }, + "datatables": { + "emptyTable": "Tabulka neobsahuje žádná data", + "info": "Zobrazuji _START_ až _END_ z celkem _TOTAL_ záznamů", + "infoEmpty": "Zobrazuji 0 až 0 z 0 záznamů", + "infoFiltered": "(filtrováno z celkem _MAX_ záznamů)", + "loadingRecords": "Načítám...", + "zeroRecords": "Žádné záznamy nebyly nalezeny", + "paginate": { + "first": "První", + "last": "Poslední", + "next": "Další", + "previous": "Předchozí" + }, + "aria": { + "sortAscending": ": aktivujte pro seřazení vzestupně", + "sortDescending": ": aktivujte pro seřazení sestupně" + }, + "lengthMenu": "Zobrazit _MENU_ výsledků", + "processing": "Zpracovávání...", + "search": "Vyhledávání:", + "decimal": ",", + "thousands": " " + }, "debug": { "chart_this_server": "Graf (tento server)", "containers_info": "Informace o kontejnerech", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 29b36c44e..276d7b9e4 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -456,6 +456,30 @@ "value_missing": "Prosím poskytnite všetky hodnoty", "yotp_verification_failed": "Overenie cez OTP Yubico zlyhalo: %s" }, + "datatables": { + "info": "Záznamy _START_ až _END_ z celkom _TOTAL_", + "infoEmpty": "Záznamy 0 až 0 z celkom 0 ", + "infoFiltered": "(vyfiltrované spomedzi _MAX_ záznamov)", + "infoThousands": " ", + "lengthMenu": "Zobraz _MENU_ záznamov", + "loadingRecords": "Načítavam...", + "processing": "Spracúvam...", + "search": "Hľadať:", + "zeroRecords": "Nenašli sa žiadne vyhovujúce záznamy", + "paginate": { + "first": "Prvá", + "last": "Posledná", + "next": "Nasledujúca", + "previous": "Predchádzajúca" + }, + "aria": { + "sortAscending": ": aktivujte na zoradenie stĺpca vzostupne", + "sortDescending": ": aktivujte na zoradenie stĺpca zostupne" + }, + "emptyTable": "Nie sú k dispozícii žiadne dáta.", + "decimal": ",", + "thousands": " " + }, "debug": { "chart_this_server": "Graf (tento server)", "containers_info": "Informácie o kontajneroch", From e4e8abb1b9f04b6852d2b64e8ae99476d27ee11a Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:31:59 +0200 Subject: [PATCH 058/174] [Web] Ratelimit settings as input group Signed-off-by: Kristian Feldsam --- data/web/edit.php | 12 +-- data/web/templates/edit/aliasdomain.twig | 4 +- data/web/templates/edit/domain-templates.twig | 13 ++-- data/web/templates/edit/domain.twig | 20 +++-- .../web/templates/edit/mailbox-templates.twig | 9 +-- data/web/templates/edit/mailbox.twig | 20 +++-- data/web/templates/modals/mailbox.twig | 73 +++++++++---------- 7 files changed, 80 insertions(+), 71 deletions(-) diff --git a/data/web/edit.php b/data/web/edit.php index 09db796d3..55bc050d9 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -59,20 +59,22 @@ if (isset($_SESSION['mailcow_cc_role'])) { ]; } } - elseif (isset($_GET["template"])){ - $domain_template = mailbox('get', 'domain_templates', $_GET["template"]); + elseif (isset($_GET['template'])){ + $domain_template = mailbox('get', 'domain_templates', $_GET['template']); if ($domain_template){ $template_data = [ - 'template' => $domain_template + 'template' => $domain_template, + 'rl' => ['frame' => $domain_template['attributes']['rl_frame']], ]; $template = 'edit/domain-templates.twig'; $result = true; } else { - $mailbox_template = mailbox('get', 'mailbox_templates', $_GET["template"]); + $mailbox_template = mailbox('get', 'mailbox_templates', $_GET['template']); if ($mailbox_template){ $template_data = [ - 'template' => $mailbox_template + 'template' => $mailbox_template, + 'rl' => ['frame' => $mailbox_template['attributes']['rl_frame']], ]; $template = 'edit/mailbox-templates.twig'; $result = true; diff --git a/data/web/templates/edit/aliasdomain.twig b/data/web/templates/edit/aliasdomain.twig index e2ecd4875..fe262d1b9 100644 --- a/data/web/templates/edit/aliasdomain.twig +++ b/data/web/templates/edit/aliasdomain.twig @@ -31,10 +31,12 @@
    - +
    + +
    {% if dkim %} diff --git a/data/web/templates/edit/domain-templates.twig b/data/web/templates/edit/domain-templates.twig index c58693b23..8b4b428b1 100644 --- a/data/web/templates/edit/domain-templates.twig +++ b/data/web/templates/edit/domain-templates.twig @@ -81,13 +81,12 @@
    - - +
    + + +
    {% endif %} diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 4ba25cf70..a5c8b6d6f 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -145,14 +145,20 @@ {% endif %}
    -
    -
    -
    - - - + + +
    +
    +
    +
    +
    diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig index 28f45b569..d4949a3af 100644 --- a/data/web/templates/edit/mailbox-templates.twig +++ b/data/web/templates/edit/mailbox-templates.twig @@ -118,14 +118,13 @@
    +
    -

    {{ lang.edit.mbox_rl_info }}

    +
    +

    {{ lang.edit.mbox_rl_info }}


    diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index c020cb0ac..76cc45bbb 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -379,18 +379,24 @@
    -
    -
    -
    + +
    +

    {{ lang.acl.ratelimit }}

    - - + + +
    +
    +
    +
    +
    -

    {{ lang.edit.mbox_rl_info }}

    +

    {{ lang.edit.mbox_rl_info }}

    diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index e59d630ae..07c9d10f6 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -155,14 +155,13 @@
    - - -

    {{ lang.edit.mbox_rl_info }}

    +
    + + +
    +

    {{ lang.edit.mbox_rl_info }}

    @@ -325,14 +324,13 @@
    - - -

    {{ lang.edit.mbox_rl_info }}

    +
    + + +
    +

    {{ lang.edit.mbox_rl_info }}


    @@ -462,13 +460,13 @@
    -
    - -
    -
    - +
    +
    + + +

    @@ -600,16 +598,13 @@
    -
    - -
    -
    - +
    +
    + + +
    {% endif %} @@ -819,13 +814,13 @@
    -
    - -
    -
    - + + +

    From f059db54d0c27ac419b41eb8b070d1455ff0d210 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:32:47 +0200 Subject: [PATCH 059/174] [Web] edit mailbox template - fixed settigns buttons styling Signed-off-by: Kristian Feldsam --- .../web/templates/edit/mailbox-templates.twig | 24 +++++++++---------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig index d4949a3af..f606bd452 100644 --- a/data/web/templates/edit/mailbox-templates.twig +++ b/data/web/templates/edit/mailbox-templates.twig @@ -41,16 +41,16 @@
    - + - + - + - +

    {{ lang.user.quarantine_notification_info }}

    @@ -60,13 +60,13 @@
    - + - + - +

    {{ lang.user.quarantine_category_info }}

    @@ -76,10 +76,10 @@
    - + - +
    @@ -119,10 +119,10 @@
    - - + +

    {{ lang.edit.mbox_rl_info }}

    From bb69f399760cdb3fa27e0d33624ce4b92a29a5b0 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:33:29 +0200 Subject: [PATCH 060/174] =?UTF-8?q?[Web]=20domain=20and=20alias=20domain?= =?UTF-8?q?=20edit=20-=20translated=20dkim=20=E2=80=9Cdomain=E2=80=9D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Kristian Feldsam --- data/web/templates/edit/aliasdomain.twig | 2 +- data/web/templates/edit/domain.twig | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/web/templates/edit/aliasdomain.twig b/data/web/templates/edit/aliasdomain.twig index fe262d1b9..fc6b5ee1a 100644 --- a/data/web/templates/edit/aliasdomain.twig +++ b/data/web/templates/edit/aliasdomain.twig @@ -43,7 +43,7 @@
    -

    Domain: {{ result.alias_domain }} ({{ dkim.dkim_selector }}._domainkey)

    +

    {{ lang.add.domain }}: {{ result.alias_domain }} ({{ dkim.dkim_selector }}._domainkey)

    {{ dkim.dkim_txt }}
    diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index a5c8b6d6f..3da44b5cb 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -136,7 +136,7 @@
    -

    Domain: {{ result.domain_name }} ({{ dkim.dkim_selector }}._domainkey)

    +

    {{ lang.add.domain }}: {{ result.domain_name }} ({{ dkim.dkim_selector }}._domainkey)

    {{ dkim.dkim_txt }}
    From d48193fd0e11837a6c09da95b476cbe841f473fa Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:33:58 +0200 Subject: [PATCH 061/174] [Web] edit object - added space after heaading Signed-off-by: Kristian Feldsam --- data/web/templates/edit/aliasdomain.twig | 6 +++--- data/web/templates/edit/syncjob.twig | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/web/templates/edit/aliasdomain.twig b/data/web/templates/edit/aliasdomain.twig index fc6b5ee1a..540326e8d 100644 --- a/data/web/templates/edit/aliasdomain.twig +++ b/data/web/templates/edit/aliasdomain.twig @@ -2,7 +2,7 @@ {% block inner_content %} {% if result %} -

    {{ lang.edit.edit_alias_domain }}

    +

    {{ lang.edit.edit_alias_domain }}

    @@ -33,9 +33,9 @@
    - {% include 'mailbox/rl-frame.twig' %} - +
    diff --git a/data/web/templates/edit/syncjob.twig b/data/web/templates/edit/syncjob.twig index 40ae00fc2..6f6cdedac 100644 --- a/data/web/templates/edit/syncjob.twig +++ b/data/web/templates/edit/syncjob.twig @@ -2,7 +2,7 @@ {% block inner_content %} {% if result %} -

    {{ lang.edit.syncjob }}

    +

    {{ lang.edit.syncjob }}

    From 1b7cc830caea787520f032c30b10e993d64e4ee9 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:36:03 +0200 Subject: [PATCH 062/174] [Web] standarize select box dropdown buttons Signed-off-by: Kristian Feldsam --- data/web/templates/edit/domain-templates.twig | 2 +- data/web/templates/modals/mailbox.twig | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/data/web/templates/edit/domain-templates.twig b/data/web/templates/edit/domain-templates.twig index 8b4b428b1..825e6674d 100644 --- a/data/web/templates/edit/domain-templates.twig +++ b/data/web/templates/edit/domain-templates.twig @@ -100,7 +100,7 @@
    - diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 07c9d10f6..8e4878ae6 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -479,7 +479,7 @@
    - @@ -618,7 +618,7 @@
    - @@ -833,7 +833,7 @@
    - From 633ebe5e8dca0cd8b064a4897b911d58143afe87 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 12:36:33 +0200 Subject: [PATCH 063/174] [Web] fixed add domain save action button group styling Signed-off-by: Kristian Feldsam --- data/web/templates/modals/mailbox.twig | 1 - 1 file changed, 1 deletion(-) diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 8e4878ae6..1f96851fc 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -506,7 +506,6 @@ {% if not skip_sogo %} -
    {% else %} {% endif %} From 871ae5d7d285b216021e782ab57ab403d2dfd194 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 18:34:20 +0200 Subject: [PATCH 064/174] [Web] mobile devices styling fixes and enhancements Signed-off-by: Kristian Feldsam --- data/web/css/build/015-responsive.css | 15 +++- data/web/js/build/013-mailcow.js | 2 +- data/web/js/site/admin.js | 30 ++++---- data/web/js/site/mailbox.js | 68 +++++++++---------- .../templates/admin/tab-config-admins.twig | 8 +-- data/web/templates/admin/tab-config-f2b.twig | 7 +- .../templates/admin/tab-config-rsettings.twig | 8 ++- data/web/templates/fido2.twig | 4 +- data/web/templates/index.twig | 24 +++---- data/web/templates/mailbox/tab-bcc.twig | 16 ++--- .../templates/mailbox/tab-domain-aliases.twig | 8 +-- data/web/templates/mailbox/tab-domains.twig | 8 +-- data/web/templates/mailbox/tab-filters.twig | 16 ++--- data/web/templates/mailbox/tab-mailboxes.twig | 8 +-- .../templates/mailbox/tab-mbox-aliases.twig | 10 +-- data/web/templates/mailbox/tab-resources.twig | 8 +-- data/web/templates/mailbox/tab-syncjobs.twig | 8 +-- .../mailbox/tab-templates-domains.twig | 12 ++-- .../templates/mailbox/tab-templates-mbox.twig | 12 ++-- .../web/templates/mailbox/tab-tls-policy.twig | 8 +-- 20 files changed, 148 insertions(+), 132 deletions(-) diff --git a/data/web/css/build/015-responsive.css b/data/web/css/build/015-responsive.css index a626a384a..57ce80233 100644 --- a/data/web/css/build/015-responsive.css +++ b/data/web/css/build/015-responsive.css @@ -38,7 +38,7 @@ @media (max-width: 767px) { - .responsive-tabs .tab-pane { + .responsive-tabs .tab-pane:not(.rsettings) { display: block !important; opacity: 1; } @@ -206,6 +206,19 @@ .senders-mw220 { max-width: 100% !important; } + + table.dataTable.dtr-inline.collapsed>tbody>tr>td.dtr-control:before, + table.dataTable.dtr-inline.collapsed>tbody>tr>th.dtr-control:before, + table.dataTable td.dt-control:before { + height: 2rem; + width: 2rem; + line-height: 2rem; + margin-top: -15px; + } + + li .dtr-data { + padding: 0; + } } @media (max-width: 350px) { diff --git a/data/web/js/build/013-mailcow.js b/data/web/js/build/013-mailcow.js index e659915b2..6291c8b47 100644 --- a/data/web/js/build/013-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -121,7 +121,7 @@ $(document).ready(function() { if (lastTab) { $('[data-bs-target="#' + lastTab + '"]').click(); var tab = $('[id^="' + lastTab + '"]'); - $(tab).find('.card-body.collapse').collapse('show'); + $(tab).find('.card-body.collapse:first').collapse('show'); } }); })(); diff --git a/data/web/js/site/admin.js b/data/web/js/site/admin.js index 252da9a19..80da64167 100644 --- a/data/web/js/site/admin.js +++ b/data/web/js/site/admin.js @@ -510,9 +510,9 @@ jQuery(function($){ if (table == 'relayhoststable') { $.each(data, function (i, item) { item.action = ''; if (item.used_by_mailboxes == '') { item.in_use_by = item.used_by_domains; } else if (item.used_by_domains == '') { item.in_use_by = item.used_by_mailboxes; } @@ -528,9 +528,9 @@ jQuery(function($){ item.username = ' ' + item.username; } item.action = ''; item.chkbox = ''; }); @@ -542,21 +542,21 @@ jQuery(function($){ }); item.recipients = rcpts.join('
    '); item.action = ''; }); } else if (table == 'forwardinghoststable') { $.each(data, function (i, item) { item.action = ''; item.chkbox = ''; }); } else if (table == 'oauth2clientstable') { $.each(data, function (i, item) { item.action = ''; item.scope = "profile"; item.grant_types = 'refresh_token password authorization_code'; @@ -568,9 +568,9 @@ jQuery(function($){ item.selected_domains = item.selected_domains.toString().replace(/,/g, "
    "); item.chkbox = ''; item.action = ''; }); } else if (table == 'adminstable') { @@ -582,8 +582,8 @@ jQuery(function($){ } item.chkbox = ''; item.action = ''; }); } diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 50ce59df1..b258a42e4 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -469,13 +469,13 @@ jQuery(function($){ item.chkbox = ''; item.action = '
    '; if (role == "admin") { - item.action += ' ' + lang.edit + '' + - ' ' + lang.remove + '' + - ' DNS
    '; + item.action += ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + ' DNS
    '; } else { - item.action += ' ' + lang.edit + '' + - ' DNS
    '; + item.action += ' ' + lang.edit + '' + + ' DNS
    '; } if (Array.isArray(item.tags)){ @@ -671,13 +671,13 @@ jQuery(function($){ if (item.template.toLowerCase() == "default"){ item.action = ''; } else { item.action = ''; } @@ -912,18 +912,18 @@ jQuery(function($){ if (acl_data.login_as === 1) { item.action = '
    ' + - ' ' + lang.edit + '' + - ' ' + lang.remove + '' + - ''; + ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + ''; if (ALLOW_ADMIN_EMAIL_LOGIN) { - item.action += ''; + item.action += ''; } item.action += '
    '; } else { item.action = ''; } item.in_use = { @@ -1190,13 +1190,13 @@ jQuery(function($){ if (item.template.toLowerCase() == "default"){ item.action = ''; } else { item.action = ''; } @@ -1378,8 +1378,8 @@ jQuery(function($){ item.multiple_bookings = '' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')'; } item.action = ''; item.chkbox = ''; item.name = escapeHtml(item.name); @@ -1518,8 +1518,8 @@ jQuery(function($){ dataSrc: function(json){ $.each(json, function (i, item) { item.action = ''; item.chkbox = ''; item.local_dest = escapeHtml(item.local_dest); @@ -1632,8 +1632,8 @@ jQuery(function($){ item.recipient_map_old = escapeHtml(item.recipient_map_old); item.recipient_map_new = escapeHtml(item.recipient_map_new); item.action = ''; item.chkbox = ''; }); @@ -1734,8 +1734,8 @@ jQuery(function($){ item.parameters = '' + escapeHtml(item.parameters) + ''; } item.action = ''; item.chkbox = ''; }); @@ -1832,8 +1832,8 @@ jQuery(function($){ dataSrc: function(json){ $.each(json, function (i, item) { item.action = ''; item.chkbox = ''; item.goto = escapeHtml(item.goto.replace(/,/g, " ")); @@ -1991,9 +1991,9 @@ jQuery(function($){ item.alias_domain = escapeHtml(item.alias_domain); item.action = '' + + ' ' + lang.edit + '' + + ' ' + lang.remove + '' + + ' DNS
    ' + '
    '; item.chkbox = ''; if(item.parent_is_backupmx == '1') { @@ -2093,8 +2093,8 @@ jQuery(function($){ } item.server_w_port = escapeHtml(item.user1) + '@' + escapeHtml(item.host1) + ':' + escapeHtml(item.port1); item.action = ''; item.chkbox = ''; if (item.is_running == 1) { @@ -2247,8 +2247,8 @@ jQuery(function($){ item.script_data = '
    ' + escapeHtml(item.script_data) + '
    ' item.filter_type = '
    ' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '
    ' item.action = ''; item.chkbox = '' }); diff --git a/data/web/templates/admin/tab-config-admins.twig b/data/web/templates/admin/tab-config-admins.twig index b672b8159..44342af4d 100644 --- a/data/web/templates/admin/tab-config-admins.twig +++ b/data/web/templates/admin/tab-config-admins.twig @@ -122,8 +122,8 @@
    -
    - +
    +
    @@ -166,8 +166,8 @@
    - - + +
    diff --git a/data/web/templates/admin/tab-config-f2b.twig b/data/web/templates/admin/tab-config-f2b.twig index de4a7c63b..a353f7fa3 100644 --- a/data/web/templates/admin/tab-config-f2b.twig +++ b/data/web/templates/admin/tab-config-f2b.twig @@ -92,13 +92,14 @@ {% endif %} {% for active_ban in f2b_data.active_bans %}

    - + {{ active_ban.network }} ({{ active_ban.banned_until }}) - - + + - {% if active_ban.queued_for_unban == 0 %} [{{ lang.admin.queue_unban }}] [whitelist] @@ -111,7 +112,7 @@


    {% for perm_ban in f2b_data.perm_bans %}

    - + {{ perm_ban.network }} diff --git a/data/web/templates/admin/tab-config-rsettings.twig b/data/web/templates/admin/tab-config-rsettings.twig index 38b0d593d..439e55a31 100644 --- a/data/web/templates/admin/tab-config-rsettings.twig +++ b/data/web/templates/admin/tab-config-rsettings.twig @@ -44,7 +44,7 @@

    {{ lang.admin.rsetting_no_selection }}

    {% for rsetting in rsettings %} -
    -
    - - +
    +
    + + +
    {% if not oauth2_request %} - +
    {% endif %}
    @@ -62,19 +66,15 @@
    {% if not oauth2_request and (mailcow_apps or app_links) %} {{ ui_texts.apps_name|raw }}
    -
    +
    {% for app in mailcow_apps %} {% if not skip_sogo or not is_uri('SOGo', app.link) %} - - {% endif %} + {{ app.name }} + {% endif %} {% endfor %} {% for row in app_links %} {% for key, val in row %} -
    - {{ key }} -
    + {{ key }} {% endfor %} {% endfor %}
    diff --git a/data/web/templates/mailbox/tab-bcc.twig b/data/web/templates/mailbox/tab-bcc.twig index 25844e48e..eedb04b22 100644 --- a/data/web/templates/mailbox/tab-bcc.twig +++ b/data/web/templates/mailbox/tab-bcc.twig @@ -11,7 +11,7 @@
    -
    -
    +
    diff --git a/data/web/templates/mailbox/tab-domain-aliases.twig b/data/web/templates/mailbox/tab-domain-aliases.twig index 6cefd0938..4bbfbbe53 100644 --- a/data/web/templates/mailbox/tab-domain-aliases.twig +++ b/data/web/templates/mailbox/tab-domain-aliases.twig @@ -11,7 +11,7 @@
    -
    +
    diff --git a/data/web/templates/mailbox/tab-domains.twig b/data/web/templates/mailbox/tab-domains.twig index 8b2d61b7d..49cb89b6d 100644 --- a/data/web/templates/mailbox/tab-domains.twig +++ b/data/web/templates/mailbox/tab-domains.twig @@ -12,7 +12,7 @@
    {#
    #} -
    +
    @@ -35,8 +35,8 @@
    - - + + {% if mailcow_cc_role == 'admin' %} - + {% endif %}
    diff --git a/data/web/templates/mailbox/tab-filters.twig b/data/web/templates/mailbox/tab-filters.twig index 203d39113..8ccff27a4 100644 --- a/data/web/templates/mailbox/tab-filters.twig +++ b/data/web/templates/mailbox/tab-filters.twig @@ -11,7 +11,7 @@
    -
    +
    {{ lang.mailbox.toggle_all }} {{ lang.mailbox.quick_actions }} @@ -34,8 +34,8 @@
    @@ -64,8 +64,8 @@
    - - + +
    @@ -82,8 +82,8 @@
    - - + +
    diff --git a/data/web/templates/mailbox/tab-mailboxes.twig b/data/web/templates/mailbox/tab-mailboxes.twig index 9b8279896..fce7d6276 100644 --- a/data/web/templates/mailbox/tab-mailboxes.twig +++ b/data/web/templates/mailbox/tab-mailboxes.twig @@ -11,7 +11,7 @@
    -
    +
    {{ lang.mailbox.toggle_all }} {{ lang.mailbox.quick_actions }} @@ -128,8 +128,8 @@
    {{ lang.mailbox.toggle_all }} diff --git a/data/web/templates/mailbox/tab-mbox-aliases.twig b/data/web/templates/mailbox/tab-mbox-aliases.twig index 7035ac212..02b5b6d0c 100644 --- a/data/web/templates/mailbox/tab-mbox-aliases.twig +++ b/data/web/templates/mailbox/tab-mbox-aliases.twig @@ -11,7 +11,7 @@
    -
    +
    diff --git a/data/web/templates/mailbox/tab-resources.twig b/data/web/templates/mailbox/tab-resources.twig index b23231f21..34728eda2 100644 --- a/data/web/templates/mailbox/tab-resources.twig +++ b/data/web/templates/mailbox/tab-resources.twig @@ -11,7 +11,7 @@
    -
    +
    diff --git a/data/web/templates/mailbox/tab-syncjobs.twig b/data/web/templates/mailbox/tab-syncjobs.twig index d634d40b6..bfd8eefb4 100644 --- a/data/web/templates/mailbox/tab-syncjobs.twig +++ b/data/web/templates/mailbox/tab-syncjobs.twig @@ -11,7 +11,7 @@
    -
    +
    diff --git a/data/web/templates/mailbox/tab-templates-domains.twig b/data/web/templates/mailbox/tab-templates-domains.twig index c339aaf01..f3c6a678f 100644 --- a/data/web/templates/mailbox/tab-templates-domains.twig +++ b/data/web/templates/mailbox/tab-templates-domains.twig @@ -1,4 +1,4 @@ -
    +
    -
    -
    +
    +
    @@ -31,8 +31,8 @@
    - - + + {% if mailcow_cc_role == 'admin' %} - + {% endif %}
    diff --git a/data/web/templates/mailbox/tab-templates-mbox.twig b/data/web/templates/mailbox/tab-templates-mbox.twig index 631394bb9..71edb9d39 100644 --- a/data/web/templates/mailbox/tab-templates-mbox.twig +++ b/data/web/templates/mailbox/tab-templates-mbox.twig @@ -1,4 +1,4 @@ -
    +
    -
    -
    +
    +
    @@ -31,8 +31,8 @@
    - - + + {% if mailcow_cc_role == 'admin' %} - + {% endif %}
    diff --git a/data/web/templates/mailbox/tab-tls-policy.twig b/data/web/templates/mailbox/tab-tls-policy.twig index 64bce55f8..3195b754a 100644 --- a/data/web/templates/mailbox/tab-tls-policy.twig +++ b/data/web/templates/mailbox/tab-tls-policy.twig @@ -11,7 +11,7 @@
    -
    +
    From d0ba061f7a79119ec2b191772ce8f0ab14af22e5 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 18:35:24 +0200 Subject: [PATCH 065/174] [Web] mobile devices - scroll window to opened tab This feature was in versions before BS5 Signed-off-by: Kristian Feldsam --- data/web/js/build/013-mailcow.js | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/data/web/js/build/013-mailcow.js b/data/web/js/build/013-mailcow.js index 6291c8b47..ead4934ef 100644 --- a/data/web/js/build/013-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -125,6 +125,17 @@ $(document).ready(function() { } }); })(); + + // responsive tabs, scroll to opened tab + $(document).on("shown.bs.collapse shown.bs.tab", function (e) { + var target = $(e.target); + if($(window).width() <= 767) { + var offset = target.offset().top - 60; + $("html, body").stop().animate({ + scrollTop: offset + }, 100); + } + }); // IE fix to hide scrollbars when table body is empty $('tbody').filter(function (index) { From 3540075b61606a11c9f2801283ab7280640410dc Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 18:49:12 +0200 Subject: [PATCH 066/174] [Web] dark mode logo support Signed-off-by: Kristian Feldsam --- data/web/admin.php | 1 + data/web/inc/functions.customize.inc.php | 22 +++++++++---- data/web/inc/header.inc.php | 1 + data/web/inc/triggers.inc.php | 4 +++ data/web/js/build/013-mailcow.js | 9 ++++++ data/web/lang/lang.en-gb.json | 2 ++ data/web/templates/admin/customize/logo.twig | 9 ++++++ .../templates/admin/tab-config-customize.twig | 32 +++++++++++-------- data/web/templates/base.twig | 5 ++- data/web/templates/debug.twig | 3 +- data/web/templates/index.twig | 5 ++- 11 files changed, 69 insertions(+), 24 deletions(-) create mode 100644 data/web/templates/admin/customize/logo.twig diff --git a/data/web/admin.php b/data/web/admin.php index 14cb89f58..ebddb7b91 100644 --- a/data/web/admin.php +++ b/data/web/admin.php @@ -108,6 +108,7 @@ $template_data = [ 'rsettings' => $rsettings, 'rspamd_regex_maps' => $rspamd_regex_maps, 'logo_specs' => customize('get', 'main_logo_specs'), + 'logo_dark_specs' => customize('get', 'main_logo_dark_specs'), 'ip_check' => customize('get', 'ip_check'), 'password_complexity' => password_complexity('get'), 'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'], diff --git a/data/web/inc/functions.customize.inc.php b/data/web/inc/functions.customize.inc.php index 6025d97da..0da8c3563 100644 --- a/data/web/inc/functions.customize.inc.php +++ b/data/web/inc/functions.customize.inc.php @@ -24,9 +24,10 @@ function customize($_action, $_item, $_data = null) { } switch ($_item) { case 'main_logo': - if (in_array($_data['main_logo']['type'], array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png', 'image/svg+xml'))) { + case 'main_logo_dark': + if (in_array($_data[$_item]['type'], array('image/gif', 'image/jpeg', 'image/pjpeg', 'image/x-png', 'image/png', 'image/svg+xml'))) { try { - if (file_exists($_data['main_logo']['tmp_name']) !== true) { + if (file_exists($_data[$_item]['tmp_name']) !== true) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_item, $_data), @@ -34,7 +35,7 @@ function customize($_action, $_item, $_data = null) { ); return false; } - $image = new Imagick($_data['main_logo']['tmp_name']); + $image = new Imagick($_data[$_item]['tmp_name']); if ($image->valid() !== true) { $_SESSION['return'][] = array( 'type' => 'danger', @@ -63,7 +64,7 @@ function customize($_action, $_item, $_data = null) { return false; } try { - $redis->Set('MAIN_LOGO', 'data:' . $_data['main_logo']['type'] . ';base64,' . base64_encode(file_get_contents($_data['main_logo']['tmp_name']))); + $redis->Set(strtoupper($_item), 'data:' . $_data[$_item]['type'] . ';base64,' . base64_encode(file_get_contents($_data[$_item]['tmp_name']))); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -201,8 +202,9 @@ function customize($_action, $_item, $_data = null) { } switch ($_item) { case 'main_logo': + case 'main_logo_dark': try { - if ($redis->del('MAIN_LOGO')) { + if ($redis->del(strtoupper($_item))) { $_SESSION['return'][] = array( 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_item, $_data), @@ -239,8 +241,9 @@ function customize($_action, $_item, $_data = null) { return ($app_links) ? $app_links : false; break; case 'main_logo': + case 'main_logo_dark': try { - return $redis->get('MAIN_LOGO'); + return $redis->get(strtoupper($_item)); } catch (RedisException $e) { $_SESSION['return'][] = array( @@ -277,9 +280,14 @@ function customize($_action, $_item, $_data = null) { } break; case 'main_logo_specs': + case 'main_logo_dark_specs': try { $image = new Imagick(); - $img_data = explode('base64,', customize('get', 'main_logo')); + if($_item == 'main_logo_specs') { + $img_data = explode('base64,', customize('get', 'main_logo')); + } else { + $img_data = explode('base64,', customize('get', 'main_logo_dark')); + } if ($img_data[1]) { $image->readImageBlob(base64_decode($img_data[1])); return $image->identifyImage(); diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php index f62819a2e..9afc288dd 100644 --- a/data/web/inc/header.inc.php +++ b/data/web/inc/header.inc.php @@ -40,6 +40,7 @@ $globalVariables = [ 'ui_texts' => $UI_TEXTS, 'css_path' => '/cache/'.basename($CSSPath), 'logo' => customize('get', 'main_logo'), + 'logo_dark' => customize('get', 'main_logo_dark'), 'available_languages' => $AVAILABLE_LANGUAGES, 'lang' => $lang, 'skip_sogo' => (getenv('SKIP_SOGO') == 'y'), diff --git a/data/web/inc/triggers.inc.php b/data/web/inc/triggers.inc.php index c40453a25..6922429b8 100644 --- a/data/web/inc/triggers.inc.php +++ b/data/web/inc/triggers.inc.php @@ -120,10 +120,14 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi if (isset($_POST["submit_main_logo"])) { if ($_FILES['main_logo']['error'] == 0) { customize('add', 'main_logo', $_FILES); + } + if ($_FILES['main_logo_dark']['error'] == 0) { + customize('add', 'main_logo_dark', $_FILES); } } if (isset($_POST["reset_main_logo"])) { customize('delete', 'main_logo'); + customize('delete', 'main_logo_dark'); } // Some actions will not be available via API if (isset($_POST["license_validate_now"])) { diff --git a/data/web/js/build/013-mailcow.js b/data/web/js/build/013-mailcow.js index e659915b2..4907623ce 100644 --- a/data/web/js/build/013-mailcow.js +++ b/data/web/js/build/013-mailcow.js @@ -314,19 +314,28 @@ $(document).ready(function() { $('#dark-mode-toggle').click(toggleDarkMode); if ($('#dark-mode-theme').length) { $('#dark-mode-toggle').prop('checked', true); + $('.main-logo').addClass('d-none'); + $('.main-logo-dark').removeClass('d-none'); if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); + } else { + $('.main-logo').removeClass('d-none'); + $('.main-logo-dark').addClass('d-none'); } function toggleDarkMode(){ if($('#dark-mode-theme').length){ $('#dark-mode-theme').remove(); $('#dark-mode-toggle').prop('checked', false); + $('.main-logo').removeClass('d-none'); + $('.main-logo-dark').addClass('d-none'); if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png'); if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png'); localStorage.setItem('theme', 'light'); }else{ $('head').append(''); $('#dark-mode-toggle').prop('checked', true); + $('.main-logo').addClass('d-none'); + $('.main-logo-dark').removeClass('d-none'); if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); localStorage.setItem('theme', 'dark'); diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index a4d06da3a..344fae6c2 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -149,6 +149,8 @@ "ays": "Are you sure you want to proceed?", "ban_list_info": "See a list of banned IPs below: network (remaining ban time) - [actions].
    IPs queued to be unbanned will be removed from the active ban list within a few seconds.
    Red labels indicate active permanent bans by blacklisting.", "change_logo": "Change logo", + "logo_normal_label": "Normal", + "logo_dark_label": "Inverted for dark mode", "configuration": "Configuration", "convert_html_to_text": "Convert HTML to plain text", "cors_settings": "CORS Settings", diff --git a/data/web/templates/admin/customize/logo.twig b/data/web/templates/admin/customize/logo.twig new file mode 100644 index 000000000..45f6c91e6 --- /dev/null +++ b/data/web/templates/admin/customize/logo.twig @@ -0,0 +1,9 @@ +
    + mailcow logo +
    + {{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px + {{ logo_specs.mimetype }} + {{ logo_specs.fileSize }} +
    +
    + diff --git a/data/web/templates/admin/tab-config-customize.twig b/data/web/templates/admin/tab-config-customize.twig index e458eeb3b..a616375c5 100644 --- a/data/web/templates/admin/tab-config-customize.twig +++ b/data/web/templates/admin/tab-config-customize.twig @@ -10,22 +10,26 @@ {{ lang.admin.change_logo }}

    {{ lang.admin.logo_info }}

    -

    -
    - -

    +
    + + +
    +
    + + +
    + +
    - {% if logo %} -
    + {% if logo or logo_dark %} +
    -
    - mailcow logo -
    - {{ logo_specs.geometry.width }}x{{ logo_specs.geometry.height }} px - {{ logo_specs.mimetype }} - {{ logo_specs.fileSize }} -
    -
    + {% if logo %} + {% include 'admin/customize/logo.twig' %} + {% endif %} + {% if logo_dark %} + {% include 'admin/customize/logo.twig' with {'logo': logo_dark, 'logo_specs': logo_dark_specs, 'dark': 1} %} + {% endif %}

    diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig index 06c47bd2c..0b1c60a29 100644 --- a/data/web/templates/base.twig +++ b/data/web/templates/base.twig @@ -31,7 +31,10 @@ {% block navbar %}
    - {% if mailcow_cc_role == 'admin' %} -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    -
    - -
    - -

    {{ lang.edit.relay_all_info|raw }}

    - -
    -

    {{ lang.edit.relay_transport_info|raw }}

    -
    -
    -
    -
    - {% endif %} -
    -
    -
    - - {{ lang.edit.gal_info|raw }} -
    -
    -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    -
    -
    - {{ lang.edit.created_on }}: {{ result.created }} - {{ lang.edit.last_modified }}: {{ result.modified }} -
    -
    - - {% if dkim %} -
    -
    -
    -

    {{ lang.add.domain }}: {{ result.domain_name }} ({{ dkim.dkim_selector }}._domainkey)

    -
    -
    -
    {{ dkim.dkim_txt }}
    -
    -
    - {% endif %} -
    -
    -
    -
    - -
    -
    - - -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    -
    -

    {{ lang.user.spamfilter_wl }}

    -

    {{ lang.user.spamfilter_wl_desc|raw }}

    -
    -
    - - -
    -
    -
    - -
    -
    -

    {{ lang.user.spamfilter_bl }}

    -

    {{ lang.user.spamfilter_bl_desc|raw }}

    -
    -
    - - -
    -
    -
    -
    - +
    +
    +
    + +
    +
    +
    +
    +

    {{ lang.edit.quota_warning_bcc }}

    +

    {{ lang.edit.quota_warning_bcc_info|raw }}

    +
    + +
    + +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    + +
    +
    +
    +
    +
    +
    -
    -
    -
    -
    -

    {{ lang.edit.quota_warning_bcc }}

    -

    {{ lang.edit.quota_warning_bcc_info|raw }}

    -
    - -
    - -
    - -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -
    {% else %} {{ parent() }} diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index 76cc45bbb..072504593 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -2,405 +2,443 @@ {% block inner_content %} {% if result %} - -
    -
    -
    -
    - - - - -
    - -
    - -
    -
    -
    - -
    -
    - {% for tag in mailbox_details.tags %} - - - {{ tag }} - - {% endfor %} - - - -
    -
    -
    -
    - -
    - - 0 = ∞ -
    -
    -
    - -
    - -
    {{ lang.edit.sender_acl_disabled|raw }}
    - {{ lang.edit.sender_acl_info|raw }} -
    -
    -
    - -
    - -

     

    - {{ lang.edit.mailbox_relayhost_info }} -
    -
    -
    - -
    -
    - - - - -
    -

    {{ lang.user.quarantine_notification_info }}

    -
    -
    -
    - -
    -
    - - - -
    -

    {{ lang.user.quarantine_category_info }}

    -
    -
    -
    - -
    -
    - - -
    -
    -
    -
    - -
    - -
    -
    -
    - -
    - -
    -
    -
    - -
    - {% if sender_acl_handles.external_sender_aliases %} - {% set ext_sender_acl = sender_acl_handles.external_sender_aliases|join(', ') %} - {% endif %} - {% if acl.extend_sender_acl and acl.extend_sender_acl == 1 %} - - {{ lang.edit.extended_sender_acl_info|raw }} - {% endif %} -
    -
    -
    - -
    - -
    -
    - -
    -
    -
    - -
    -
    -
    -
    -
    - - {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }} -
    -
    -
    - {% if not skip_sogo %} -
    -
    -
    - - {{ lang.edit.sogo_access_info }} -
    -
    -
    - {% endif %} -
    -
    - -
    -
    -
    -
    - {{ lang.edit.created_on }}: {{ result.created }} - {{ lang.edit.last_modified }}: {{ result.modified }} -
    -
    -
    -
    -
    -
    - - - -
    -
    -

    -
    -
    -

    {{ lang.user.pushover_info|format(mailbox)|raw }}

    -

    {{ lang.edit.pushover_vars|raw }}: {SUBJECT}, {SENDER}, {SENDER_ADDRESS}, {SENDER_NAME}, {TO_NAME}, {TO_ADDRESS}, {MSG_ID}

    -
    -
    - - +
    + +
    +
    +
    +
    +
    +
    -
    - - +
    + + + + + +
    + +
    + +
    +
    +
    + +
    +
    + {% for tag in mailbox_details.tags %} + + + {{ tag }} + + {% endfor %} + + + +
    +
    +
    +
    + +
    + + 0 = ∞ +
    +
    +
    + +
    + +
    {{ lang.edit.sender_acl_disabled|raw }}
    + {{ lang.edit.sender_acl_info|raw }} +
    +
    +
    + +
    + +

     

    + {{ lang.edit.mailbox_relayhost_info }} +
    +
    +
    + +
    +
    + + + + +
    +

    {{ lang.user.quarantine_notification_info }}

    +
    +
    +
    + +
    +
    + + + +
    +

    {{ lang.user.quarantine_category_info }}

    +
    +
    +
    + +
    +
    + + +
    +
    +
    +
    + +
    + +
    +
    +
    + +
    + +
    +
    +
    + +
    + {% if sender_acl_handles.external_sender_aliases %} + {% set ext_sender_acl = sender_acl_handles.external_sender_aliases|join(', ') %} + {% endif %} + {% if acl.extend_sender_acl and acl.extend_sender_acl == 1 %} + + {{ lang.edit.extended_sender_acl_info|raw }} + {% endif %} +
    +
    +
    + +
    + +
    +
    + +
    +
    +
    + +
    +
    +
    +
    +
    + + {{ lang.edit.force_pw_update_info|format(ui_texts.main_name) }} +
    +
    +
    + {% if not skip_sogo %} +
    +
    +
    + + {{ lang.edit.sogo_access_info }} +
    +
    +
    + {% endif %} +
    +
    + +
    +
    +
    +
    + {{ lang.edit.created_on }}: {{ result.created }} + {{ lang.edit.last_modified }}: {{ result.modified }} +
    +
    +
    -
    - - -
    -
    - - -
    -
    - - -
    -
    -
    -
    - -
    -
    -
    -
    - -
    -
    -
    - - {{ lang.edit.advanced_settings }} - -
    -
    -
    -
    - - -
    - -
    -
    - -
    -
    -
    -
    -
    - -
    -
    -
    -
    -
    -

    ACL

    -
    -
    - - +
    +
    +
    + +
    +
    + + + + +
    +
    +

    +
    +
    +

    {{ lang.user.pushover_info|format(mailbox)|raw }}

    +

    {{ lang.edit.pushover_vars|raw }}: {SUBJECT}, {SENDER}, {SENDER_ADDRESS}, {SENDER_NAME}, {TO_NAME}, {TO_ADDRESS}, {MSG_ID}

    +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    + + +
    +
    +
    +
    + +
    +
    +
    +
    + +
    +
    +
    + + {{ lang.edit.advanced_settings }} + +
    +
    +
    +
    + + +
    + +
    +
    + +
    +
    +
    +
    + +
    +
    + +
    - -
    -
    -
    -
    -
    -

    {{ lang.acl.ratelimit }}

    -
    -
    -
    - - -
    -
    -
    -
    -
    - -

    {{ lang.edit.mbox_rl_info }}

    +
    +
    +
    + +
    +
    + +
    +
    +

    ACL

    +
    +
    + + +
    +
    + +
    - -
    +
    +
    +
    + +
    +
    +
    +
    +
    +

    {{ lang.acl.ratelimit }}

    +
    +
    +
    + + +
    +
    +
    +
    +
    + +

    {{ lang.edit.mbox_rl_info }}

    +
    +
    +
    +
    +
    +
    +
    {% else %} {{ parent() }} From 8e5cd907072a75cee8116367b234362e97616c53 Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Sun, 3 Sep 2023 14:05:12 +0200 Subject: [PATCH 069/174] [Web] Filter tables by Domain where possible This feature was standard in Mailcow in pre-BS5 releases Signed-off-by: Kristian Feldsam --- data/web/js/site/mailbox.js | 46 +++++++++++++++++++++++++++++++++---- 1 file changed, 42 insertions(+), 4 deletions(-) diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 3ddeea944..8381ab4d5 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -851,8 +851,9 @@ jQuery(function($){ "tr" + "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", language: lang_datatables, - initComplete: function(){ + initComplete: function(settings, json){ hideTableExpandCollapseBtn('#tab-mailboxes', '#mailbox_table'); + filterByDomain(json, 8, table); }, ajax: { type: "GET", @@ -1362,8 +1363,9 @@ jQuery(function($){ "tr" + "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", language: lang_datatables, - initComplete: function(){ + initComplete: function(settings, json){ hideTableExpandCollapseBtn('#tab-resources', '#resource_table'); + filterByDomain(json, 5, table); }, ajax: { type: "GET", @@ -1509,8 +1511,9 @@ jQuery(function($){ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", language: lang_datatables, order: [[2, 'desc']], - initComplete: function(){ + initComplete: function(settings, json){ hideTableExpandCollapseBtn('#collapse-tab-bcc', '#bcc_table'); + filterByDomain(json, 6, table); }, ajax: { type: "GET", @@ -1823,8 +1826,9 @@ jQuery(function($){ "<'row'<'col-sm-12 col-md-5'i><'col-sm-12 col-md-7'p>>", language: lang_datatables, order: [[2, 'desc']], - initComplete: function(){ + initComplete: function(settings, json){ hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table'); + filterByDomain(json, 5, table); }, ajax: { type: "GET", @@ -2329,6 +2333,40 @@ jQuery(function($){ else $(tab).find(".table_collapse_option").hide(); } + + function filterByDomain(json, column, table){ + var tableId = $(table.table().container()).attr('id'); + // Create the `select` element + var select = $('') + .insertBefore( + $('#'+tableId+' .dataTables_filter > label > input') + ) + .on( 'change', function(){ + table.column(column) + .search($(this).val()) + .draw(); + }); + + // get all domains + var domains = []; + json.forEach(obj => { + Object.entries(obj).forEach(([key, value]) => { + if(key === 'domain') { + domains.push(value) + } + }); + }); + + // get unique domain list + domains = domains.filter(function(value, index, array) { + return array.indexOf(value) === index; + }); + + // add domains to select + domains.forEach(function(domain) { + select.append($('')); + }); + } // detect element visibility changes function onVisible(element, callback) { From 8e87e76dcf821d3353a77ff2fdc729f459dd8c22 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Mon, 4 Sep 2023 18:49:38 +0200 Subject: [PATCH 070/174] Update actions/checkout action to v4 (#5409) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/image_builds.yml | 2 +- .github/workflows/pr_to_nightly.yml | 2 +- .github/workflows/rebuild_backup_image.yml | 2 +- .github/workflows/update_postscreen_access_list.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/image_builds.yml b/.github/workflows/image_builds.yml index 65678dffe..496d4f73d 100644 --- a/.github/workflows/image_builds.yml +++ b/.github/workflows/image_builds.yml @@ -28,7 +28,7 @@ jobs: - "watchdog-mailcow" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v3 + - uses: actions/checkout@v4 - name: Setup Docker run: | curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh diff --git a/.github/workflows/pr_to_nightly.yml b/.github/workflows/pr_to_nightly.yml index 57aac7816..e629e5e9a 100644 --- a/.github/workflows/pr_to_nightly.yml +++ b/.github/workflows/pr_to_nightly.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v3 + uses: actions/checkout@v4 with: fetch-depth: 0 - name: Run the Action diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index 21c218a8f..6c1d7e834 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -11,7 +11,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Set up QEMU uses: docker/setup-qemu-action@v2 diff --git a/.github/workflows/update_postscreen_access_list.yml b/.github/workflows/update_postscreen_access_list.yml index 5d31eb9a6..42502f303 100644 --- a/.github/workflows/update_postscreen_access_list.yml +++ b/.github/workflows/update_postscreen_access_list.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v3 + uses: actions/checkout@v4 - name: Generate postscreen_access.cidr run: | From 21121f98273f607d981e625227e85d68165f9347 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 4 Sep 2023 19:56:42 +0200 Subject: [PATCH 071/174] Translations update from Weblate (#5410) * [Web] Language file updated by 'Cleanup translation files' addon Co-authored-by: milkmaker * [Web] Updated lang.en-gb.json Co-authored-by: Peter * [Web] Updated lang.de-de.json Co-authored-by: Peter * [Web] Updated lang.ru-ru.json Co-authored-by: Peter * [Web] Updated lang.uk-ua.json Co-authored-by: Peter --------- Co-authored-by: Peter --- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.ru-ru.json | 2 +- data/web/lang/lang.sk-sk.json | 43 +++++++++++++++++------------------ data/web/lang/lang.uk-ua.json | 2 +- 5 files changed, 25 insertions(+), 26 deletions(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 43d2b6c50..30d1816de 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -484,7 +484,7 @@ "info": "_START_ bis _END_ von _TOTAL_ Einträgen", "infoEmpty": "0 bis 0 von 0 Einträgen", "infoFiltered": "(gefiltert von _MAX_ Einträgen)", - "infoPostFix": "datatables.infoPostFix", + "infoPostFix": "", "thousands": ".", "lengthMenu": "_MENU_ Einträge anzeigen", "loadingRecords": "Wird geladen...", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index a4d06da3a..28ff19b81 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -484,7 +484,7 @@ "info": "Showing _START_ to _END_ of _TOTAL_ entries", "infoEmpty": "Showing 0 to 0 of 0 entries", "infoFiltered": "(filtered from _MAX_ total entries)", - "infoPostFix": "datatables.infoPostFix", + "infoPostFix": "", "thousands": ",", "lengthMenu": "Show _MENU_ entries", "loadingRecords": "Loading...", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 0783710ca..dccaa2041 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -1202,6 +1202,6 @@ "session_ua": "Неверный токен формы: ошибка проверки User-Agent" }, "datatables": { - "infoPostFix": "datatables.infoPostFix" + "infoPostFix": "" } } diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 276d7b9e4..7e3f598a2 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -457,28 +457,27 @@ "yotp_verification_failed": "Overenie cez OTP Yubico zlyhalo: %s" }, "datatables": { - "info": "Záznamy _START_ až _END_ z celkom _TOTAL_", - "infoEmpty": "Záznamy 0 až 0 z celkom 0 ", - "infoFiltered": "(vyfiltrované spomedzi _MAX_ záznamov)", - "infoThousands": " ", - "lengthMenu": "Zobraz _MENU_ záznamov", - "loadingRecords": "Načítavam...", - "processing": "Spracúvam...", - "search": "Hľadať:", - "zeroRecords": "Nenašli sa žiadne vyhovujúce záznamy", - "paginate": { - "first": "Prvá", - "last": "Posledná", - "next": "Nasledujúca", - "previous": "Predchádzajúca" - }, - "aria": { - "sortAscending": ": aktivujte na zoradenie stĺpca vzostupne", - "sortDescending": ": aktivujte na zoradenie stĺpca zostupne" - }, - "emptyTable": "Nie sú k dispozícii žiadne dáta.", - "decimal": ",", - "thousands": " " + "info": "Záznamy _START_ až _END_ z celkom _TOTAL_", + "infoEmpty": "Záznamy 0 až 0 z celkom 0 ", + "infoFiltered": "(vyfiltrované spomedzi _MAX_ záznamov)", + "lengthMenu": "Zobraz _MENU_ záznamov", + "loadingRecords": "Načítavam...", + "processing": "Spracúvam...", + "search": "Hľadať:", + "zeroRecords": "Nenašli sa žiadne vyhovujúce záznamy", + "paginate": { + "first": "Prvá", + "last": "Posledná", + "next": "Nasledujúca", + "previous": "Predchádzajúca" + }, + "aria": { + "sortAscending": ": aktivujte na zoradenie stĺpca vzostupne", + "sortDescending": ": aktivujte na zoradenie stĺpca zostupne" + }, + "emptyTable": "Nie sú k dispozícii žiadne dáta.", + "decimal": ",", + "thousands": " " }, "debug": { "chart_this_server": "Graf (tento server)", diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 93545aa34..b7b405684 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -1254,7 +1254,7 @@ }, "datatables": { "decimal": ".", - "infoPostFix": "datatables.infoPostFix", + "infoPostFix": "", "zeroRecords": "Відповідних записів не знайдено", "aria": { "sortAscending": ": активувати для сортування стовпців за зростанням", From 8d75b570c805fcc83b9695c5faf26403788a73e3 Mon Sep 17 00:00:00 2001 From: Mirko Ceroni Date: Mon, 4 Sep 2023 21:43:24 +0200 Subject: [PATCH 072/174] Update data/conf/sogo/sogo.conf Co-authored-by: Peter --- data/conf/sogo/sogo.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf index d12333a8b..4e18d80b0 100644 --- a/data/conf/sogo/sogo.conf +++ b/data/conf/sogo/sogo.conf @@ -83,7 +83,7 @@ //SoDebugBaseURL = YES; //ImapDebugEnabled = YES; //SOGoEASDebugEnabled = YES; - SOGoEASSearchInBody = YES + SOGoEASSearchInBody = YES; //LDAPDebugEnabled = YES; //PGDebugEnabled = YES; //MySQL4DebugEnabled = YES; From 89bc11ce0f2d2b7ce3bcd9b09980ad1dcfd03ca7 Mon Sep 17 00:00:00 2001 From: Christian Schmitt Date: Mon, 11 Sep 2023 15:44:24 +0200 Subject: [PATCH 073/174] Fix typo in German translation: (#5414) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit "gibt Aufschluss darüber" --- 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 1e65f1be7..e7c6682ab 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -966,7 +966,7 @@ "queue": { "delete": "Queue löschen", "flush": "Queue flushen", - "info": "In der Mailqueue befinden sich alle E-Mails, welche auf eine Zustellung warten. Sollte eine E-Mail eine längere Zeit innerhalb der Mailqueue stecken wird diese automatisch vom System gelöscht.
    Die Fehlermeldung der jeweiligen Mail gibt aufschluss darüber, warum diese nicht zugestellt werden konnte", + "info": "In der Mailqueue befinden sich alle E-Mails, welche auf eine Zustellung warten. Sollte eine E-Mail eine längere Zeit innerhalb der Mailqueue stecken wird diese automatisch vom System gelöscht.
    Die Fehlermeldung der jeweiligen Mail gibt Aufschluss darüber, warum diese nicht zugestellt werden konnte", "legend": "Funktionen der Mailqueue Aktionen:", "ays": "Soll die derzeitige Queue wirklich komplett bereinigt werden?", "deliver_mail": "Ausliefern", From e26501261e232a1edc3229173eede4862f982625 Mon Sep 17 00:00:00 2001 From: AlexHuebi <39099705+AlexHuebi@users.noreply.github.com> Date: Mon, 11 Sep 2023 20:08:42 +0200 Subject: [PATCH 074/174] "temp" change - removed "git remote set-url" --- update.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/update.sh b/update.sh index 54ddcbc48..95c6478a6 100755 --- a/update.sh +++ b/update.sh @@ -888,7 +888,7 @@ done [[ -f data/conf/nginx/ZZZ-ejabberd.conf ]] && rm data/conf/nginx/ZZZ-ejabberd.conf # Silently fixing remote url from andryyy to mailcow -git remote set-url origin https://github.com/mailcow/mailcow-dockerized +# git remote set-url origin https://github.com/mailcow/mailcow-dockerized echo -e "\e[32mCommitting current status...\e[0m" [[ -z "$(git config user.name)" ]] && git config user.name moo [[ -z "$(git config user.email)" ]] && git config user.email moo@cow.moo @@ -1021,4 +1021,4 @@ fi # echo # git reflog --color=always | grep "Before update on " # echo -# echo "Use \"git reset --hard hash-on-the-left\" and run $COMPOSE_COMMAND up -d afterwards." \ No newline at end of file +# echo "Use \"git reset --hard hash-on-the-left\" and run $COMPOSE_COMMAND up -d afterwards." From a8930e8060104a3b943887d7a579be2838154cce Mon Sep 17 00:00:00 2001 From: AlexHuebi <39099705+AlexHuebi@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:39:07 +0200 Subject: [PATCH 075/174] fixed remote url override --- update.sh | 14 ++++++++++++++ 1 file changed, 14 insertions(+) diff --git a/update.sh b/update.sh index 95c6478a6..a379ee306 100755 --- a/update.sh +++ b/update.sh @@ -887,8 +887,22 @@ done [[ -f data/conf/nginx/ZZZ-ejabberd.conf ]] && rm data/conf/nginx/ZZZ-ejabberd.conf + # Silently fixing remote url from andryyy to mailcow # git remote set-url origin https://github.com/mailcow/mailcow-dockerized + +DEFAULT_REPO=https://github.com/mailcow/mailcow-dockerized +CURRENT_REPO=$(git remote get-url origin) +if ["$CURRENT_REPO" != "$DEFAULT_REPO"] + echo "The Repository currently used is not the default Mailcow Repository." + echo "Currently Repository: $CURRENT_REPO" + echo "Default Repository: $DEFAULT_REPO" + read -r -p "Should it be changed back to default? [y/N] " repo_response + if [[ "$repo_response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + git remote set-url origin $DEFAULT_REPO + fi +fi + echo -e "\e[32mCommitting current status...\e[0m" [[ -z "$(git config user.name)" ]] && git config user.name moo [[ -z "$(git config user.email)" ]] && git config user.email moo@cow.moo From d098e7b9e6c73e823da5dd09bbf958aee523d874 Mon Sep 17 00:00:00 2001 From: AlexHuebi <39099705+AlexHuebi@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:42:43 +0200 Subject: [PATCH 076/174] fixed remote url override --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index a379ee306..6ffc06f8b 100755 --- a/update.sh +++ b/update.sh @@ -893,7 +893,7 @@ done DEFAULT_REPO=https://github.com/mailcow/mailcow-dockerized CURRENT_REPO=$(git remote get-url origin) -if ["$CURRENT_REPO" != "$DEFAULT_REPO"] +if ["$CURRENT_REPO" != "$DEFAULT_REPO"]; then echo "The Repository currently used is not the default Mailcow Repository." echo "Currently Repository: $CURRENT_REPO" echo "Default Repository: $DEFAULT_REPO" From 88fbec1e5383491a2df04117516882be4d07d996 Mon Sep 17 00:00:00 2001 From: AlexHuebi <39099705+AlexHuebi@users.noreply.github.com> Date: Mon, 11 Sep 2023 21:43:52 +0200 Subject: [PATCH 077/174] fixed remote url override --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index 6ffc06f8b..db0db3b43 100755 --- a/update.sh +++ b/update.sh @@ -893,7 +893,7 @@ done DEFAULT_REPO=https://github.com/mailcow/mailcow-dockerized CURRENT_REPO=$(git remote get-url origin) -if ["$CURRENT_REPO" != "$DEFAULT_REPO"]; then +if [ "$CURRENT_REPO" != "$DEFAULT_REPO" ]; then echo "The Repository currently used is not the default Mailcow Repository." echo "Currently Repository: $CURRENT_REPO" echo "Default Repository: $DEFAULT_REPO" From 5ae9605e7747d2588609f9b34245264c03a811ac Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 12 Sep 2023 12:19:46 +0200 Subject: [PATCH 078/174] [Rspamd] domain-wide-footer add jinja templating --- data/conf/rspamd/lua/rspamd.local.lua | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 3d4716009..eb1659b36 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -505,6 +505,7 @@ rspamd_config:register_symbol({ type = 'prefilter', callback = function(task) local lua_mime = require "lua_mime" + local lua_util = require "lua_util" local rspamd_logger = require "rspamd_logger" local rspamd_redis = require "rspamd_redis" local ucl = require "ucl" @@ -542,6 +543,15 @@ rspamd_config:register_symbol({ if footer and type(footer) == "table" and (footer.html or footer.plain) then rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain) + local replacements = { + email = uname + } + if footer.html then + footer.html = lua_util.jinja_template(footer.html, replacements, true) + end + if footer.plain then + footer.plain = lua_util.jinja_template(footer.plain, replacements, true) + end -- add footer local out = {} From e02a92a0d072e95b3dbfdcc54829b96badbdf8b4 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:40:44 +0200 Subject: [PATCH 079/174] Update docker/build-push-action action to v5 (#5415) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rebuild_backup_image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index f22662eda..4fe94ead5 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -26,7 +26,7 @@ jobs: password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }} - name: Build and push - uses: docker/build-push-action@v4 + uses: docker/build-push-action@v5 with: context: . platforms: linux/amd64,linux/arm64 From f86f5657d91132047daf5d4c487e7ce73f816b09 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:41:00 +0200 Subject: [PATCH 080/174] Update docker/login-action action to v3 (#5416) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rebuild_backup_image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index 4fe94ead5..7f05d8148 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -20,7 +20,7 @@ jobs: uses: docker/setup-buildx-action@v2 - name: Login to Docker Hub - uses: docker/login-action@v2 + uses: docker/login-action@v3 with: username: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_USERNAME }} password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }} From 33de78845380dc11040b08a3d8b62a7852326bf9 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:41:09 +0200 Subject: [PATCH 081/174] Update docker/setup-qemu-action action to v3 (#5418) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rebuild_backup_image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index 7f05d8148..65c4c2e5c 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -14,7 +14,7 @@ jobs: uses: actions/checkout@v4 - name: Set up QEMU - uses: docker/setup-qemu-action@v2 + uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx uses: docker/setup-buildx-action@v2 From 160c9caee35a79058dd79f8ea45ec3518533a048 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 12 Sep 2023 17:41:16 +0200 Subject: [PATCH 082/174] Update docker/setup-buildx-action action to v3 (#5417) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/rebuild_backup_image.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index 65c4c2e5c..649d76a13 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -17,7 +17,7 @@ jobs: uses: docker/setup-qemu-action@v3 - name: Set up Docker Buildx - uses: docker/setup-buildx-action@v2 + uses: docker/setup-buildx-action@v3 - name: Login to Docker Hub uses: docker/login-action@v3 From 2111115a7329300e0c0433fe6c238bb1f7a48c3e Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 13 Sep 2023 12:42:12 +0200 Subject: [PATCH 083/174] [Rspamd] domain-wide-footer add more template vars --- data/conf/rspamd/lua/rspamd.local.lua | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index eb1659b36..95b3d4092 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -543,8 +543,21 @@ rspamd_config:register_symbol({ if footer and type(footer) == "table" and (footer.html or footer.plain) then rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain) + + local envfrom_mime = task:get_from(2) + local from_name = "" + if envfrom_mime and envfrom_mime[1].name then + from_name = envfrom_mime[1].name + elseif envfrom and envfrom[1].name then + from_name = envfrom[1].name + end + local replacements = { - email = uname + auth_user = uname, + from_user = envfrom[1].user, + from_name = from_name, + from_addr = envfrom[1].addr, + from_domain = envfrom[1].domain:lower() } if footer.html then footer.html = lua_util.jinja_template(footer.html, replacements, true) From 8d792fbd624ce7d23ae8bcf88b49e28d654c3e2e Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 13 Sep 2023 13:03:46 +0200 Subject: [PATCH 084/174] [Rspamd] domain-wide-footer update description --- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/templates/edit/domain.twig | 7 ++++++- 3 files changed, 8 insertions(+), 3 deletions(-) diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index d0c494da5..d073c45c5 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -583,7 +583,7 @@ "domain_admin": "Domain-Administrator bearbeiten", "domain_footer": "Domain wide footer", "domain_footer_html": "HTML footer", - "domain_footer_info": "Domain wide footer werden allen E-Mails hinzugefügt, die von der angegebenen Domain gesendet werden.", + "domain_footer_info": "Domain wide footer werden allen ausgehenden E-Mails hinzugefügt, die einer Adresse innerhalb dieser Domain gehört.
    Die folgenden Variablen können für den Footer benutzt werden:", "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain Speicherplatz gesamt (MiB)", "domains": "Domains", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index c8dded338..3896a79a4 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -585,7 +585,7 @@ "domain_admin": "Edit domain administrator", "domain_footer": "Domain wide footer", "domain_footer_html": "HTML footer", - "domain_footer_info": "Domain wide footers will be added to all emails sent from the specified domain.", + "domain_footer_info": "Domain-wide footers are added to all outgoing emails associated with an address within this domain.
    The following variables can be used for the footer:", "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain quota", "domains": "Domains", diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 997788df7..527a312c8 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -281,7 +281,12 @@

    {{ lang.edit.domain_footer }}

    {{ lang.edit.domain_footer_info|raw }}

    -
    +
    {= auth_user =}   - Authenticated Username specified by an MTA
    +{= from_user =}   - Parsed user part of email headers, e.g for "moo@mailcow.tld" it returns "moo"
    +{= from_name =}   - Parsed name of email headers, e.g for "Mailcow <moo@mailcow.tld>" it returns "Mailcow"
    +{= from_addr =}   - Parsed address part of email headers
    +{= from_domain =} - Parsed domain part of email headers
    +
    From acee74282217b07d858dba92f73a2cb2bffdaffc Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Wed, 13 Sep 2023 15:08:07 +0200 Subject: [PATCH 085/174] [Web] move domain-wide-footer vars info to lang files --- data/web/lang/lang.en-gb.json | 7 +++++++ data/web/templates/edit/domain.twig | 10 +++++----- 2 files changed, 12 insertions(+), 5 deletions(-) diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 3896a79a4..22475bb28 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -586,6 +586,13 @@ "domain_footer": "Domain wide footer", "domain_footer_html": "HTML footer", "domain_footer_info": "Domain-wide footers are added to all outgoing emails associated with an address within this domain.
    The following variables can be used for the footer:", + "domain_footer_info_vars": { + "auth_user": "{= auth_user =} - Authenticated Username specified by an MTA", + "from_user": "{= from_user =} - From user part of envelope, e.g for \"moo@mailcow.tld\" it returns \"moo\"", + "from_name": "{= from_name =} - From name of envelope, e.g for \"Mailcow <moo@mailcow.tld>\" it returns \"Mailcow\"", + "from_addr": "{= from_addr =} - From address part of envelope", + "from_domain": "{= from_domain =} - From domain part of envelope" + }, "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain quota", "domains": "Domains", diff --git a/data/web/templates/edit/domain.twig b/data/web/templates/edit/domain.twig index 527a312c8..5e9eb54be 100644 --- a/data/web/templates/edit/domain.twig +++ b/data/web/templates/edit/domain.twig @@ -281,11 +281,11 @@

    {{ lang.edit.domain_footer }}

    {{ lang.edit.domain_footer_info|raw }}

    -
    {= auth_user =}   - Authenticated Username specified by an MTA
    -{= from_user =}   - Parsed user part of email headers, e.g for "moo@mailcow.tld" it returns "moo"
    -{= from_name =}   - Parsed name of email headers, e.g for "Mailcow <moo@mailcow.tld>" it returns "Mailcow"
    -{= from_addr =}   - Parsed address part of email headers
    -{= from_domain =} - Parsed domain part of email headers
    +
    {{ lang.edit.domain_footer_info_vars.auth_user }}
    +{{ lang.edit.domain_footer_info_vars.from_user }}
    +{{ lang.edit.domain_footer_info_vars.from_name }}
    +{{ lang.edit.domain_footer_info_vars.from_addr }}
    +{{ lang.edit.domain_footer_info_vars.from_domain }}
    From 1a1955c1c23d591856982abb964475ff395c3084 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 16 Sep 2023 09:09:40 +0000 Subject: [PATCH 086/174] Update dependency nextcloud/server to v27.1.0 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 6d7c7953c..dc10e4ce7 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.0.2 +NEXTCLOUD_VERSION=27.1.0 echo -ne "Checking prerequisites..." sleep 1 From e5752755d157798c64352a11bcb15da6b9f92582 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 26 Sep 2023 20:29:47 +0200 Subject: [PATCH 087/174] Update dependency nextcloud/server to v27.1.1 (#5426) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index dc10e4ce7..fed98e4e0 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.1.0 +NEXTCLOUD_VERSION=27.1.1 echo -ne "Checking prerequisites..." sleep 1 From 69d15df22187452ea6290e6cea85d03fa315099e Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 27 Sep 2023 16:10:10 +0200 Subject: [PATCH 088/174] [SOGo] Update to 5.9.0 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index ac45857fe..0137413d5 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -170,7 +170,7 @@ services: - phpfpm sogo-mailcow: - image: mailcow/sogo:1.118 + image: mailcow/sogo:1.119 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From b4a56052c564fd332ffd93740eb5b5b0e5aa8535 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Wed, 27 Sep 2023 17:56:21 +0200 Subject: [PATCH 089/174] [Web] Updated lang.nl-nl.json (#5431) Co-authored-by: Nick Bouwhuis --- data/web/lang/lang.nl-nl.json | 94 +++++++++++++++++++++++++++++++++-- 1 file changed, 89 insertions(+), 5 deletions(-) diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index 4c2ea0b17..8dcbd9506 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -102,7 +102,9 @@ "timeout2": "Time-out voor verbinding met lokale hosts", "username": "Gebruikersnaam", "validate": "Verifieer", - "validation_success": "Succesvol geverifieerd" + "validation_success": "Succesvol geverifieerd", + "tags": "Tags", + "bcc_dest_format": "BCC-bestemming moet één geldig e-mailadres zijn.
    Als u een kopie naar meerdere adressen wilt sturen, maak dan een alias aan en gebruik die hier." }, "admin": { "access": "Toegang", @@ -310,7 +312,32 @@ "upload": "Upload", "username": "Gebruikersnaam", "validate_license_now": "Valideer licentie", - "verify": "Verifieer" + "verify": "Verifieer", + "logo_normal_label": "Normaal", + "logo_dark_label": "Omgekeerd voor donkere modus", + "cors_settings": "CORS instellingen", + "is_mx_based": "MX gebasseerd", + "password_length": "Wachtwoordlengte", + "password_policy": "Wachtwoordbeleid", + "password_policy_chars": "Moet tenminste één alfanumeriek karakter bevatten", + "password_policy_length": "Minimale wachtwoord lengte is %d", + "ip_check": "IP controle", + "ip_check_disabled": "IP controle is uitgeschakeld. Je kan het inschakelen onder
    Systeem > Configuratie > Opties > Aanpassen", + "oauth2_apps": "OAuth2 applicaties", + "oauth2_add_client": "Voeg OAuth2 client toe", + "options": "Opties", + "password_policy_lowerupper": "Moet hoofdletters en kleine letters bevatten", + "password_policy_numbers": "Moet ten minste één nummer bevatten", + "password_policy_special_chars": "Moet tenminste één speciaal teken bevatten", + "relay_rcpt": "\"Aan:\" adres", + "rsettings_preset_4": "Rspamd voor domein uitschakelen", + "service": "Dienst", + "success": "Succes", + "admins": "Administrators", + "admins_ldap": "LDAP administrators", + "api_read_only": "Alleen-lezen toegang", + "api_read_write": "Lees en schrijf toegang", + "login_time": "Login tijd" }, "danger": { "access_denied": "Toegang geweigerd of ongeldige gegevens", @@ -429,7 +456,14 @@ "username_invalid": "Gebruikersnaam %s kan niet worden gebruikt", "validity_missing": "Wijs een geldigheidstermijn toe", "value_missing": "Niet alle waarden zijn ingevuld", - "yotp_verification_failed": "Yubico OTP-verificatie mislukt: %s" + "yotp_verification_failed": "Yubico OTP-verificatie mislukt: %s", + "cors_invalid_method": "Ongeldige Allow-Method opgegeven", + "webauthn_authenticator_failed": "De geselecteerde authenticator kon niet wordcen gevonden", + "webauthn_publickey_failed": "Er was geen publieke sleutel opgeslagen voor de geselecteerde authenticator", + "demo_mode_enabled": "Demo modus is ingeschakeld", + "template_exists": "Sjabloon %s bestaat al", + "template_id_invalid": "Sjabloon ID %s ongeldig", + "template_name_invalid": "Sjabloon naam ongeldig" }, "debug": { "chart_this_server": "Grafiek (deze server)", @@ -452,7 +486,25 @@ "uptime": "Uptime", "started_on": "Gestart op", "static_logs": "Statische logs", - "system_containers": "Systeem & containers" + "system_containers": "Systeem & containers", + "container_running": "Actief", + "container_disabled": "Container gestopt of uitgeschakeld", + "container_stopped": "Gestopt", + "current_time": "Systeemtijd", + "error_show_ip": "Kon het publieke IP adres niet resolven", + "login_time": "Tijd", + "memory": "Geheugen", + "show_ip": "Toon publiek IP", + "success": "Succes", + "timezone": "Tijdzone", + "update_available": "Er is een update beschikbaar", + "no_update_available": "Het systeem heeft de laatste versie", + "update_failed": "Kon niet op updates controleren", + "username": "Gebruikersnaam", + "wip": "Momenteel werk in uitvoering", + "architecture": "Architectuur", + "cores": "Kernen", + "service": "Dienst" }, "diagnostics": { "cname_from_a": "Waarde afgeleid van een A- of AAAA-vermelding.", @@ -567,7 +619,15 @@ "title": "Wijzig object", "unchanged_if_empty": "Laat leeg wanneer ongewijzigd", "username": "Gebruikersnaam", - "validate_save": "Verifieer en sla op" + "validate_save": "Verifieer en sla op", + "domain_footer_info": "Domeinwijde voetteksten worden toegevoegd aan alle uitgaande e-mails die zijn gekoppeld aan een adres binnen dit domein.
    De volgende variabelen kunnen worden gebruikt voor de voettekst:", + "admin": "Bewerk administrator", + "app_passwd_protocols": "Toegestane protocollen voor app wachtwoord", + "created_on": "Gemaakt op", + "acl": "ACL (Toestemming)", + "domain_footer": "Domeinbreede footer", + "domain_footer_html": "HTML footer", + "mailbox_relayhost_info": "Wordt alleen toegepast op de mailbox en directe aliassen, maar heft een domein relayhost op." }, "footer": { "cancel": "Annuleren", @@ -1082,5 +1142,29 @@ "quota_exceeded_scope": "Domeinquota overschreden: Voor dit domein kunnen uitsluitend onbeperkte mailboxen aangemaakt worden.", "session_token": "Token ongeldig: komt niet overeen", "session_ua": "Token ongeldig: gebruikersagentvalidatie mislukt" + }, + "datatables": { + "emptyTable": "Geen data beschikbaar in tabel", + "expand_all": "Alles uitbreiden", + "paginate": { + "last": "Laatste", + "next": "Volgende", + "previous": "Vorige", + "first": "Eerste" + }, + "aria": { + "sortAscending": ": activeer om kolommen oplopend te sorteren", + "sortDescending": ": activeer om kolommen aflopend te sorteren" + }, + "collapse_all": "Alle samenvoegen", + "decimal": ".", + "info": "_START_ tot _END_ van _TOTAL_ worden getoond", + "infoEmpty": "0 tot 0 van 0 items worden getoond", + "thousands": ",", + "lengthMenu": "Toon _MENU_ items", + "loadingRecords": "Laden...", + "processing": "Wachten alstublieft..", + "search": "Zoeken:", + "zeroRecords": "Geen overeenkomsten gevonden" } } From b1c2ffba6ebb92cd130802a60ccf9d70dd945a83 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 27 Sep 2023 18:34:53 +0200 Subject: [PATCH 090/174] mailcow.github.io -> docs.mailcow.email --- .github/ISSUE_TEMPLATE/config.yml | 2 +- CONTRIBUTING.md | 4 ++-- README.md | 2 +- data/web/_status.502.html | 2 +- data/web/lang/lang.cs-cz.json | 2 +- data/web/lang/lang.da-dk.json | 2 +- data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- data/web/lang/lang.fr-fr.json | 2 +- data/web/lang/lang.it-it.json | 2 +- data/web/lang/lang.nl-nl.json | 2 +- data/web/lang/lang.ro-ro.json | 2 +- data/web/lang/lang.ru-ru.json | 2 +- data/web/lang/lang.sk-sk.json | 2 +- data/web/lang/lang.sv-se.json | 2 +- data/web/lang/lang.uk-ua.json | 2 +- data/web/lang/lang.zh-cn.json | 2 +- data/web/lang/lang.zh-tw.json | 2 +- data/web/templates/user/tab-user-auth.twig | 2 +- generate_config.sh | 12 ++++++------ 20 files changed, 26 insertions(+), 26 deletions(-) diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml index 51d037009..dcda8f021 100644 --- a/.github/ISSUE_TEMPLATE/config.yml +++ b/.github/ISSUE_TEMPLATE/config.yml @@ -1,7 +1,7 @@ blank_issues_enabled: false contact_links: - name: ❓ Community-driven support - url: https://mailcow.github.io/mailcow-dockerized-docs/#get-support + url: https://docs.mailcow.email/#get-support about: Please use the community forum for questions or assistance - name: 🚨 Report a security vulnerability url: https://www.servercow.de/anfrage?lang=en diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index 9cdc6d64c..920dd4f3c 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -3,7 +3,7 @@ When a problem occurs, then always for a reason! What you want to do in such a c 1. Read your logs; follow them to see what the reason for your problem is. 2. Follow the leads given to you in your logfiles and start investigating. 3. Restarting the troubled service or the whole stack to see if the problem persists. -4. Read the [documentation](https://mailcow.github.io/mailcow-dockerized-docs/) of the troubled service and search its bugtracker for your problem. +4. Read the [documentation](https://docs.mailcow.email/) of the troubled service and search its bugtracker for your problem. 5. Search our [issues](https://github.com/mailcow/mailcow-dockerized/issues) for your problem. 6. [Create an issue](https://github.com/mailcow/mailcow-dockerized/issues/new/choose) over at our GitHub repository if you think your problem might be a bug or a missing feature you badly need. But please make sure, that you include **all the logs** and a full description to your problem. -7. Ask your questions in our community-driven [support channels](https://mailcow.github.io/mailcow-dockerized-docs/#community-support-and-chat). +7. Ask your questions in our community-driven [support channels](https://docs.mailcow.email/#community-support-and-chat). diff --git a/README.md b/README.md index c15b8ef06..2dacac9ae 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Or just spread the word: moo. ## Info, documentation and support -Please see [the official documentation](https://mailcow.github.io/mailcow-dockerized-docs/) for installation and support instructions. 🐄 +Please see [the official documentation](https://docs.mailcow.email/) for installation and support instructions. 🐄 🐛 **If you found a critical security issue, please mail us to [info at servercow.de](mailto:info@servercow.de).** diff --git a/data/web/_status.502.html b/data/web/_status.502.html index 35a66ba99..c8a9b7022 100644 --- a/data/web/_status.502.html +++ b/data/web/_status.502.html @@ -20,6 +20,6 @@
    BACKUP_LOCATION=/tmp/ ./helper-scripts/backup_and_restore.sh backup all
    docker compose down --volumes ; docker compose up -d

    Make sure your timezone is correct. Use "America/New_York" for example, do not use spaces. Check here for a list.

    -
    Click to learn more about getting support. +
    Click to learn more about getting support. diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index ee0a952ff..d8ec9bf6b 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -515,7 +515,7 @@ "dns_records": "DNS záznamy", "dns_records_24hours": "Upozornění: Změnám v systému DNS může trvat až 24 hodin, než se zde správně zobrazí jejich aktuální stav. Můžete zde snadno zjistit, jak nastavit DNS záznamy a zda jsou všechny záznamy správně uloženy.", "dns_records_data": "Správný záznam", - "dns_records_docs": "Přečtěte si prosím dokumentaci.", + "dns_records_docs": "Přečtěte si prosím dokumentaci.", "dns_records_name": "Název", "dns_records_status": "Současný stav", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.da-dk.json b/data/web/lang/lang.da-dk.json index 5846181b4..33629bbeb 100644 --- a/data/web/lang/lang.da-dk.json +++ b/data/web/lang/lang.da-dk.json @@ -459,7 +459,7 @@ "cname_from_a": "Værdi afledt af A / AAAA-post. Dette understøttes, så længe posten peger på den korrekte ressource.", "dns_records": "DNS-poster", "dns_records_24hours": "Bemærk, at ændringer, der foretages i DNS, kan tage op til 24 timer for at få deres aktuelle status korrekt reflekteret på denne side. Det er beregnet som en måde for dig let at se, hvordan du konfigurerer dine DNS-poster og kontrollere, om alle dine poster er korrekt gemt i DNS.", - "dns_records_docs": "Se også dokumentationen.", + "dns_records_docs": "Se også dokumentationen.", "dns_records_data": "Korrekte data", "dns_records_name": "Navn", "dns_records_status": "Nuværende tilstand", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index d073c45c5..ee3d225c0 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -548,7 +548,7 @@ "dns_records": "DNS-Einträge", "dns_records_24hours": "Bitte beachten Sie, dass es bis zu 24 Stunden dauern kann, bis Änderungen an Ihren DNS-Einträgen als aktueller Status auf dieser Seite dargestellt werden. Diese Seite ist nur als Hilfsmittel gedacht, um die korrekten Werte für DNS-Einträge anzuzeigen und zu überprüfen, ob die Daten im DNS hinterlegt sind.", "dns_records_data": "Korrekte Daten", - "dns_records_docs": "Die Online-Dokumentation enthält weitere Informationen zur DNS-Konfiguration.", + "dns_records_docs": "Die Online-Dokumentation enthält weitere Informationen zur DNS-Konfiguration.", "dns_records_name": "Name", "dns_records_status": "Aktueller Status", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 22475bb28..63b6e80db 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -550,7 +550,7 @@ "dns_records": "DNS Records", "dns_records_24hours": "Please note that changes made to DNS may take up to 24 hours to correctly have their current state reflected on this page. It is intended as a way for you to easily see how to configure your DNS records and to check whether all your records are correctly stored in DNS.", "dns_records_data": "Correct Data", - "dns_records_docs": "Please also consult the documentation.", + "dns_records_docs": "Please also consult the documentation.", "dns_records_name": "Name", "dns_records_status": "Current State", "dns_records_type": "Type", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 484205504..ca67b592d 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -479,7 +479,7 @@ "cname_from_a": "Valeur dérivée de l’enregistrement A/AAAA. Ceci est supporté tant que l’enregistrement indique la bonne ressource.", "dns_records": "Enregistrements DNS", "dns_records_24hours": "Veuillez noter que les modifications apportées au DNS peuvent prendre jusqu’à 24 heures pour que leurs états actuels soient correctement reflétés sur cette page. Il est conçu comme un moyen pour vous de voir facilement comment configurer vos enregistrements DNS et de vérifier si tous vos enregistrements sont correctement stockés dans les DNS.", - "dns_records_docs": "Veuillez également consulter la documentation.", + "dns_records_docs": "Veuillez également consulter la documentation.", "dns_records_data": "Données correcte", "dns_records_name": "Nom", "dns_records_status": "Etat courant", diff --git a/data/web/lang/lang.it-it.json b/data/web/lang/lang.it-it.json index 8831358e1..6783dfed8 100644 --- a/data/web/lang/lang.it-it.json +++ b/data/web/lang/lang.it-it.json @@ -506,7 +506,7 @@ "dns_records": "Record DNS", "dns_records_24hours": "Tieni presente che le modifiche apportate ai record DNS potrebbero richiedere fino a 24 ore per poter essere visualizzate correttamente in questa pagina. Tutto ciò è da intendersi come un modo per voi di vedere come configurare i record DNS e per controllare se tutti i record DNS sono stati inseriti correttamente.", "dns_records_data": "Dati corretti", - "dns_records_docs": "Si prega di consultare anche la documentazione.", + "dns_records_docs": "Si prega di consultare anche la documentazione.", "dns_records_name": "Nome", "dns_records_status": "Stato attuale", "dns_records_type": "Tipo", diff --git a/data/web/lang/lang.nl-nl.json b/data/web/lang/lang.nl-nl.json index 8dcbd9506..efffa1d7e 100644 --- a/data/web/lang/lang.nl-nl.json +++ b/data/web/lang/lang.nl-nl.json @@ -510,7 +510,7 @@ "cname_from_a": "Waarde afgeleid van een A- of AAAA-vermelding.", "dns_records": "DNS-configuratie", "dns_records_24hours": "Houd er rekening mee dat wijzigingen aan DNS tot wel 24 uur in beslag kunnen nemen voordat ze op deze pagina worden weergegeven. Deze informatie is bedoeld om gemakkelijk te bekijken of de DNS-configuratie aan de eisen voldoet.", - "dns_records_docs": "Raadpleeg ook de documentatie.", + "dns_records_docs": "Raadpleeg ook de documentatie.", "dns_records_data": "Correcte gegevens", "dns_records_name": "Naam", "dns_records_status": "Huidige staat", diff --git a/data/web/lang/lang.ro-ro.json b/data/web/lang/lang.ro-ro.json index 1d7eb8ba4..5c7b29b0e 100644 --- a/data/web/lang/lang.ro-ro.json +++ b/data/web/lang/lang.ro-ro.json @@ -504,7 +504,7 @@ "cname_from_a": "Valoare derivată din înregistrarea A/AAAA. Acest lucru este acceptat atâta timp cât înregistrarea indică resursele corecte.", "dns_records": "Înregistrări DNS", "dns_records_24hours": "Rețineți că modificările aduse DNS-ului pot dura până la 24 de ore pentru a reflecta corect starea lor curentă pe această pagină. Acest mecanism este conceput ca o modalitate să vezi ușor cum să îți configurezi înregistrările DNS și să verifici dacă toate înregistrările sunt stocate corect în DNS.", - "dns_records_docs": "Vă rugăm să consultați și documentația.", + "dns_records_docs": "Vă rugăm să consultați și documentația.", "dns_records_data": "Date corecte", "dns_records_name": "Nume", "dns_records_status": "Stare curentă", diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index dccaa2041..87452a092 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -500,7 +500,7 @@ "dns_records": "Записи DNS", "dns_records_24hours": "Обратите внимание, что для внесения изменений в DNS может потребоваться до 24 часов, чтобы правильно отобразить их текущее состояние на этой странице. Эта страница предназначен для того, чтобы вы могли легко увидеть, как настроить записи DNS и проверить, все ли записи правильно занесены в DNS.", "dns_records_data": "Значение", - "dns_records_docs": "Пожалуйста, ознакомьтесь с документацией.", + "dns_records_docs": "Пожалуйста, ознакомьтесь с документацией.", "dns_records_name": "Название", "dns_records_status": "Статус", "dns_records_type": "Тип", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 072d9ce38..20694e9c0 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -512,7 +512,7 @@ "dns_records": "DNS záznamy", "dns_records_24hours": "Berte prosím do úvahy, že zmeny v DNS môžu trvať až 24 hodín, aby sa zmeny prejavili na tejto stránke. Pre jednoduchosť DNS konfigurácie môžete použiť údaje uvedené nižšie, prípadne skontrolovať tak správnosť záznamov v DNS.", "dns_records_data": "Správne dáta", - "dns_records_docs": "Pozrite si prosím dokumentáciu.", + "dns_records_docs": "Pozrite si prosím dokumentáciu.", "dns_records_name": "Meno", "dns_records_status": "Súčasný stav", "dns_records_type": "Typ", diff --git a/data/web/lang/lang.sv-se.json b/data/web/lang/lang.sv-se.json index 31bc0ab33..ba97e705d 100644 --- a/data/web/lang/lang.sv-se.json +++ b/data/web/lang/lang.sv-se.json @@ -473,7 +473,7 @@ "cname_from_a": "Värde härstammar från A/AAAA-uppslaget. Detta stöds så länge som uppslaget pekar mot rätt resurs.", "dns_records": "DNS-uppslag", "dns_records_24hours": "Observera att ändringar gjorda i DNS kan ta upp till 24 timmar innan det visas korrekt på denna sida. Syftet med sidan är att enkelt se hur DNS-uppslagen är konfigurerade. Det är lätt att kontrollera att DNS-uppslagen är korrekt uppsatta.", - "dns_records_docs": "Se även dokumentationen.", + "dns_records_docs": "Se även dokumentationen.", "dns_records_data": "Korrektdata", "dns_records_name": "Namn", "dns_records_status": "Nuvarande status", diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 8ebad3896..6cb439f73 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -521,7 +521,7 @@ "cname_from_a": "Значення, отримане із запису A/AAAA. Це підтримується, поки запис вказує на правильний ресурс.", "dns_records": "Записи DNS", "dns_records_data": "Значення", - "dns_records_docs": "Також перегляньте документацію.", + "dns_records_docs": "Також перегляньте документацію.", "dns_records_name": "Назва", "dns_records_status": "Статус", "optional": "Цей запис необов'язковий.", diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json index 428e5934e..b1aacf5c8 100644 --- a/data/web/lang/lang.zh-cn.json +++ b/data/web/lang/lang.zh-cn.json @@ -494,7 +494,7 @@ "dns_records": "DNS 记录", "dns_records_24hours": "请注意 DNS 记录的更改可能需要24小时才可以使此页面的当前状态显示正确。此页面为你提供了一个可以便捷查询如何配置 DNS 记录以及检查你的 DNS 记录是否正确的方式。", "dns_records_data": "正确数据", - "dns_records_docs": "请同时也参考这个文档.", + "dns_records_docs": "请同时也参考这个文档.", "dns_records_name": "名称", "dns_records_status": "当前状态", "dns_records_type": "类型", diff --git a/data/web/lang/lang.zh-tw.json b/data/web/lang/lang.zh-tw.json index d973157cc..2c9d61fde 100644 --- a/data/web/lang/lang.zh-tw.json +++ b/data/web/lang/lang.zh-tw.json @@ -488,7 +488,7 @@ "dns_records": "DNS 紀錄", "dns_records_24hours": "請注意 DNS 紀錄的更改可能需要 24 小時才能正確顯示於此頁面。此頁面的目的是為了讓你可以輕鬆的了解如何設定 DNS 紀錄並檢查 DNS 是否設定正確。", "dns_records_data": "正確值", - "dns_records_docs": "請同時另外查看 文件.", + "dns_records_docs": "請同時另外查看 文件.", "dns_records_name": "名稱", "dns_records_status": "目前狀態", "dns_records_type": "類型", diff --git a/data/web/templates/user/tab-user-auth.twig b/data/web/templates/user/tab-user-auth.twig index ab664f7cd..4d55b7090 100644 --- a/data/web/templates/user/tab-user-auth.twig +++ b/data/web/templates/user/tab-user-auth.twig @@ -142,7 +142,7 @@
    -

    [{{ lang.user.client_configuration }}]

    +

    [{{ lang.user.client_configuration }}]

    [{{ lang.user.show_sieve_filters }}]


    diff --git a/generate_config.sh b/generate_config.sh index 127496051..5fdcecc6d 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -34,7 +34,7 @@ if docker compose > /dev/null 2>&1; then echo -e "\e[33mNotice: You´ll have to update this Compose Version via your Package Manager manually!\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" exit 1 fi elif docker-compose > /dev/null 2>&1; then @@ -47,14 +47,14 @@ elif docker-compose > /dev/null 2>&1; then echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" else echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" exit 1 fi fi else echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/i_u_m/i_u_m_install/\e[0m" exit 1 fi @@ -220,7 +220,7 @@ MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} # Password hash algorithm # Only certain password hash algorithm are supported. For a fully list of supported schemes, -# see https://mailcow.github.io/mailcow-dockerized-docs/models/model-passwd/ +# see https://docs.mailcow.email/models/model-passwd/ MAILCOW_PASS_SCHEME=BLF-CRYPT # ------------------------------ @@ -246,7 +246,7 @@ DBROOT=$(LC_ALL=C /dev/null | head -c 28) # IMPORTANT: Do not use port 8081, 9081 or 65510! # Example: HTTP_BIND=1.2.3.4 # For IPv4 leave it as it is: HTTP_BIND= & HTTPS_PORT= -# For IPv6 see https://mailcow.github.io/mailcow-dockerized-docs/post_installation/firststeps-ip_bindings/ +# For IPv6 see https://docs.mailcow.email/post_installation/firststeps-ip_bindings/ HTTP_PORT=80 HTTP_BIND= @@ -450,7 +450,7 @@ DOVECOT_MASTER_PASS= # Optional: Leave empty for none # This value is only used on first order! # Setting it at a later point will require the following steps: -# https://mailcow.github.io/mailcow-dockerized-docs/troubleshooting/debug-reset_tls/ +# https://docs.mailcow.email/troubleshooting/debug-reset_tls/ ACME_CONTACT= # WebAuthn device manufacturer verification From c55c38f77b0807459f29708196fef4147590c4ff Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 30 Sep 2023 14:18:55 +0200 Subject: [PATCH 091/174] Translations update from Weblate (#5434) * [Web] Updated lang.ru-ru.json Co-authored-by: Oleksii Kruhlenko Co-authored-by: milkmaker * [Web] Updated lang.uk-ua.json Co-authored-by: Oleksii Kruhlenko Co-authored-by: milkmaker --------- Co-authored-by: Oleksii Kruhlenko --- data/web/lang/lang.ru-ru.json | 16 ++++++++++++++-- data/web/lang/lang.uk-ua.json | 13 ++++++++++++- 2 files changed, 26 insertions(+), 3 deletions(-) diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index 87452a092..67800f33c 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -618,7 +618,18 @@ "username": "Имя пользователя", "validate_save": "Подтвердить и сохранить", "sogo_access_info": "Единый вход из интерфейса почты продолжает работать. Эта настройка не влияет на доступ ко всем другим службам, а также не удаляет или изменяет существующий профиль пользователя SOGo.", - "app_passwd_protocols": "Разрешенные протоколы для пароля приложения" + "app_passwd_protocols": "Разрешенные протоколы для пароля приложения", + "domain_footer_info": "Нижние колонтитулы на уровне домена добавляются ко всем исходящим электронным письмам, связанным с адресом в этом домене.
    Для нижнего колонтитула можно использовать следующие переменные:", + "domain_footer_info_vars": { + "from_name": "{= from_name =} - Из названия envelope, например, для \"Mailcow <moo@mailcow.tld>\" возвращается \"Mailcow\"", + "auth_user": "{= auth_user =} - Аутентифицированное имя пользователя, указанное MTA", + "from_user": "{= from_user =} - Из пользовательской части envelope, например, для \"moo@mailcow.tld\" возвращается \"moo\"", + "from_addr": "{= from_addr =} - Из адресной части envelope", + "from_domain": "{= from_domain =} - из доменной части envelope" + }, + "domain_footer": "Нижний колонтитул домена", + "domain_footer_html": "HTML нижний колонтитул", + "domain_footer_plain": "ПРОСТОЙ нижний колонтитул" }, "fido2": { "confirm": "Подтвердить", @@ -999,7 +1010,8 @@ "verified_totp_login": "Авторизация TOTP пройдена", "verified_webauthn_login": "Авторизация WebAuthn пройдена", "verified_yotp_login": "Авторизация Yubico OTP пройдена", - "cors_headers_edited": "Настройки CORS сохранены" + "cors_headers_edited": "Настройки CORS сохранены", + "domain_footer_modified": "Изменения в нижнем колонтитуле домена %s сохранены" }, "tfa": { "api_register": "%s использует Yubico Cloud API. Пожалуйста, получите ключ API для вашего ключа здесь", diff --git a/data/web/lang/lang.uk-ua.json b/data/web/lang/lang.uk-ua.json index 6cb439f73..d7f3e3e33 100644 --- a/data/web/lang/lang.uk-ua.json +++ b/data/web/lang/lang.uk-ua.json @@ -642,7 +642,18 @@ "sogo_visible_info": "Впливає лише на об'єкти, які можуть відображатися в SOGo (персональні або загальні псевдоніми, що вказують щонайменше на один локальний поштовий обліковий запис). Зверніть увагу, що якщо функцію вимкнено, користувач не зможе вибрати адресу псевдоніма як відправника в SOGo.", "target_address": "Власники псевдоніма, (розділені комами)", "timeout2": "Тайм-аут для підключення до локального хоста", - "pushover_sound": "Звук" + "pushover_sound": "Звук", + "domain_footer": "Нижній колонтитул домену", + "domain_footer_info": "Нижні колонтитули для всього домену додаються до всіх вихідних електронних листів, пов’язаних з адресою в цьому домені.
    Наступні змінні можна використовувати для нижнього колонтитула:", + "domain_footer_info_vars": { + "from_name": "{= from_name =} - З назви envelope, наприклад, для \"Mailcow <moo@mailcow.tld>\" повертає \"Mailcow\"", + "auth_user": "{= auth_user =} - Аутентифіковане ім'я користувача, вказане MTA", + "from_user": "{= from_user =} - З користувацької частини envelope, наприклад, для \"moo@mailcow.tld\" повертає \"moo\"", + "from_addr": "{= from_addr =} - З адресної частини envelope", + "from_domain": "{= from_domain =} - З доменної частини envelope" + }, + "domain_footer_html": "Нижній колонтитул HTML", + "domain_footer_plain": "ЗВИЧАЙНИЙ нижній колонтитул" }, "fido2": { "confirm": "Підтвердити", From 24ff70759abf4e752161e0604330fd392dc60eb2 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sun, 1 Oct 2023 00:15:00 +0000 Subject: [PATCH 092/174] update postscreen_access.cidr --- data/conf/postfix/postscreen_access.cidr | 62 ++++++++---------------- 1 file changed, 19 insertions(+), 43 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 153cd6894..61aac6443 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Mon Jul 31 10:06:06 UTC 2023 +# Whitelist generated by Postwhite v3.4 on Sun Oct 1 00:14:59 UTC 2023 # https://github.com/stevejenkins/postwhite/ -# 2043 total rules +# 2019 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:8000::/50 permit @@ -113,14 +113,10 @@ 39.156.163.64/29 permit 40.71.187.0/24 permit 40.92.0.0/15 permit +40.92.0.0/16 permit 40.107.0.0/16 permit 40.112.65.63 permit 40.117.80.0/24 permit -41.74.192.0/22 permit -41.74.196.0/22 permit -41.74.200.0/23 permit -41.74.204.0/23 permit -41.74.206.0/24 permit 43.228.184.0/22 permit 44.206.138.57 permit 44.209.42.157 permit @@ -192,8 +188,6 @@ 51.137.58.21 permit 51.140.75.55 permit 51.144.100.179 permit -51.163.158.0/24 permit -51.163.159.21 permit 52.5.230.59 permit 52.27.5.72 permit 52.27.28.47 permit @@ -217,9 +211,9 @@ 52.96.222.194 permit 52.96.222.226 permit 52.96.223.2 permit -52.96.228.130 permit 52.96.229.242 permit 52.100.0.0/14 permit +52.103.0.0/17 permit 52.119.213.144/28 permit 52.160.39.140 permit 52.165.175.144 permit @@ -272,8 +266,6 @@ 62.13.150.0/23 permit 62.13.152.0/23 permit 62.17.146.128/26 permit -62.140.7.0/24 permit -62.140.10.21 permit 62.179.121.0/24 permit 62.201.172.0/27 permit 62.201.172.32/27 permit @@ -300,8 +292,6 @@ 64.127.115.252 permit 64.132.88.0/23 permit 64.132.92.0/24 permit -64.135.77.0/24 permit -64.135.83.0/24 permit 64.147.123.17 permit 64.147.123.18 permit 64.147.123.19 permit @@ -622,6 +612,7 @@ 77.238.189.142 permit 77.238.189.146/31 permit 77.238.189.148/30 permit +81.7.169.128/25 permit 81.223.46.0/27 permit 82.165.159.0/24 permit 82.165.159.0/26 permit @@ -672,9 +663,7 @@ 87.248.117.205 permit 87.253.232.0/21 permit 89.22.108.0/24 permit -91.194.248.0/23 permit 91.211.240.0/22 permit -91.220.42.0/24 permit 94.245.112.0/27 permit 94.245.112.10/31 permit 95.131.104.0/21 permit @@ -1190,17 +1179,16 @@ 99.78.197.208/28 permit 103.2.140.0/22 permit 103.9.96.0/22 permit -103.13.69.0/24 permit 103.28.42.0/24 permit 103.47.204.0/22 permit -103.96.21.0/24 permit -103.96.22.0/24 permit -103.96.23.0/24 permit 103.151.192.0/23 permit 103.168.172.128/27 permit 104.43.243.237 permit 104.44.112.128/25 permit 104.47.0.0/17 permit +104.47.20.0/23 permit +104.47.75.0/24 permit +104.47.108.0/23 permit 104.130.96.0/28 permit 104.130.122.0/23 permit 104.214.25.77 permit @@ -1368,8 +1356,6 @@ 121.244.91.48 permit 122.15.156.182 permit 123.126.78.64/29 permit -124.47.150.0/24 permit -124.47.189.0/24 permit 124.108.96.0/24 permit 124.108.96.24/31 permit 124.108.96.28/31 permit @@ -1396,6 +1382,7 @@ 129.41.169.249 permit 129.80.5.164 permit 129.80.67.121 permit +129.145.74.12 permit 129.146.88.28 permit 129.146.147.105 permit 129.146.236.58 permit @@ -1408,6 +1395,7 @@ 129.159.87.137 permit 129.213.195.191 permit 130.61.9.72 permit +130.162.39.83 permit 130.211.0.0/22 permit 131.253.30.0/24 permit 131.253.121.0/26 permit @@ -1466,8 +1454,6 @@ 146.20.215.0/24 permit 146.20.215.182 permit 146.88.28.0/24 permit -146.101.78.0/24 permit -147.28.36.0/24 permit 147.160.158.0/24 permit 147.243.1.47 permit 147.243.1.48 permit @@ -1477,6 +1463,7 @@ 148.105.0.0/16 permit 148.105.8.0/21 permit 149.72.0.0/16 permit +149.72.248.236 permit 149.97.173.180 permit 150.230.98.160 permit 152.67.105.195 permit @@ -1539,6 +1526,7 @@ 166.78.71.131 permit 167.89.0.0/17 permit 167.89.46.159 permit +167.89.54.103 permit 167.89.64.9 permit 167.89.65.0 permit 167.89.65.53 permit @@ -1556,6 +1544,9 @@ 168.138.5.36 permit 168.138.73.51 permit 168.245.0.0/17 permit +168.245.12.252 permit +168.245.46.9 permit +168.245.127.231 permit 169.148.129.0/24 permit 169.148.131.0/24 permit 170.10.68.0/22 permit @@ -1592,7 +1583,6 @@ 176.32.105.0/24 permit 176.32.127.0/24 permit 178.236.10.128/26 permit -180.189.28.0/24 permit 182.50.76.0/22 permit 182.50.78.64/28 permit 183.240.219.64/29 permit @@ -1600,11 +1590,6 @@ 185.4.122.0/24 permit 185.12.80.0/22 permit 185.58.84.93 permit -185.58.85.0/24 permit -185.58.86.0/24 permit -185.72.128.75 permit -185.72.128.76 permit -185.72.128.80 permit 185.80.93.204 permit 185.80.93.227 permit 185.80.95.31 permit @@ -1682,22 +1667,17 @@ 192.254.113.10 permit 192.254.113.101 permit 192.254.114.176 permit -193.7.206.0/25 permit -193.7.207.0/25 permit 193.109.254.0/23 permit 193.122.128.100 permit +193.123.56.63 permit +194.19.134.0/25 permit 194.64.234.128/27 permit 194.64.234.129 permit -194.104.109.0/24 permit -194.104.110.21 permit -194.104.110.240/28 permit -194.104.111.0/24 permit 194.106.220.0/23 permit 194.113.24.0/22 permit 194.154.193.192/27 permit 195.4.92.0/23 permit 195.54.172.0/23 permit -195.130.217.0/24 permit 195.234.109.226 permit 195.245.230.0/23 permit 198.2.128.0/18 permit @@ -1792,6 +1772,7 @@ 204.92.114.204/31 permit 204.141.32.0/23 permit 204.141.42.0/23 permit +204.220.160.0/20 permit 204.232.168.0/24 permit 205.139.110.0/24 permit 205.201.128.0/20 permit @@ -1832,7 +1813,6 @@ 207.67.98.192/27 permit 207.68.176.0/26 permit 207.68.176.96/27 permit -207.82.80.0/24 permit 207.126.144.0/20 permit 207.171.160.0/19 permit 207.211.30.64/26 permit @@ -1899,7 +1879,6 @@ 209.67.98.46 permit 209.67.98.59 permit 209.85.128.0/17 permit -212.4.136.0/26 permit 212.82.96.0/24 permit 212.82.96.32/27 permit 212.82.96.64/29 permit @@ -1946,8 +1925,6 @@ 212.227.126.128/25 permit 213.46.255.0/24 permit 213.165.64.0/23 permit -213.167.75.0/25 permit -213.167.81.0/25 permit 213.199.128.139 permit 213.199.128.145 permit 213.199.138.181 permit @@ -2006,7 +1983,6 @@ 216.136.162.65 permit 216.136.162.120/29 permit 216.136.168.80/28 permit -216.145.217.0/24 permit 216.145.221.0/24 permit 216.198.0.0/18 permit 216.203.30.55 permit @@ -2039,7 +2015,7 @@ 2620:109:c006:104::/64 permit 2620:109:c006:104::215 permit 2620:109:c00d:104::/64 permit -2620:10d:c090:450::120 permit +2620:10d:c090:400::8:1 permit 2620:10d:c091:400::8:1 permit 2620:119:50c0:207::/64 permit 2620:119:50c0:207::215 permit From ed365c35e716b19d501e74fded1d53a5cde09e82 Mon Sep 17 00:00:00 2001 From: Peter Date: Mon, 2 Oct 2023 20:22:08 +0200 Subject: [PATCH 093/174] Fix renovate.json to allow version extracts --- .github/renovate.json | 2 +- data/Dockerfiles/dovecot/Dockerfile | 4 ++-- data/Dockerfiles/phpfpm/Dockerfile | 12 ++++++------ data/Dockerfiles/sogo/Dockerfile | 2 +- data/Dockerfiles/solr/Dockerfile | 2 +- 5 files changed, 11 insertions(+), 11 deletions(-) diff --git a/.github/renovate.json b/.github/renovate.json index 36b4aec59..e2de9e5cf 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -24,7 +24,7 @@ { "fileMatch": ["(^|/)Dockerfile[^/]*$"], "matchStrings": [ - "#\\srenovate:\\sdatasource=(?.*?) depName=(?.*?)( versioning=(?.*?))?\\s(ENV|ARG) .*?_VERSION=(?.*)\\s" + "#\\srenovate:\\sdatasource=(?.*?) depName=(?.*?)( versioning=(?.*?))?( extractVersion=(?.*?))?\\s(ENV|ARG) .*?_VERSION=(?.*)\\s" ] } ] diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index db3a71b50..fc4501a5f 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -2,9 +2,9 @@ FROM debian:bullseye-slim LABEL maintainer "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive -# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced +# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=^v(?.*)$ ARG DOVECOT=2.3.20 -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ ARG GOSU_VERSION=1.16 ENV LC_ALL C diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index a7a4236b3..6c53f28c8 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -1,17 +1,17 @@ FROM php:8.2-fpm-alpine3.17 LABEL maintainer "The Infrastructure Company GmbH " -# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced +# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$ ARG APCU_PECL_VERSION=5.1.22 -# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced +# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=^v(?.*)$ ARG IMAGICK_PECL_VERSION=3.7.0 -# renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced +# renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ ARG MAILPARSE_PECL_VERSION=3.1.4 -# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced +# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ ARG MEMCACHED_PECL_VERSION=3.2.0 -# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced +# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ ARG REDIS_PECL_VERSION=5.3.7 -# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced +# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=^v(?.*)$ ARG COMPOSER_VERSION=2.5.5 RUN apk add -U --no-cache autoconf \ diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index a1ef95bb4..35e0721ec 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -3,7 +3,7 @@ LABEL maintainer "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/ -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ ARG GOSU_VERSION=1.16 ENV LC_ALL C diff --git a/data/Dockerfiles/solr/Dockerfile b/data/Dockerfiles/solr/Dockerfile index 0c5af1afa..dd465b4d4 100644 --- a/data/Dockerfiles/solr/Dockerfile +++ b/data/Dockerfiles/solr/Dockerfile @@ -2,7 +2,7 @@ FROM solr:7.7-slim USER root -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ ARG GOSU_VERSION=1.16 COPY solr.sh / From 3f2a9b6973a246d92231cd2f7ddeb771413e95e6 Mon Sep 17 00:00:00 2001 From: Florian Hillebrand Date: Tue, 3 Oct 2023 20:54:45 +0200 Subject: [PATCH 094/174] Update ClamAV to latest LTS version 1.0.3 --- data/Dockerfiles/clamd/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index f381e0efd..6d6466643 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,4 +1,4 @@ -FROM clamav/clamav:1.0.1-1_base +FROM clamav/clamav:1.0.3_base LABEL maintainer "André Peters " From 257e104d2b05c9d44a060cb04c36731acfaa0cb3 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 13:21:58 +0000 Subject: [PATCH 095/174] Update dependency nextcloud/server to v27.1.2 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index fed98e4e0..730e61244 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.1.1 +NEXTCLOUD_VERSION=27.1.2 echo -ne "Checking prerequisites..." sleep 1 From 3851a48ea0833c29fcc8c663186d2216cdae3fee Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 5 Oct 2023 15:49:19 +0200 Subject: [PATCH 096/174] Bumped clamd version in compose.yml --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 0137413d5..5adb92b34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,7 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.61 + image: mailcow/clamd:1.62 restart: always depends_on: - unbound-mailcow From 0c0ec7be583e8a07ac63025ce386fcb05a21fcee Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:08:31 +0000 Subject: [PATCH 097/174] Update dependency phpredis/phpredis to v6 Signed-off-by: milkmaker --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 6c53f28c8..72ed60338 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -10,7 +10,7 @@ ARG MAILPARSE_PECL_VERSION=3.1.4 # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ -ARG REDIS_PECL_VERSION=5.3.7 +ARG REDIS_PECL_VERSION=6.0.1 # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=^v(?.*)$ ARG COMPOSER_VERSION=2.5.5 From e67ba60863d5fc4f999caab8a72ce4be3f80ffde Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 5 Oct 2023 16:21:57 +0200 Subject: [PATCH 098/174] Added Colors, cause there fancy :) + Added in generate_config.sh --- generate_config.sh | 21 ++++++++++++++++++--- update.sh | 7 ++++--- 2 files changed, 22 insertions(+), 6 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index d09dae9e6..5c00347d6 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -109,9 +109,24 @@ echo "Press enter to confirm the detected value '[value]' where applicable or en while [ -z "${MAILCOW_HOSTNAME}" ]; do read -p "Mail server hostname (FQDN) - this is not your mail domain, but your mail servers hostname: " -e MAILCOW_HOSTNAME DOTS=${MAILCOW_HOSTNAME//[^.]}; - if [ ${#DOTS} -lt 2 ] && [ ! -z ${MAILCOW_HOSTNAME} ]; then - echo "${MAILCOW_HOSTNAME} is not a FQDN" - MAILCOW_HOSTNAME= + if [ ${#DOTS} -lt 1 ]; then + echo -e "\e[31mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!\e[0m" + sleep 1 + echo "Please change it to a FQDN and redeploy the stack with docker(-)compose up -d" + exit 1 + elif [[ "${MAILCOW_HOSTNAME: -1}" == "." ]]; then + echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is ending with a dot. This is not a valid FQDN!" + exit 1 + elif [ ${#DOTS} -eq 1 ]; then + echo -e "\e[33mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) does not contain a Subdomain. This is not fully tested and may cause issues.\e[0m" + echo "Find more information about why this message exists here: https://github.com/mailcow/mailcow-dockerized/issues/1572" + read -r -p "Do you want to proceed anyway? [y/N] " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + echo "OK. Procceding." + else + echo "OK. Exiting." + exit 1 + fi fi done diff --git a/update.sh b/update.sh index db0db3b43..5204659e1 100755 --- a/update.sh +++ b/update.sh @@ -419,14 +419,15 @@ detect_docker_compose_command [[ ! -f mailcow.conf ]] && { echo "mailcow.conf is missing! Is mailcow installed?"; exit 1;} DOTS=${MAILCOW_HOSTNAME//[^.]}; if [ ${#DOTS} -lt 1 ]; then - echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!" - echo "Please change it to a FQDN and run $COMPOSE_COMMAND down followed by $COMPOSE_COMMAND up -d" + echo -e "\e[31mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is not a FQDN!\e[0m" + sleep 1 + echo "Please change it to a FQDN and redeploy the stack with $COMPOSE_COMMAND up -d" exit 1 elif [[ "${MAILCOW_HOSTNAME: -1}" == "." ]]; then echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) is ending with a dot. This is not a valid FQDN!" exit 1 elif [ ${#DOTS} -eq 1 ]; then - echo "MAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) does not contain a Subdomain. This is not fully tested and may cause issues." + echo -e "\e[33mMAILCOW_HOSTNAME (${MAILCOW_HOSTNAME}) does not contain a Subdomain. This is not fully tested and may cause issues.\e[0m" echo "Find more information about why this message exists here: https://github.com/mailcow/mailcow-dockerized/issues/1572" read -r -p "Do you want to proceed anyway? [y/N] " response if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then From 115d0681a729f554e46cb57031eeca8670e0f73f Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:20:24 +0000 Subject: [PATCH 099/174] Update dependency php/pecl-mail-mailparse to v3.1.6 Signed-off-by: milkmaker --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 6c53f28c8..ca7d629ab 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -6,7 +6,7 @@ ARG APCU_PECL_VERSION=5.1.22 # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=^v(?.*)$ ARG IMAGICK_PECL_VERSION=3.7.0 # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ -ARG MAILPARSE_PECL_VERSION=3.1.4 +ARG MAILPARSE_PECL_VERSION=v3.1.6 # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ From 5de151a966a3f5ee3c8a6bfdf66a54fd3beb0eef Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 6 Oct 2023 00:12:49 +0200 Subject: [PATCH 100/174] change column name --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index 25770ce24..2005ca401 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -290,7 +290,7 @@ 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 row named 'TZ database name' + pay attention for 'Notes' row +# Use the column named 'TZ identifier' + pay attention for the column named 'Notes' TZ=${MAILCOW_TZ} From 3d8f45db43fe1b7b3de852c83bce5aaf93a0f9cc Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 6 Oct 2023 09:17:46 +0000 Subject: [PATCH 101/174] Update dependency composer/composer to v2.6.5 Signed-off-by: milkmaker --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index 6c53f28c8..5dacfc57e 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -12,7 +12,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ ARG REDIS_PECL_VERSION=5.3.7 # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=^v(?.*)$ -ARG COMPOSER_VERSION=2.5.5 +ARG COMPOSER_VERSION=2.6.5 RUN apk add -U --no-cache autoconf \ aspell-dev \ From 33a38e6fde83e10f5a7987fcc624d6edda8e39f2 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 6 Oct 2023 11:31:28 +0200 Subject: [PATCH 102/174] [Web] Avoid setting default ACL on create when nothing is selected --- data/web/inc/functions.mailbox.inc.php | 46 ++++++++++++++++++-------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index fe41028b9..68cb50f1b 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1250,9 +1250,27 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { )); } else { - $stmt = $pdo->prepare("INSERT INTO `user_acl` (`username`) VALUES (:username)"); + $stmt = $pdo->prepare("INSERT INTO `user_acl` + (`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`, + `pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`) + VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset, + :pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds) "); $stmt->execute(array( - ':username' => $username + ':username' => $username, + ':spam_alias' => 0, + ':tls_policy' => 0, + ':spam_score' => 0, + ':spam_policy' => 0, + ':delimiter_action' => 0, + ':syncjobs' => 0, + ':eas_reset' => 0, + ':sogo_profile_reset' => 0, + ':pushover' => 0, + ':quarantine' => 0, + ':quarantine_attachments' => 0, + ':quarantine_notification' => 0, + ':quarantine_category' => 0, + ':app_passwds' => 0 )); } @@ -1533,20 +1551,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $attr['acl_app_passwds'] = (in_array('app_passwds', $_data['acl'])) ? 1 : 0; } else { $_data['acl'] = (array)$_data['acl']; - $attr['acl_spam_alias'] = 1; - $attr['acl_tls_policy'] = 1; - $attr['acl_spam_score'] = 1; - $attr['acl_spam_policy'] = 1; - $attr['acl_delimiter_action'] = 1; + $attr['acl_spam_alias'] = 0; + $attr['acl_tls_policy'] = 0; + $attr['acl_spam_score'] = 0; + $attr['acl_spam_policy'] = 0; + $attr['acl_delimiter_action'] = 0; $attr['acl_syncjobs'] = 0; - $attr['acl_eas_reset'] = 1; + $attr['acl_eas_reset'] = 0; $attr['acl_sogo_profile_reset'] = 0; - $attr['acl_pushover'] = 1; - $attr['acl_quarantine'] = 1; - $attr['acl_quarantine_attachments'] = 1; - $attr['acl_quarantine_notification'] = 1; - $attr['acl_quarantine_category'] = 1; - $attr['acl_app_passwds'] = 1; + $attr['acl_pushover'] = 0; + $attr['acl_quarantine'] = 0; + $attr['acl_quarantine_attachments'] = 0; + $attr['acl_quarantine_notification'] = 0; + $attr['acl_quarantine_category'] = 0; + $attr['acl_app_passwds'] = 0; } From 87e3c91c26ee117d9ccd92df053bfc2f0ebcd1a2 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 8 Oct 2023 11:41:39 +0200 Subject: [PATCH 103/174] Update Dockerfile --- data/Dockerfiles/phpfpm/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index ca7d629ab..9f8c8b7b6 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -6,7 +6,7 @@ ARG APCU_PECL_VERSION=5.1.22 # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=^v(?.*)$ ARG IMAGICK_PECL_VERSION=3.7.0 # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ -ARG MAILPARSE_PECL_VERSION=v3.1.6 +ARG MAILPARSE_PECL_VERSION=3.1.6 # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ ARG MEMCACHED_PECL_VERSION=3.2.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ @@ -110,4 +110,4 @@ COPY ./docker-entrypoint.sh / ENTRYPOINT ["/docker-entrypoint.sh"] -CMD ["php-fpm"] \ No newline at end of file +CMD ["php-fpm"] From d7f3ee16aab2656d94c5d68ec4e5b448eaaad771 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 10 Oct 2023 16:13:28 +0200 Subject: [PATCH 104/174] Update Dovecot Wiki Link for new mailcows --- generate_config.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/generate_config.sh b/generate_config.sh index 2005ca401..f25309ead 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -352,7 +352,7 @@ SKIP_LETS_ENCRYPT=n # Create seperate certificates for all domains - y/n # this will allow adding more than 100 domains, but some email clients will not be able to connect with alternative hostnames -# see https://wiki.dovecot.org/SSL/SNIClientSupport +# see https://doc.dovecot.org/admin_manual/ssl/sni_support ENABLE_SSL_SNI=n # Skip IPv4 check in ACME container - y/n From a02bd4beff7a550f25e018b61c652770e94845c5 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 11 Oct 2023 12:14:47 +0200 Subject: [PATCH 105/174] [Dovecot] Update to 2.3.21 --- data/Dockerfiles/dovecot/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index fc4501a5f..90a6af938 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -3,7 +3,7 @@ LABEL maintainer "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive # renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=^v(?.*)$ -ARG DOVECOT=2.3.20 +ARG DOVECOT=2.3.21 # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ ARG GOSU_VERSION=1.16 ENV LC_ALL C From 1fda71e4fa6c457707c744f9820a94e965718691 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 11 Oct 2023 12:16:05 +0200 Subject: [PATCH 106/174] Update Images which contains Curl to fix CVEs --- docker-compose.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 5adb92b34..1666a48df 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,7 +2,7 @@ version: '2.1' services: unbound-mailcow: - image: mailcow/unbound:1.17 + image: mailcow/unbound:1.18 environment: - TZ=${TZ} volumes: @@ -106,7 +106,7 @@ services: - rspamd php-fpm-mailcow: - image: mailcow/phpfpm:1.84 + image: mailcow/phpfpm:1.85 command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: - redis-mailcow @@ -217,7 +217,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.24 + image: mailcow/dovecot:1.25 depends_on: - mysql-mailcow dns: @@ -297,7 +297,7 @@ services: - dovecot postfix-mailcow: - image: mailcow/postfix:1.71 + image: mailcow/postfix:1.72 depends_on: - mysql-mailcow volumes: @@ -391,7 +391,7 @@ services: acme-mailcow: depends_on: - nginx-mailcow - image: mailcow/acme:1.84 + image: mailcow/acme:1.85 dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: @@ -450,7 +450,7 @@ services: - /lib/modules:/lib/modules:ro watchdog-mailcow: - image: mailcow/watchdog:1.97 + image: mailcow/watchdog:1.98 dns: - ${IPV4_NETWORK:-172.22.1}.254 tmpfs: From eb3be80286b1fe80c64f407cb5ac692767955abc Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 11 Oct 2023 15:48:25 +0200 Subject: [PATCH 107/174] [Unbound] Added Healthcheck (nslookup) --- data/Dockerfiles/unbound/Dockerfile | 5 +++++ data/Dockerfiles/unbound/healthcheck.sh | 12 ++++++++++++ 2 files changed, 17 insertions(+) create mode 100644 data/Dockerfiles/unbound/healthcheck.sh diff --git a/data/Dockerfiles/unbound/Dockerfile b/data/Dockerfiles/unbound/Dockerfile index e853082d8..b19090835 100644 --- a/data/Dockerfiles/unbound/Dockerfile +++ b/data/Dockerfiles/unbound/Dockerfile @@ -18,6 +18,11 @@ EXPOSE 53/udp 53/tcp COPY docker-entrypoint.sh /docker-entrypoint.sh +# healthcheck (nslookup) +COPY healthcheck.sh /healthcheck.sh +RUN chmod +x /healthcheck.sh +HEALTHCHECK --interval=30s --timeout=10s CMD [ "/healthcheck.sh" ] + ENTRYPOINT ["/docker-entrypoint.sh"] CMD ["/usr/sbin/unbound"] diff --git a/data/Dockerfiles/unbound/healthcheck.sh b/data/Dockerfiles/unbound/healthcheck.sh new file mode 100644 index 000000000..8c4508fb1 --- /dev/null +++ b/data/Dockerfiles/unbound/healthcheck.sh @@ -0,0 +1,12 @@ +#!/bin/bash + +nslookup mailcow.email 127.0.0.1 1> /dev/null + +if [ $? == 0 ]; then + echo "DNS resolution is working!" + exit 0 +else + echo "DNS resolution is not working correctly..." + echo "Maybe check your outbound firewall, as it needs to resolve DNS over TCP AND UDP!" + exit 1 +fi From 0b627017e0658bc48234e001d2611cc50c5005d4 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 11 Oct 2023 15:49:00 +0200 Subject: [PATCH 108/174] [Compose] Added Healthcheck startup logics --- docker-compose.yml | 22 +++++++++++++++++++--- 1 file changed, 19 insertions(+), 3 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 1666a48df..c8cfd589f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -61,7 +61,9 @@ services: image: mailcow/clamd:1.62 restart: always depends_on: - - unbound-mailcow + unbound-mailcow: + condition: service_healthy + restart: true dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: @@ -299,7 +301,11 @@ services: postfix-mailcow: image: mailcow/postfix:1.72 depends_on: - - mysql-mailcow + mysql-mailcow: + condition: service_started + unbound-mailcow: + condition: service_healthy + restart: true volumes: - ./data/hooks/postfix:/hooks:Z - ./data/conf/postfix:/opt/postfix/conf:z @@ -390,7 +396,10 @@ services: acme-mailcow: depends_on: - - nginx-mailcow + nginx-mailcow: + condition: service_started + unbound-mailcow: + condition: service_healthy image: mailcow/acme:1.85 dns: - ${IPV4_NETWORK:-172.22.1}.254 @@ -461,6 +470,13 @@ services: - postfix-vol-1:/var/spool/postfix - ./data/assets/ssl:/etc/ssl/mail/:ro,z restart: always + depends_on: + - postfix-mailcow + - dovecot-mailcow + - mysql-mailcow + - acme-mailcow + - redis-mailcow + environment: - IPV6_NETWORK=${IPV6_NETWORK:-fd4d:6169:6c63:6f77::/64} - LOG_LINES=${LOG_LINES:-9999} From c134078d601488e233b95a3ceb7a0b42ad711129 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 12 Oct 2023 11:11:50 +0200 Subject: [PATCH 109/174] Add comment about experimental thingy --- data/conf/sogo/sogo.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf index 4e18d80b0..b424efd81 100644 --- a/data/conf/sogo/sogo.conf +++ b/data/conf/sogo/sogo.conf @@ -83,7 +83,7 @@ //SoDebugBaseURL = YES; //ImapDebugEnabled = YES; //SOGoEASDebugEnabled = YES; - SOGoEASSearchInBody = YES; + SOGoEASSearchInBody = YES; // Experimental. Enabled since 2023-10 //LDAPDebugEnabled = YES; //PGDebugEnabled = YES; //MySQL4DebugEnabled = YES; From 2c0d379dc5e48ce92541cd8c89c5fb2364d5bef6 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 12 Oct 2023 13:05:27 +0200 Subject: [PATCH 110/174] [Rspamd] Update to 3.7.1 --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index c8cfd589f..d4e65241f 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -78,7 +78,7 @@ services: - clamd rspamd-mailcow: - image: mailcow/rspamd:1.92 + image: mailcow/rspamd:1.93 stop_grace_period: 30s depends_on: - dovecot-mailcow From 907912046feb3e6aecd1df909f774ac5ed366761 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 12 Oct 2023 15:18:19 +0200 Subject: [PATCH 111/174] Fix Clamd Version image in compose --- data/Dockerfiles/clamd/Dockerfile | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/clamd/Dockerfile b/data/Dockerfiles/clamd/Dockerfile index 6d6466643..31a332d7a 100644 --- a/data/Dockerfiles/clamd/Dockerfile +++ b/data/Dockerfiles/clamd/Dockerfile @@ -1,6 +1,6 @@ FROM clamav/clamav:1.0.3_base -LABEL maintainer "André Peters " +LABEL maintainer "The Infrastructure Company GmbH " RUN apk upgrade --no-cache \ && apk add --update --no-cache \ diff --git a/docker-compose.yml b/docker-compose.yml index c8cfd589f..51887053c 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -58,7 +58,7 @@ services: - redis clamd-mailcow: - image: mailcow/clamd:1.62 + image: mailcow/clamd:1.63 restart: always depends_on: unbound-mailcow: From 99de302ec9426b2c038c24322443ec23d3c7580f Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 12 Oct 2023 15:38:58 +0200 Subject: [PATCH 112/174] Reverted restart action removal in docker-compose.yml for older 2.X compatibility --- docker-compose.yml | 2 -- 1 file changed, 2 deletions(-) diff --git a/docker-compose.yml b/docker-compose.yml index 51887053c..8d84e3a75 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -63,7 +63,6 @@ services: depends_on: unbound-mailcow: condition: service_healthy - restart: true dns: - ${IPV4_NETWORK:-172.22.1}.254 environment: @@ -305,7 +304,6 @@ services: condition: service_started unbound-mailcow: condition: service_healthy - restart: true volumes: - ./data/hooks/postfix:/hooks:Z - ./data/conf/postfix:/opt/postfix/conf:z From bb4bc11383911b2306735df5a7352f79f6d9bf5d Mon Sep 17 00:00:00 2001 From: Jordan ERNST Date: Thu, 12 Oct 2023 15:55:53 +0200 Subject: [PATCH 113/174] Fix for git < v1.7.5 This change should be compatible with all git version. (get-url available from v1.7.5) --- update.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/update.sh b/update.sh index 5204659e1..bd431b478 100755 --- a/update.sh +++ b/update.sh @@ -893,7 +893,7 @@ done # git remote set-url origin https://github.com/mailcow/mailcow-dockerized DEFAULT_REPO=https://github.com/mailcow/mailcow-dockerized -CURRENT_REPO=$(git remote get-url origin) +CURRENT_REPO=$(git config --get remote.origin.url) if [ "$CURRENT_REPO" != "$DEFAULT_REPO" ]; then echo "The Repository currently used is not the default Mailcow Repository." echo "Currently Repository: $CURRENT_REPO" From 8a70cdb48b2e8dd0d43cb6a1e60594a5ab01b5f3 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Thu, 12 Oct 2023 18:27:04 +0200 Subject: [PATCH 114/174] Translations update from Weblate (#5460) * [Web] Added lang.pt-br.json Co-authored-by: Peter * Add pt-br in vars.inc.php --------- Co-authored-by: Peter --- data/web/inc/vars.inc.php | 1 + data/web/lang/lang.pt-br.json | 1 + 2 files changed, 2 insertions(+) create mode 100644 data/web/lang/lang.pt-br.json diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 3f726934a..392b0d49e 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -97,6 +97,7 @@ $AVAILABLE_LANGUAGES = array( 'lv-lv' => 'latviešu (Latvian)', 'nl-nl' => 'Nederlands (Dutch)', 'pl-pl' => 'Język Polski (Polish)', + 'pt-br' => 'Português brasileiro (Brazilian Portuguese)', 'pt-pt' => 'Português (Portuguese)', 'ro-ro' => 'Română (Romanian)', 'ru-ru' => 'Pусский (Russian)', diff --git a/data/web/lang/lang.pt-br.json b/data/web/lang/lang.pt-br.json new file mode 100644 index 000000000..0967ef424 --- /dev/null +++ b/data/web/lang/lang.pt-br.json @@ -0,0 +1 @@ +{} From adc6a0054cffe2c8fd5de44a3cff17bc26ee2234 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Fri, 13 Oct 2023 15:37:37 +0200 Subject: [PATCH 115/174] Updated compose version info color from red to yellow --- generate_config.sh | 8 ++++---- update.sh | 8 ++++---- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/generate_config.sh b/generate_config.sh index f25309ead..2b1d2c35e 100755 --- a/generate_config.sh +++ b/generate_config.sh @@ -28,8 +28,8 @@ done if docker compose > /dev/null 2>&1; then if docker compose version --short | grep "^2." > /dev/null 2>&1; then COMPOSE_VERSION=native - echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m" - echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" + echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" sleep 2 echo -e "\e[33mNotice: You´ll have to update this Compose Version via your Package Manager manually!\e[0m" else @@ -41,8 +41,8 @@ elif docker-compose > /dev/null 2>&1; then if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then if docker-compose version --short | grep "^2." > /dev/null 2>&1; then COMPOSE_VERSION=standalone - echo -e "\e[31mFound Docker Compose Standalone.\e[0m" - echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" + echo -e "\e[33mFound Docker Compose Standalone.\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" sleep 2 echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" else diff --git a/update.sh b/update.sh index 5204659e1..1d0a3af66 100755 --- a/update.sh +++ b/update.sh @@ -181,8 +181,8 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then if docker compose version --short | grep "2." > /dev/null 2>&1; then DOCKER_COMPOSE_VERSION=native COMPOSE_COMMAND="docker compose" - echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m" - echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" + echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf sleep 2 echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" @@ -196,8 +196,8 @@ if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then if docker-compose version --short | grep "^2." > /dev/null 2>&1; then DOCKER_COMPOSE_VERSION=standalone COMPOSE_COMMAND="docker-compose" - echo -e "\e[31mFound Docker Compose Standalone.\e[0m" - echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" + echo -e "\e[33mFound Docker Compose Standalone.\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf sleep 2 echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" From 4f9dad5dd342d63bbacb5fc9027ddf099c4179a4 Mon Sep 17 00:00:00 2001 From: "Pedro Lucca S.C" <134713218+pedroluccasc@users.noreply.github.com> Date: Sat, 14 Oct 2023 09:16:07 -0300 Subject: [PATCH 116/174] pt-br translation (#5470) --- data/web/lang/lang.pt-br.json | 1296 ++++++++++++++++++++++++++++++++- 1 file changed, 1295 insertions(+), 1 deletion(-) diff --git a/data/web/lang/lang.pt-br.json b/data/web/lang/lang.pt-br.json index 0967ef424..1f9228c25 100644 --- a/data/web/lang/lang.pt-br.json +++ b/data/web/lang/lang.pt-br.json @@ -1 +1,1295 @@ -{} +{ + "acl": { + "alias_domains": "Adicionar domínios de alias", + "app_passwds": "Gerenciar senhas de aplicativos", + "bcc_maps": "Mapas BCC", + "delimiter_action": "Ação delimitadora", + "domain_desc": "Alterar descrição do domínio", + "domain_relayhost": "Alterar relayhost para um domínio", + "eas_reset": "Redefinir dispositivos EAS", + "extend_sender_acl": "Permitir estender a ACL do remetente por endereços externos", + "filters": "Filtros", + "login_as": "Faça login como usuário da caixa de correio", + "mailbox_relayhost": "Alterar relayhost para uma caixa de correio", + "prohibited": "Proibido pela ACL", + "protocol_access": "Alterar o acesso ao protocolo", + "pushover": "Pushover", + "quarantine": "Ações de quarentena", + "quarantine_attachments": "Anexos de quarentena", + "quarantine_category": "Alterar categoria de notificação de quarentena", + "quarantine_notification": "Alterar notificações de quarentena", + "ratelimit": "Limite de taxa", + "recipient_maps": "Mapas de destinatários", + "smtp_ip_access": "Alterar hosts permitidos para SMTP", + "sogo_access": "Permitir o gerenciamento do acesso ao SoGo", + "sogo_profile_reset": "Redefinir perfil SoGo", + "spam_alias": "Aliases temporários", + "spam_policy": "Lista negra/lista branca", + "spam_score": "Pontuação de spam", + "syncjobs": "Trabalhos de sincronização", + "tls_policy": "Política de TLS", + "unlimited_quota": "Cota ilimitada para caixas de correio" + }, + "add": { + "activate_filter_warn": "Todos os outros filtros serão desativados quando a opção ativa estiver marcada.", + "active": "Ativo", + "add": "Adicionar", + "add_domain_only": "Adicionar somente domínio", + "add_domain_restart": "Adicionar domínio e reiniciar o SoGo", + "alias_address": "Endereço (s) de alias", + "alias_address_info": "Endereço de e-mail completo/es ou @example .com, para capturar todas as mensagens de um domínio (separadas por vírgula). somente domínios mailcow.", + "alias_domain": "Domínio de alias", + "alias_domain_info": "Somente nomes de domínio válidos (separados por vírgula).", + "app_name": "Nome do aplicativo", + "app_password": "Adicionar senha do aplicativo", + "app_passwd_protocols": "Protocolos permitidos para a senha do aplicativo", + "automap": "Tente mapear pastas automaticamente (“Itens enviados”, “Enviados” => “Enviados” etc.)", + "backup_mx_options": "Opções de relé", + "bcc_dest_format": "O destino do BCC deve ser um único endereço de e-mail válido.
    Se precisar enviar uma cópia para vários endereços, crie um alias e use-o aqui.", + "comment_info": "Um comentário privado não é visível para o usuário, enquanto um comentário público é mostrado como dica de ferramenta ao passar o mouse sobre ele na visão geral do usuário", + "custom_params": "Parâmetros personalizados", + "custom_params_hint": "Certo: --param=xy, errado: --param xy", + "delete1": "Excluir da fonte quando concluído", + "delete2": "Excluir mensagens no destino que não estão na origem", + "delete2duplicates": "Excluir duplicatas no destino", + "description": "Descrição", + "destination": "Destino", + "disable_login": "Não permitir login (e-mails recebidos ainda são aceitos)", + "domain": "Domínio", + "domain_matches_hostname": "O domínio %s corresponde ao nome do host", + "domain_quota_m": "Cota total de domínio (MiB)", + "enc_method": "Método de criptografia", + "exclude": "Excluir objetos (regex)", + "full_name": "Nome completo", + "gal": "Lista de endereços global", + "gal_info": "A GAL contém todos os objetos de um domínio e não pode ser editada por nenhum usuário. Faltam informações de disponibilidade no SoGo, se desativadas! Reinicie o SoGo para aplicar as alterações.", + "generate": "geram", + "goto_ham": "Aprenda como presunto", + "goto_null": "Descarte e-mails silenciosamente", + "goto_spam": "Aprenda como spam", + "hostname": "Anfitrião", + "inactive": "Inativo", + "kind": "Gentil", + "mailbox_quota_def": "Cota de caixa de correio padrão", + "mailbox_quota_m": "Cota máxima por caixa de correio (MiB)", + "mailbox_username": "Nome de usuário (parte esquerda de um endereço de e-mail)", + "max_aliases": "Máximo de aliases possíveis", + "max_mailboxes": "Número máximo de caixas de correio possíveis", + "mins_interval": "Intervalo de votação (minutos)", + "multiple_bookings": "Várias reservas", + "nexthop": "Próximo salto", + "password": "Senha", + "password_repeat": "Senha de confirmação (repetição)", + "port": "Porto", + "post_domain_add": "O contêiner SoGo, “sogo-mailcow”, precisa ser reiniciado após a adição de um novo domínio!

    Além disso, a configuração do DNS dos domínios deve ser revisada. Depois que a configuração de DNS for aprovada, reinicie “acme-mailcow” para gerar automaticamente certificados para seu novo domínio (autoconfig). , descoberta automática. ).
    Essa etapa é opcional e será repetida a cada 24 horas.", + "private_comment": "Comentário privado", + "public_comment": "Comentário público", + "quota_mb": "Cota (MiB)", + "relay_all": "Retransmita todos os destinatários", + "relay_all_info": "↪ Se você optar por não retransmitir todos os destinatários, precisará adicionar uma caixa de correio (“cega”) para cada destinatário que deve ser retransmitido.", + "relay_domain": "Retransmitir este domínio", + "relay_transport_info": "
    Informações
    Você pode definir mapas de transporte para um destino personalizado para esse domínio. Se não for definido, uma pesquisa MX será feita.", + "relay_unknown_only": "Retransmita somente caixas de correio não existentes. As caixas de correio existentes serão entregues localmente.", + "relayhost_wrapped_tls_info": "Por favor, não use portas com cobertura TLS (usadas principalmente na porta 465).
    \r\nUse qualquer porta não encapsulada e emita STARTTLS. Uma política de TLS para impor o TLS pode ser criada em “mapas de políticas de TLS”.", + "select": "Selecione...", + "select_domain": "Selecione primeiro um domínio", + "sieve_desc": "Breve descrição", + "sieve_type": "Tipo de filtro", + "skipcrossduplicates": "Ignore mensagens duplicadas entre pastas (primeiro a chegar, primeiro a ser servido)", + "subscribeall": "Assine todas as pastas", + "syncjob": "Adicionar tarefa de sincronização", + "syncjob_hint": "Esteja ciente de que as senhas precisam ser salvas em texto simples!", + "tags": "Etiquetas", + "target_address": "Vá para endereços", + "target_address_info": "Endereço (s) de e-mail completo (separado por vírgula).", + "target_domain": "Domínio de destino", + "timeout1": "Tempo limite para conexão com o host remoto", + "timeout2": "Tempo limite para conexão com o host local", + "username": "Nome de usuário", + "validate": "Validar", + "validation_success": "Validado com sucesso" + }, + "admin": { + "access": "Acesso", + "action": "Ação", + "activate_api": "Ativar API", + "activate_send": "Ativar botão de envio", + "active": "Ativo", + "active_rspamd_settings_map": "Mapa de configurações ativas", + "add": "Adicionar", + "add_admin": "Adicionar administrador", + "add_domain_admin": "Adicionar administrador de domínio", + "add_forwarding_host": "Adicionar host de encaminhamento", + "add_relayhost": "Adicionar transporte dependente do remetente", + "add_relayhost_hint": "Esteja ciente de que os dados de autenticação, se houver, serão armazenados como texto simples.", + "add_row": "Adicionar linha", + "add_settings_rule": "Adicionar regra de configurações", + "add_transport": "Adicionar transporte", + "add_transports_hint": "Esteja ciente de que os dados de autenticação, se houver, serão armazenados como texto simples.", + "additional_rows": " linhas adicionais foram adicionadas", + "admin": "Administrador", + "admin_details": "Editar detalhes do administrador", + "admin_domains": "Atribuições de domínio", + "admins": "Administradores", + "admins_ldap": "Administradores do LDAP", + "advanced_settings": "Configurações avançadas", + "allowed_methods": "Métodos de permissão de controle de acesso", + "allowed_origins": "Controle de acesso, permissão de origem", + "api_allow_from": "Permita o acesso à API a partir dessas notações de rede IPS/CIDR", + "api_info": "A API é um trabalho em andamento. A documentação pode ser encontrada em /api", + "api_key": "Chave de API", + "api_read_only": "Acesso somente para leitura", + "api_read_write": "Acesso de leitura e gravação", + "api_skip_ip_check": "Ignorar verificação de IP para API", + "app_links": "Links de aplicativos", + "app_name": "Nome do aplicativo", + "apps_name": "Nome “mailcow Apps”", + "arrival_time": "Hora de chegada (hora do servidor)", + "authed_user": "Usuário autoritário", + "ays": "Tem certeza de que deseja continuar?", + "ban_list_info": "Veja uma lista de IPs banidos abaixo: rede (tempo restante de banimento) - [ações].
    Os IPs na fila para serem desbanidos serão removidos da lista de banimentos ativos em alguns segundos.
    Rótulos vermelhos indicam proibições permanentes ativas na lista negra.", + "change_logo": "Alterar logotipo", + "logo_normal_label": "Normal", + "logo_dark_label": "Invertido para o modo escuro", + "configuration": "Configuração", + "convert_html_to_text": "Converter HTML em texto sem formatação", + "cors_settings": "Configurações do CORS", + "credentials_transport_warning": "Aviso: Adicionar uma nova entrada no mapa de transporte atualizará as credenciais de todas as entradas com uma coluna correspondente do próximo salto.", + "customer_id": "ID do cliente", + "customize": "Personalizar", + "destination": "Destino", + "dkim_add_key": "Adicionar chave ARC/DKIM", + "dkim_domains_selector": "Seletor", + "dkim_domains_wo_keys": "Selecione domínios com chaves ausentes", + "dkim_from": "De", + "dkim_from_title": "Domínio de origem do qual copiar dados", + "dkim_key_length": "Comprimento da chave DKIM (bits)", + "dkim_key_missing": "Falta a chave", + "dkim_key_unused": "Chave não usada", + "dkim_key_valid": "Chave válida", + "dkim_keys": "Teclas ARC/DKIM", + "dkim_overwrite_key": "Substituir a chave DKIM existente", + "dkim_private_key": "Chave privada", + "dkim_to": "Para", + "dkim_to_title": "Domínio/s de destino - serão sobrescritos", + "domain": "Domínio", + "domain_admin": "Administrador de domínio", + "domain_admins": "Administradores de domínio", + "domain_s": "Domínio/s", + "duplicate": "Duplicado", + "duplicate_dkim": "Registro DKIM duplicado", + "edit": "Editar", + "empty": "Sem resultados", + "excludes": "Exclui esses destinatários", + "f2b_ban_time": "Tempo (s) de proibição", + "f2b_ban_time_increment": "O tempo de banimento é incrementado com cada banimento", + "f2b_blacklist": "Redes/hosts na lista negra", + "f2b_filter": "Filtros Regex", + "f2b_list_info": "Um host ou rede na lista negra sempre superará uma entidade na lista branca. As atualizações da lista levarão alguns segundos para serem aplicadas.", + "f2b_max_attempts": "Máximo de tentativas", + "f2b_max_ban_time": "Tempo (s) máximo (s) de banimento", + "f2b_netban_ipv4": "Tamanho da sub-rede IPv4 a ser proibida (8-32)", + "f2b_netban_ipv6": "Tamanho da sub-rede IPv6 a ser proibida (8-128)", + "f2b_parameters": "Parâmetros do Fail2ban", + "f2b_regex_info": "Registros considerados: SoGo, Postfix, Dovecot, PHP-FPM.", + "f2b_retry_window": "Repita a (s) janela (s) para o máximo de tentativas", + "f2b_whitelist": "Redes/hosts incluídos na lista branca", + "filter_table": "Tabela de filtros", + "forwarding_hosts": "Anfitriões de encaminhamento", + "forwarding_hosts_add_hint": "Você pode especificar endereços IPv4/IPv6, redes em notação CIDR, nomes de host (que serão resolvidos para endereços IP) ou nomes de domínio (que serão resolvidos para endereços IP consultando registros SPF ou, na ausência deles, registros MX).", + "forwarding_hosts_hint": "As mensagens recebidas são aceitas incondicionalmente de qualquer host listado aqui. Esses hosts não são então verificados em relação aos DNSBLs nem submetidos à lista cinza. O spam recebido deles nunca é rejeitado, mas, opcionalmente, pode ser arquivado na pasta Lixo eletrônico. O uso mais comum para isso é especificar servidores de e-mail nos quais você configurou uma regra que encaminha e-mails recebidos para o servidor mailcow.", + "from": "De", + "generate": "geram", + "guid": "GUID - ID de instância exclusiva", + "guid_and_license": "GUID e licença", + "hash_remove_info": "A remoção de um hash de limite de taxa (se ainda existir) reiniciará completamente seu contador.
    \r\n Cada hash é indicado por uma cor individual.", + "help_text": "Substituir texto de ajuda abaixo da máscara de login (HTML permitido)", + "host": "Anfitrião", + "html": "HTML", + "import": "Importar", + "import_private_key": "Importar chave privada", + "in_use_by": "Em uso por", + "inactive": "Inativo", + "include_exclude": "Incluir/Excluir", + "include_exclude_info": "Por padrão - sem seleção - todas as caixas de correio são endereçadas", + "includes": "Inclua esses destinatários", + "ip_check": "Verificação de IP", + "ip_check_disabled": "A verificação de IP está desativada. Você pode ativá-lo em
    Sistema > Configuração > Opções > Personalizar", + "ip_check_opt_in": "Opte por usar o serviço de terceiros ipv4.mailcow.email e ipv6.mailcow.email para resolver endereços IP externos.", + "is_mx_based": "Baseado em MX", + "last_applied": "Aplicado pela última vez", + "license_info": "Uma licença não é necessária, mas ajuda no desenvolvimento futuro.
    Registre seu GUID aqui ou compre suporte para a instalação do mailcow.", + "link": "Link", + "loading": "Por favor, espere...", + "login_time": "Hora do login", + "logo_info": "Sua imagem será dimensionada para uma altura de 40 px para a barra de navegação superior e uma largura máxima de 250 px para a página inicial. Um gráfico escalável é altamente recomendado.", + "lookup_mx": "Destination é uma expressão regular que corresponde ao nome MX (.*\\ .google\\ .com para rotear todos os e-mails direcionados a um MX que termina em google.com nesse salto)", + "main_name": "nome “mailcow UI”", + "merged_vars_hint": "As linhas acinzentadas foram mescladas a partir das barras. (local.) inc.php e não pode ser modificado.", + "message": "Mensagem", + "message_size": "Tamanho da mensagem", + "nexthop": "Próximo salto", + "no": "✕", + "no_active_bans": "Sem proibições ativas", + "no_new_rows": "Não há mais linhas disponíveis", + "no_record": "Sem registro", + "oauth2_apps": "Aplicativos OAuth2", + "oauth2_add_client": "Adicionar cliente OAuth2", + "oauth2_client_id": "ID do cliente", + "oauth2_client_secret": "Segredo do cliente", + "oauth2_info": "A implementação do OAuth2 suporta o tipo de concessão “Código de Autorização” e emite tokens de atualização.
    \r\nO servidor também emite automaticamente novos tokens de atualização, após o uso de um token de atualização.

    \r\n• O escopo padrão é perfil. Somente usuários de caixas de correio podem ser autenticados no OAuth2. Se o parâmetro do escopo for omitido, ele retornará ao perfil.
    \r\n• O parâmetro state deve ser enviado pelo cliente como parte da solicitação de autorização.

    \r\nCaminhos para solicitações para a API OAuth2:
    \r\n
      \r\n
    • Ponto final de autorização: /oauth/authorize
    • \r\n
    • Ponto final do token: /oauth/token
    • \r\n
    • Página de recursos: /oauth/profile
    \r\nA regeneração do segredo do cliente não expirará os códigos de autorização existentes, mas eles falharão na renovação do token.

    \r\nA revogação dos tokens do cliente causará o encerramento imediato de todas as sessões ativas. Todos os clientes precisam se autenticar novamente.", + "oauth2_redirect_uri": "URI de redirecionamento", + "oauth2_renew_secret": "Gere um novo segredo de cliente", + "oauth2_revoke_tokens": "Revogar todos os tokens do cliente", + "optional": "opcionais", + "options": "Opções", + "password": "Senha", + "password_length": "Tamanho da senha", + "password_policy": "Política de senha", + "password_policy_chars": "Deve conter pelo menos um caractere alfabético", + "password_policy_length": "O tamanho mínimo da senha é %d", + "password_policy_lowerupper": "Deve conter caracteres maiúsculos e minúsculos", + "password_policy_numbers": "Deve conter pelo menos um número", + "password_policy_special_chars": "Deve conter caracteres especiais", + "password_repeat": "Senha de confirmação (repetição)", + "priority": "Prioridade", + "private_key": "Chave privada", + "quarantine": "Quarentena", + "quarantine_bcc": "Envie uma cópia de todas as notificações (BCC) para esse destinatário:
    deixe em branco para desativar. Correio não assinado e não verificado. Deve ser entregue somente internamente.", + "quarantine_exclude_domains": "Excluir domínios e domínios de alias", + "quarantine_max_age": "Idade máxima em dias
    O valor deve ser igual ou superior a 1 dia.", + "quarantine_max_score": "Descarte a notificação se a pontuação de spam de um e-mail for maior que esse valor: O
    padrão é 9999,0", + "quarantine_max_size": "Tamanho máximo em MiB (elementos maiores são descartados):
    0 não indica ilimitado.", + "quarantine_notification_html": "Modelo de e-mail de notificação:
    deixe em branco para restaurar o modelo padrão.", + "quarantine_notification_sender": "Remetente do e-mail de notificação", + "quarantine_notification_subject": "Assunto do e-mail de notificação", + "quarantine_redirect": "Redirecione todas as notificações para esse destinatário:
    deixe em branco para desativar. Correio não assinado e não verificado. Deve ser entregue somente internamente.", + "quarantine_release_format": "Formato dos itens lançados", + "quarantine_release_format_att": "Como anexo", + "quarantine_release_format_raw": "Original não modificado", + "quarantine_retention_size": "Retenções por caixa de correio: 0 indica inativo.
    ", + "quota_notification_html": "Modelo de e-mail de notificação:
    deixe em branco para restaurar o modelo padrão.", + "quota_notification_sender": "Remetente do e-mail de notificação", + "quota_notification_subject": "Assunto do e-mail de notificação", + "quota_notifications": "Notificações de cotas", + "quota_notifications_info": "As notificações de cota são enviadas aos usuários uma vez ao ultrapassar 80% e uma vez ao ultrapassar 95% de uso.", + "quota_notifications_vars": "{{percent}} é igual à cota atual do usuário
    {{username}} é o nome da caixa de correio", + "queue_unban": "não banido", + "r_active": "Restrições ativas", + "r_inactive": "Restrições inativas", + "r_info": "Os elementos acinzentados/desativados na lista de restrições ativas não são conhecidos como restrições válidas para mailcow e não podem ser movidos. De qualquer forma, restrições desconhecidas serão definidas em ordem de aparição.
    Você pode adicionar novos elementos em inc/vars.local.inc.php para poder alterná-los.", + "rate_name": "Nome da tarifa", + "recipients": "Destinatários", + "refresh": "Atualizar", + "regen_api_key": "Regenerar chave de API", + "regex_maps": "Mapas Regex", + "relay_from": "Endereço “De:”", + "relay_rcpt": "Endereço “Para:”", + "relay_run": "Execute o teste", + "relayhosts": "Transportes dependentes do remetente", + "relayhosts_hint": "Defina transportes dependentes do remetente para poder selecioná-los em uma caixa de diálogo de configuração de domínios.
    \r\n O serviço de transporte é sempre “smtp:” e, portanto, experimentará o TLS quando oferecido. O Wrapped TLS (SMTPS) não é suportado. A configuração da política de TLS de saída individual de um usuário é levada em consideração.
    \r\n Afeta domínios selecionados, incluindo domínios de alias.", + "remove": "Remover", + "remove_row": "Remover linha", + "reset_default": "Redefinir para o padrão", + "reset_limit": "Remover o hash", + "routing": "Roteamento", + "rsetting_add_rule": "Adicionar regra", + "rsetting_content": "Conteúdo da regra", + "rsetting_desc": "Breve descrição", + "rsetting_no_selection": "Selecione uma regra", + "rsetting_none": "Nenhuma regra disponível", + "rsettings_insert_preset": "Inserir exemplo de predefinição “%s”", + "rsettings_preset_1": "Desative tudo, exceto o DKIM e o limite de taxa para usuários autenticados", + "rsettings_preset_2": "Postmasters querem spam", + "rsettings_preset_3": "Permitir somente remetentes específicos para uma caixa de correio (ou seja, uso somente como caixa de correio interna)", + "rsettings_preset_4": "Desativar Rspamd para um domínio", + "rspamd_com_settings": "Um nome de configuração será gerado automaticamente, veja os exemplos de predefinições abaixo. Para obter mais detalhes, consulte a documentação do Rspamd", + "rspamd_global_filters": "Mapas de filtro globais", + "rspamd_global_filters_agree": "Eu vou ter cuidado!", + "rspamd_global_filters_info": "Os mapas de filtros globais contêm diferentes tipos de listas negras e brancas globais.", + "rspamd_global_filters_regex": "Seus nomes explicam seu propósito. Todo o conteúdo deve conter uma expressão regular válida no formato “/padrão/opções” (por exemplo, /. + @domain\\ .tld/i).
    \r\n Embora verificações rudimentares estejam sendo executadas em cada linha de regex, a funcionalidade do Rspamd pode ser interrompida se não conseguir ler a sintaxe corretamente.
    \r\n O Rspamd tentará ler o conteúdo do mapa quando alterado. Se você tiver problemas, reinicie o Rspamd para forçar o recarregamento do mapa.
    Os elementos da lista negra são excluídos da quarentena.", + "rspamd_settings_map": "Mapa de configurações do Rspamd", + "sal_level": "Nível de humor", + "save": "Salvar alterações", + "search_domain_da": "Domínios de pesquisa", + "send": "Enviar", + "sender": "Remetente", + "service": "Serviço", + "service_id": "ID do serviço", + "source": "Fonte", + "spamfilter": "Filtro de spam", + "subject": "Assunto", + "success": "Sucesso", + "sys_mails": "E-mails do sistema", + "text": "Texto", + "time": "Hora", + "title": "Título", + "title_name": "Título do site “mailcow UI”", + "to_top": "Voltar ao topo", + "transport_dest_format": "Regex ou sintaxe: example.org, .example.org, *, box@example.org (vários valores podem ser separados por vírgula)", + "transport_maps": "Mapas de transporte", + "transport_test_rcpt_info": "• Use null@hosted.mailcow.de para testar a retransmissão para um destino estrangeiro.", + "transports_hint": "• Uma entrada no mapa de transporte anula um mapa de transporte dependente do remetente.
    \r\n• Os transportes baseados em MX são preferencialmente usados.
    \r\n• As configurações de política de TLS de saída por usuário são ignoradas e só podem ser aplicadas por entradas do mapa de políticas de TLS.
    \r\n• O serviço de transporte para transportes definidos é sempre “smtp:” e, portanto, tentará o TLS quando oferecido. O Wrapped TLS (SMTPS) não é suportado.
    \r\n• Endereços correspondentes a “/localhost$/” sempre serão transportados via “local:”, portanto, um destino “*” não se aplicará a esses endereços.
    \r\n• Para determinar as credenciais para um próximo salto exemplar “[host] :25\", o Postfix sempre consulta por “host” antes de pesquisar por “[host] :25\". Esse comportamento impossibilita o uso de “host” e “[host] :25\" ao mesmo tempo.", + "ui_footer": "Rodapé (HTML permitido)", + "ui_header_announcement": "Anúncios", + "ui_header_announcement_active": "Definir anúncio ativo", + "ui_header_announcement_content": "Texto (HTML permitido)", + "ui_header_announcement_help": "O anúncio é visível para todos os usuários conectados e na tela de login da interface do usuário.", + "ui_header_announcement_select": "Selecione o tipo de anúncio", + "ui_header_announcement_type": "Tipo", + "ui_header_announcement_type_danger": "Muito importante", + "ui_header_announcement_type_info": "Informações", + "ui_header_announcement_type_warning": "Importante", + "ui_texts": "Rótulos e textos da interface do usuário", + "unban_pending": "pendência não banida", + "unchanged_if_empty": "Se inalterado, deixe em branco", + "upload": "Carregar", + "username": "Nome de usuário", + "validate_license_now": "Valide o GUID em relação ao servidor de licenças", + "verify": "Verificar", + "yes": "✓" + }, + "danger": { + "access_denied": "Acesso negado ou dados de formulário inválidos", + "alias_domain_invalid": "O domínio alias %s é inválido", + "alias_empty": "O endereço do alias não deve estar vazio", + "alias_goto_identical": "O alias e o endereço de destino não devem ser idênticos", + "alias_invalid": "O endereço de alias %s é inválido", + "aliasd_targetd_identical": "O domínio do alias não deve ser igual ao domínio de destino: %s", + "aliases_in_use": "O máximo de aliases deve ser maior ou igual a %d", + "app_name_empty": "O nome do aplicativo não pode estar vazio", + "app_passwd_id_invalid": "ID de senha do aplicativo %s inválida", + "bcc_empty": "O destino do BCC não pode estar vazio", + "bcc_exists": "Existe um mapa BCC %s para o tipo %s", + "bcc_must_be_email": "O destino %s do BCC não é um endereço de e-mail válido", + "comment_too_long": "Comentário muito longo, máximo de 160 caracteres permitidos", + "cors_invalid_method": "Método de permissão inválido especificado", + "cors_invalid_origin": "Origem de permissão inválida especificada", + "defquota_empty": "A cota padrão por caixa de correio não deve ser 0.", + "demo_mode_enabled": "O modo de demonstração está ativado", + "description_invalid": "A descrição do recurso para %s é inválida", + "dkim_domain_or_sel_exists": "Existe uma chave DKIM para “%s” e não será substituída", + "dkim_domain_or_sel_invalid": "Domínio ou seletor DKIM inválido: %s", + "domain_cannot_match_hostname": "O domínio não pode corresponder ao nome do host", + "domain_exists": "O domínio %s já existe", + "domain_invalid": "O nome do domínio está vazio ou é inválido", + "domain_not_empty": "Não é possível remover o domínio não vazio %s", + "domain_not_found": "Domínio %s não encontrado", + "domain_quota_m_in_use": "A cota de domínio deve ser maior ou igual a %s MiB", + "extended_sender_acl_denied": "ACL ausente para definir endereços de remetentes externos", + "extra_acl_invalid": "O endereço do remetente externo “%s” é inválido", + "extra_acl_invalid_domain": "O remetente externo “%s” usa um domínio inválido", + "fido2_verification_failed": "Falha na verificação do FIDO2: %s", + "file_open_error": "O arquivo não pode ser aberto para gravação", + "filter_type": "Tipo de filtro errado", + "from_invalid": "O remetente não deve estar vazio", + "global_filter_write_error": "Não foi possível gravar o arquivo de filtro: %s", + "global_map_invalid": "ID de mapa global %s inválida", + "global_map_write_error": "Não foi possível gravar a ID do mapa global %s: %s", + "goto_empty": "Um endereço de alias deve conter pelo menos um endereço de destino válido", + "goto_invalid": "O endereço Goto %s é inválido", + "ham_learn_error": "Erro de aprendizado do Ham: %s", + "imagick_exception": "Erro: exceção Imagick ao ler a imagem", + "img_invalid": "Não é possível validar o arquivo de imagem", + "img_tmp_missing": "Não é possível validar o arquivo de imagem: Arquivo temporário não encontrado", + "invalid_bcc_map_type": "Tipo de mapa BCC inválido", + "invalid_destination": "O formato de destino “%s” é inválido", + "invalid_filter_type": "Tipo de filtro inválido", + "invalid_host": "Host inválido especificado: %s", + "invalid_mime_type": "Tipo de mime inválido", + "invalid_nexthop": "O formato do próximo salto é inválido", + "invalid_nexthop_authenticated": "O próximo salto existe com credenciais diferentes. Primeiro, atualize as credenciais existentes para o próximo salto.", + "invalid_recipient_map_new": "Novo destinatário inválido especificado: %s", + "invalid_recipient_map_old": "Destinatário original inválido especificado: %s", + "ip_list_empty": "A lista de IPs permitidos não pode estar vazia", + "is_alias": "%s já é conhecido como endereço de alias", + "is_alias_or_mailbox": "%s já é conhecido como alias, caixa de correio ou endereço de alias expandido a partir de um domínio de alias.", + "is_spam_alias": "%s já é conhecido como endereço de alias temporário (endereço de alias de spam)", + "last_key": "A última chave não pode ser excluída. Em vez disso, desative o TFA.", + "login_failed": "Falha no login", + "mailbox_defquota_exceeds_mailbox_maxquota": "A cota padrão excede o limite máximo da cota", + "mailbox_invalid": "O nome da caixa de correio é inválido", + "mailbox_quota_exceeded": "A cota excede o limite do domínio (máx. %d MiB)", + "mailbox_quota_exceeds_domain_quota": "A cota máxima excede o limite da cota do domínio", + "mailbox_quota_left_exceeded": "Não há espaço restante (espaço restante: %d MiB)", + "mailboxes_in_use": "O máximo de caixas de correio deve ser maior ou igual a %d", + "malformed_username": "Nome de usuário malformado", + "map_content_empty": "O conteúdo do mapa não pode estar vazio", + "max_alias_exceeded": "Número máximo de aliases excedido", + "max_mailbox_exceeded": "Número máximo de caixas de correio excedido (%d de %d)", + "max_quota_in_use": "A cota da caixa de correio deve ser maior ou igual a %d MiB", + "maxquota_empty": "A cota máxima por caixa de correio não deve ser 0.", + "mysql_error": "Erro do MySQL: %s", + "network_host_invalid": "Rede ou host inválidos: %s", + "next_hop_interferes": "%s interfere com o nexthop %s", + "next_hop_interferes_any": "Um próximo salto existente interfere com %s", + "nginx_reload_failed": "Falha na recarga do Nginx: %s", + "no_user_defined": "Nenhum usuário definido", + "object_exists": "O objeto %s já existe", + "object_is_not_numeric": "O valor %s não é numérico", + "password_complexity": "A senha não atende à política", + "password_empty": "A senha não deve estar vazia", + "password_mismatch": "A senha de confirmação não corresponde", + "policy_list_from_exists": "Existe um registro com nome próprio", + "policy_list_from_invalid": "O registro tem formato inválido", + "private_key_error": "Erro de chave privada: %s", + "pushover_credentials_missing": "Token Pushover e/ou chave ausente", + "pushover_key": "A tecla Pushover tem um formato errado", + "pushover_token": "O token Pushover tem um formato errado", + "quota_not_0_not_numeric": "A cota deve ser numérica e >= 0", + "recipient_map_entry_exists": "Existe uma entrada de mapa de destinatários “%s”", + "redis_error": "Erro do Redis: %s", + "relayhost_invalid": "A entrada de mapa %s é inválida", + "release_send_failed": "A mensagem não pôde ser liberada: %s", + "reset_f2b_regex": "O filtro Regex não pôde ser redefinido a tempo. Tente novamente ou aguarde mais alguns segundos e recarregue o site.", + "resource_invalid": "O nome do recurso %s é inválido", + "rl_timeframe": "O prazo do limite de taxa está incorreto", + "rspamd_ui_pw_length": "A senha do Rspamd UI deve ter pelo menos 6 caracteres", + "script_empty": "O script não pode estar vazio", + "sender_acl_invalid": "O valor %s da ACL do remetente é inválido", + "set_acl_failed": "Falha ao definir a ACL", + "settings_map_invalid": "ID do mapa de configurações %s inválida", + "sieve_error": "Erro do analisador do Sieve: %s", + "spam_learn_error": "Erro de aprendizado de spam: %s", + "subject_empty": "O assunto não deve estar vazio", + "target_domain_invalid": "O domínio de destino %s é inválido", + "targetd_not_found": "Domínio de destino %s não encontrado", + "targetd_relay_domain": "O domínio de destino %s é um domínio de retransmissão", + "template_exists": "O modelo %s já existe", + "template_id_invalid": "ID de modelo %s inválida", + "template_name_invalid": "Nome do modelo inválido", + "temp_error": "Erro temporário", + "text_empty": "O texto não deve estar vazio", + "tfa_token_invalid": "Token TFA inválido", + "tls_policy_map_dest_invalid": "O destino da política é inválido", + "tls_policy_map_entry_exists": "Existe uma entrada “%s” no mapa de políticas TLS", + "tls_policy_map_parameter_invalid": "O parâmetro de política é inválido", + "totp_verification_failed": "Falha na verificação do TOTP", + "transport_dest_exists": "O destino de transporte “%s” existe", + "webauthn_verification_failed": "Falha na verificação do WebAuthn: %s", + "webauthn_authenticator_failed": "O autenticador selecionado não foi encontrado", + "webauthn_publickey_failed": "Nenhuma chave pública foi armazenada para o autenticador selecionado", + "webauthn_username_failed": "O autenticador selecionado pertence a outra conta", + "unknown": "Ocorreu um erro desconhecido", + "unknown_tfa_method": "Método TFA desconhecido", + "unlimited_quota_acl": "Cota ilimitada proibida pela ACL", + "username_invalid": "O nome de usuário %s não pode ser usado", + "validity_missing": "Por favor, atribua um período de validade", + "value_missing": "Forneça todos os valores", + "yotp_verification_failed": "Falha na verificação do Yubico OTP: %s" + }, + "datatables": { + "collapse_all": "Recolher tudo", + "decimal": ".", + "emptyTable": "Não há dados disponíveis na tabela", + "expand_all": "Expandir tudo", + "info": "Exibindo _START_ a _END_ de _TOTAL_ entradas", + "infoEmpty": "Exibindo 0 a 0 de 0 inscrições", + "infoFiltered": "(filtrado do total de entradas _MAX_)", + "infoPostFix": "", + "thousands": ",", + "lengthMenu": "Show _MENU_ entries", + "loadingRecords": "Loading...", + "processing": "Please wait...", + "search": "Search:", + "zeroRecords": "No matching records found", + "paginate": { + "first": "First", + "last": "Last", + "next": "Next", + "previous": "Previous" + }, + "aria": { + "sortAscending": ": activate to sort column ascending", + "sortDescending": ": activate to sort column descending" + } + }, + "debug": { + "architecture": "Arquitetura", + "chart_this_server": "Gráfico (este servidor)", + "containers_info": "Informações do contêiner", + "container_running": "Correndo", + "container_disabled": "Contêiner parado ou desativado", + "container_stopped": "Parado", + "cores": "Núcleos", + "current_time": "Hora do sistema", + "disk_usage": "Uso do disco", + "docs": "Documentos", + "error_show_ip": "Não foi possível resolver os endereços IP públicos", + "external_logs": "Registros externos", + "history_all_servers": "Histórico (todos os servidores)", + "in_memory_logs": "Registros na memória", + "jvm_memory_solr": "Uso de memória JVM", + "last_modified": "Última modificação", + "log_info": "

    Os registros na memória do mailcow são coletados em listas do Redis e reduzidos para LOG_LINES (%d) a cada minuto para reduzir o martelamento.\r\n Os
    registros na memória não devem ser persistentes. Todos os aplicativos que fazem login na memória também fazem login no daemon do Docker e, portanto, no driver de registro padrão.\r\n


    O tipo de registro na memória deve ser usado para depurar pequenos problemas com contêineres.\r\n

    Os registros externos são coletados por meio da API do aplicativo em questão.

    \r\n

    Os registros estáticos são principalmente registros de atividades, que não são registrados no Dockerd, mas ainda precisam ser persistentes (exceto os registros da API).

    ", + "login_time": "Hora", + "logs": "Registros", + "memory": "Memória", + "online_users": "Usuários online", + "restart_container": "Reiniciar", + "service": "Serviço", + "show_ip": "Mostrar IP público", + "size": "Tamanho", + "solr_dead": "O Solr está iniciando, desativado ou morreu.", + "solr_status": "Status do solr", + "started_at": "Começou em", + "started_on": "Começou em", + "static_logs": "Registros estáticos", + "success": "Sucesso", + "system_containers": "Sistema e contêineres", + "timezone": "Fuso horário", + "uptime": "Tempo de atividade", + "update_available": "Há uma atualização disponível", + "no_update_available": "O sistema está na versão mais recente", + "update_failed": "Não foi possível verificar se havia uma atualização", + "username": "Nome de usuário", + "wip": "Trabalho em andamento no momento" + }, + "diagnostics": { + "cname_from_a": "Valor derivado do registro A/AAAA. Isso é suportado desde que o registro aponte para o recurso correto.", + "dns_records": "Registros DNS", + "dns_records_24hours": "Observe que as alterações feitas no DNS podem levar até 24 horas para que seu estado atual seja refletido corretamente nesta página. O objetivo é uma forma de você ver facilmente como configurar seus registros DNS e verificar se todos os seus registros estão armazenados corretamente no DNS.", + "dns_records_data": "Dados corretos", + "dns_records_docs": "Consulte também a documentação.", + "dns_records_name": "Nome", + "dns_records_status": "Estado atual", + "dns_records_type": "Tipo", + "optional": "Esse registro é opcional." + }, + "edit": { + "acl": "ACL (permissão)", + "active": "Ativo", + "admin": "Editar administrador", + "advanced_settings": "Configurações avançadas", + "alias": "Editar alias", + "allow_from_smtp": "Permita que esses IPs usem apenas SMTP", + "allow_from_smtp_info": "Deixe em branco para permitir todos os remetentes. Endereços e
    redes IPv4/IPv6.", + "allowed_protocols": "Protocolos permitidos", + "app_name": "Nome do aplicativo", + "app_passwd": "Senha do aplicativo", + "app_passwd_protocols": "Protocolos permitidos para a senha do aplicativo", + "automap": "Tente mapear pastas automaticamente (“Itens enviados”, “Enviados” => “Enviados” etc.)", + "backup_mx_options": "Opções de relé", + "bcc_dest_format": "O destino do BCC deve ser um único endereço de e-mail válido.
    Se precisar enviar uma cópia para vários endereços, crie um alias e use-o aqui.", + "client_id": "ID do cliente", + "client_secret": "Segredo do cliente", + "comment_info": "Um comentário privado não é visível para o usuário, enquanto um comentário público é mostrado como dica de ferramenta ao passar o mouse sobre ele na visão geral do usuário", + "created_on": "Criado em", + "delete1": "Excluir da fonte quando concluído", + "delete2": "Excluir mensagens no destino que não estão na origem", + "delete2duplicates": "Excluir duplicatas no destino", + "delete_ays": "Confirme o processo de exclusão.", + "description": "Descrição", + "disable_login": "Não permitir login (e-mails recebidos ainda são aceitos)", + "domain": "Editar domínio", + "domain_admin": "Editar administrador de domínio", + "domain_footer": "Rodapé amplo do domínio", + "domain_footer_html": "rodapé HTML", + "domain_footer_info": "Os rodapés de todo o domínio são adicionados a todos os e-mails enviados associados a um endereço dentro desse domínio.
    As seguintes variáveis podem ser usadas para o rodapé:", + "domain_footer_info_vars": { + "auth_user": "{= auth_user =} - Nome de usuário autenticado especificado por um MTA", + "from_user": "{= from_user =} - Da parte do envelope do usuário, por exemplo, para \"moo@mailcow.tld\", ele retorna “moo”", + "from_name": "{= from_name =} - Do nome do envelope, por exemplo, para “Mailcow < moo@mailcow.tld >”, ele retorna “Mailcow”", + "from_addr": "{= from_addr =} - Do endereço, parte do envelope", + "from_domain": "{= from_domain =} - Da parte do domínio do envelope" + }, + "domain_footer_plain": "Rodapé simples", + "domain_quota": "Cota de domínio", + "domains": "Domínios", + "dont_check_sender_acl": "Desativar a verificação de remetente para o domínio %s (+ domínios de alias)", + "edit_alias_domain": "Editar domínio Alias", + "encryption": "Criptografia", + "exclude": "Excluir objetos (regex)", + "extended_sender_acl": "Endereços de remetentes externos", + "extended_sender_acl_info": "Uma chave de domínio DKIM deve ser importada, se disponível.
    \r\n Lembre-se de adicionar esse servidor ao registro TXT SPF correspondente.
    \r\n Sempre que um domínio ou domínio de alias é adicionado a esse servidor, que se sobrepõe a um endereço externo, o endereço externo é removido.
    \r\n Use @domain .tld para permitir o envio como * @domain .tld.", + "force_pw_update": "Forçar a atualização da senha no próximo login", + "force_pw_update_info": "Esse usuário só poderá fazer login em %s. As senhas do aplicativo permanecem utilizáveis.", + "full_name": "Nome completo", + "gal": "Lista de endereços global", + "gal_info": "A GAL contém todos os objetos de um domínio e não pode ser editada por nenhum usuário. Faltam informações de disponibilidade no SoGo, se desativadas! Reinicie o SoGo para aplicar as alterações.", + "generate": "geram", + "grant_types": "Tipos de subsídios", + "hostname": "Nome do host", + "inactive": "Inativo", + "kind": "Gentil", + "last_modified": "Última modificação", + "lookup_mx": "Destination é uma expressão regular que corresponde ao nome MX (.*\\ .google\\ .com para rotear todos os e-mails direcionados a um MX que termina em google.com nesse salto)", + "mailbox": "Editar caixa de correio", + "mailbox_quota_def": "Cota de caixa de correio padrão", + "mailbox_relayhost_info": "Aplicado somente à caixa de correio e aos aliases diretos, substitui um host de retransmissão de domínio.", + "max_aliases": "Máximo de aliases", + "max_mailboxes": "Número máximo de caixas de correio possíveis", + "max_quota": "Cota máxima por caixa de correio (MiB)", + "maxage": "Duração máxima das mensagens em dias que serão pesquisadas remotamente
    (0 = ignorar a idade)", + "maxbytespersecond": "Máximo de bytes por segundo
    (0 = ilimitado)", + "mbox_rl_info": "Esse limite de taxa é aplicado ao nome de login do SASL e corresponde a qualquer endereço “de” usado pelo usuário conectado. Um limite de taxa de caixa de correio substitui um limite de taxa em todo o domínio.", + "mins_interval": "Intervalo (min)", + "multiple_bookings": "Várias reservas", + "none_inherit": "Nenhum/Herdar", + "nexthop": "Próximo salto", + "password": "Senha", + "password_repeat": "Senha de confirmação (repetição)", + "previous": "Página anterior", + "private_comment": "Comentário privado", + "public_comment": "Comentário público", + "pushover": "Pushover", + "pushover_evaluate_x_prio": "Escale e-mails de alta prioridade [X-Priority: 1]", + "pushover_info": "As configurações de notificação push serão aplicadas a todos os e-mails limpos (sem spam) entregues a %s, incluindo aliases (compartilhados, não compartilhados, marcados).", + "pushover_only_x_prio": "Considere somente e-mails de alta prioridade [X-Priority: 1]", + "pushover_sender_array": "Considere apenas os seguintes endereços de e-mail do remetente (separados por vírgula)", + "pushover_sender_regex": "Considere o seguinte regex do remetente", + "pushover_text": "Texto de notificação", + "pushover_title": "Título da notificação", + "pushover_sound": "Som", + "pushover_vars": "Quando nenhum filtro de remetente for definido, todos os e-mails serão considerados.
    Os filtros Regex, bem como as verificações exatas do remetente, podem ser definidos individualmente e serão considerados sequencialmente. Eles não dependem um do outro.
    Variáveis utilizáveis para texto e título (observe as políticas de proteção de dados)", + "pushover_verify": "Verifique as credenciais", + "quota_mb": "Cota (MiB)", + "quota_warning_bcc": "Aviso de cota BCC", + "quota_warning_bcc_info": "Os avisos serão enviados em cópias separadas para os seguintes destinatários. O assunto será sufixado pelo nome de usuário correspondente entre colchetes, por exemplo: Aviso de cota (user@example.com).", + "ratelimit": "Limite de taxa", + "redirect_uri": "URL de redirecionamento/retorno de chamada", + "relay_all": "Retransmita todos os destinatários", + "relay_all_info": "↪ Se você optar por não retransmitir todos os destinatários, precisará adicionar uma caixa de correio (“cega”) para cada destinatário que deve ser retransmitido.", + "relay_domain": "Retransmitir este domínio", + "relay_transport_info": "
    Informações
    Você pode definir mapas de transporte para um destino personalizado para esse domínio. Se não for definido, uma pesquisa MX será feita.", + "relay_unknown_only": "Retransmita somente caixas de correio não existentes. As caixas de correio existentes serão entregues localmente.", + "relayhost": "Transportes dependentes do remetente", + "remove": "Remover", + "resource": "Recurso", + "save": "Salvar alterações", + "scope": "Escopo", + "sender_acl": "Permitir enviar como", + "sender_acl_disabled": "A verificação do remetente está desativada", + "sender_acl_info": "Se o usuário A da caixa de correio tiver permissão para enviar como usuário B da caixa de correio, o endereço do remetente não será exibido automaticamente como campo “de” selecionável no SoGo.
    \r\n O usuário B da caixa de correio precisa criar uma delegação no SoGo para permitir que o usuário A da caixa de correio selecione seu endereço como remetente. Para delegar uma caixa de correio no SoGo, use o menu (três pontos) à direita do nome da sua caixa de correio no canto superior esquerdo enquanto estiver na visualização de e-mail. Esse comportamento não se aplica a endereços de alias.", + "sieve_desc": "Breve descrição", + "sieve_type": "Tipo de filtro", + "skipcrossduplicates": "Ignore mensagens duplicadas entre pastas (primeiro a chegar, primeiro a ser servido)", + "sogo_access": "Conceder acesso de login direto ao SoGo", + "sogo_access_info": "O login único de dentro da interface do usuário de e-mail continua funcionando. Essa configuração não afeta o acesso a todos os outros serviços nem exclui ou altera o perfil SoGo existente de um usuário.", + "sogo_visible": "O alias é visível no SoGo", + "sogo_visible_info": "Essa opção afeta somente objetos, que podem ser exibidos no SoGo (endereços de alias compartilhados ou não compartilhados apontando para pelo menos uma caixa de correio local). Se estiver oculto, um alias não aparecerá como remetente selecionável no SoGo.", + "spam_alias": "Crie ou altere endereços de alias com limite de tempo", + "spam_filter": "Filtro de spam", + "spam_policy": "Adicionar ou remover itens da lista branca/negra", + "spam_score": "Defina uma pontuação de spam personalizada", + "subfolder2": "Sincronizar na subpasta no destino
    (vazio = não usar subpasta)", + "syncjob": "Editar tarefa de sincronização", + "target_address": "Ir para endereço/es (separados por vírgula)", + "target_domain": "Domínio de destino", + "timeout1": "Tempo limite para conexão com o host remoto", + "timeout2": "Tempo limite para conexão com o host local", + "title": "Editar objeto", + "unchanged_if_empty": "Se inalterado, deixe em branco", + "username": "Nome de usuário", + "validate_save": "Valide e salve" + }, + "fido2": { + "confirm": "Confirme", + "fido2_auth": "Faça login com FIDO2", + "fido2_success": "Dispositivo registrado com sucesso", + "fido2_validation_failed": "Falha na validação", + "fn": "Nome amigável", + "known_ids": "IDs conhecidos", + "none": "Deficiente", + "register_status": "Status do registro", + "rename": "Renomear", + "set_fido2": "Registre o dispositivo FIDO2", + "set_fido2_touchid": "Registre o Touch ID no Apple M1", + "set_fn": "Defina um nome amigável", + "start_fido2_validation": "Inicie a validação do FIDO2" + }, + "footer": { + "cancel": "Cancelar", + "confirm_delete": "Confirme a exclusão", + "delete_now": "Excluir agora", + "delete_these_items": "Confirme suas alterações no seguinte ID de objeto", + "hibp_check": "Verifique em haveibeenpwned.com", + "hibp_nok": "Combinado! Essa é uma senha potencialmente perigosa!", + "hibp_ok": "Nenhuma combinação encontrada.", + "loading": "Por favor, espere...", + "nothing_selected": "Nada selecionado", + "restart_container": "Reiniciar contêiner", + "restart_container_info": "Importante: uma reinicialização normal pode demorar um pouco para ser concluída. Aguarde a conclusão.", + "restart_now": "Reinicie agora", + "restarting_container": "Reiniciando o contêiner, isso pode demorar um pouco" + }, + "header": { + "administration": "Configuração e detalhes", + "apps": "Aplicativos", + "debug": "Informações", + "email": "Correio eletrônico", + "mailcow_system": "Sistema", + "mailcow_config": "Configuração", + "quarantine": "Quarentena", + "restart_netfilter": "Reinicie o filtro de rede", + "restart_sogo": "Reinicie o SoGo", + "user_settings": "Configurações do usuário" + }, + "info": { + "awaiting_tfa_confirmation": "Aguardando a confirmação do TFA", + "no_action": "Nenhuma ação aplicável", + "session_expires": "Sua sessão expirará em cerca de 15 segundos" + }, + "login": { + "delayed": "O login foi atrasado em %s segundos.", + "fido2_webauthn": "Login do FIDO2/WebAuthn", + "login": "Login", + "mobileconfig_info": "Faça login como usuário da caixa de correio para baixar o perfil de conexão Apple solicitado.", + "other_logins": "Login com chave", + "password": "Senha", + "username": "Nome de usuário" + }, + "mailbox": { + "action": "Ação", + "activate": "Ativar", + "active": "Ativo", + "add": "Adicionar", + "add_alias": "Adicionar alias", + "add_alias_expand": "Expanda o alias em domínios de alias", + "add_bcc_entry": "Adicionar mapa BCC", + "add_domain": "Adicionar domínio", + "add_domain_alias": "Adicionar alias de domínio", + "add_domain_record_first": "Por favor, adicione um domínio primeiro", + "add_filter": "Adicionar filtro", + "add_mailbox": "Adicionar caixa de correio", + "add_recipient_map_entry": "Adicionar mapa do destinatário", + "add_resource": "Adicionar recurso", + "add_template": "Adicionar modelo", + "add_tls_policy_map": "Adicionar mapa de política TLS", + "address_rewriting": "Reescrita de endereço", + "alias": "Pseudônimo", + "alias_domain_alias_hint": "Os aliases não são aplicados automaticamente aos aliases de domínio. Um endereço de alias my-alias @domain não cobre o endereço my-alias @alias -domain (onde “alias-domain” é um domínio de alias imaginário para “domain”).
    Use um filtro de peneira para redirecionar e-mails para uma caixa de correio externa (consulte a guia “Filtros” ou use SoGo -> Forwarder). Use “Expandir alias em domínios de alias” para adicionar automaticamente os aliases ausentes.", + "alias_domain_backupmx": "Domínio de alias inativo para domínio de retransmissão", + "aliases": "Pseudônimos", + "all_domains": "Todos os domínios", + "allow_from_smtp": "Permita que esses IPs usem apenas SMTP", + "allow_from_smtp_info": "Deixe em branco para permitir todos os remetentes. Endereços e
    redes IPv4/IPv6.", + "allowed_protocols": "Protocolos permitidos para acesso direto do usuário (não afeta os protocolos de senha do aplicativo)", + "backup_mx": "Domínio de retransmissão", + "bcc": "BCC", + "bcc_destination": "Destino BCC", + "bcc_destinations": "Destino BCC", + "bcc_info": "Os mapas BCC são usados para encaminhar silenciosamente cópias de todas as mensagens para outro endereço. Uma entrada do tipo mapa do destinatário é usada quando o destino local atua como destinatário de um e-mail. Os mapas do remetente estão em conformidade com o mesmo princípio.
    \r\n O destino local não será informado sobre uma falha na entrega.", + "bcc_local_dest": "Destino local", + "bcc_map": "mapa do BCC", + "bcc_map_type": "Tipo BCC", + "bcc_maps": "Mapas BCC", + "bcc_rcpt_map": "Mapa do destinatário", + "bcc_sender_map": "Mapa do remetente", + "bcc_to_rcpt": "Mudar para o tipo de mapa do destinatário", + "bcc_to_sender": "Mudar para o tipo de mapa do remetente", + "bcc_type": "Tipo BCC", + "booking_null": "Sempre mostre como gratuito", + "booking_0_short": "Sempre grátis", + "booking_custom": "Limite rígido para uma quantidade personalizada de reservas", + "booking_custom_short": "Limite rígido", + "booking_ltnull": "Ilimitado, mas mostre como ocupado quando reservado", + "booking_lt0_short": "Limite flexível", + "catch_all": "Apanhável", + "created_on": "Criado em", + "daily": "Diariamente", + "deactivate": "Desativar", + "description": "Descrição", + "disable_login": "Não permitir login (e-mails recebidos ainda são aceitos)", + "disable_x": "Desativar", + "dkim_domains_selector": "Seletor", + "dkim_key_length": "Comprimento da chave DKIM (bits)", + "domain": "Domínio", + "domain_admins": "Administradores de domínio", + "domain_aliases": "Aliases de domínio", + "domain_templates": "Modelos de domínio", + "domain_quota": "Cota", + "domain_quota_total": "Cota total de domínio", + "domains": "Domínios", + "edit": "Editar", + "empty": "Sem resultados", + "enable_x": "Habilitar", + "excludes": "Exclui", + "filter_table": "Tabela de filtros", + "filters": "Filtros", + "fname": "Nome completo", + "force_pw_update": "Forçar a atualização da senha no próximo login", + "gal": "Lista de endereços global", + "goto_ham": "Aprenda como presunto", + "goto_spam": "Aprenda como spam", + "hourly": "A cada hora", + "in_use": "Em uso (%)", + "inactive": "Inativo", + "insert_preset": "Inserir exemplo de predefinição “%s”", + "kind": "Gentil", + "last_mail_login": "Último login por e-mail", + "last_modified": "Última modificação", + "last_pw_change": "Última alteração de senha", + "last_run": "Última corrida", + "last_run_reset": "Programe a seguir", + "mailbox": "Caixa de correio", + "mailbox_defaults": "Configurações padrão", + "mailbox_defaults_info": "Defina as configurações padrão para novas caixas de correio.", + "mailbox_defquota": "Tamanho padrão da caixa de correio", + "mailbox_templates": "Modelos de caixa de correio", + "mailbox_quota": "Tamanho máximo de uma caixa de correio", + "mailboxes": "Caixas de correio", + "max_aliases": "Máximo de aliases", + "max_mailboxes": "Número máximo de caixas de correio possíveis", + "max_quota": "Cota máxima por caixa de correio", + "mins_interval": "Intervalo (min)", + "msg_num": "Mensagem #", + "multiple_bookings": "Várias reservas", + "never": "Nunca", + "no": "✕", + "no_record": "Nenhum registro para o objeto %s", + "no_record_single": "Sem registro", + "open_logs": "Registros abertos", + "owner": "Proprietário", + "private_comment": "Comentário privado", + "public_comment": "Comentário público", + "q_add_header": "quando movido para a pasta Lixo", + "q_all": " quando movido para a pasta de lixo eletrônico e ao ser rejeitado", + "q_reject": "na rejeição", + "quarantine_category": "Categoria de notificação de quarentena", + "quarantine_notification": "Notificações de quarentena", + "quick_actions": "Ações", + "recipient": "Destinatário", + "recipient_map": "Mapa do destinatário", + "recipient_map_info": "Os mapas de destinatários são usados para substituir o endereço de destino em uma mensagem antes que ela seja entregue.", + "recipient_map_new": "Novo destinatário", + "recipient_map_new_info": "O destino do mapa do destinatário deve ser um endereço de e-mail válido.", + "recipient_map_old": "Destinatário original", + "recipient_map_old_info": "O destino original do mapa de um destinatário deve ser um endereço de e-mail válido ou um nome de domínio.", + "recipient_maps": "Mapas de destinatários", + "relay_all": "Retransmita todos os destinatários", + "relay_unknown": "Retransmitir caixas de correio desconhecidas", + "remove": "Remover", + "resources": "Recursos", + "running": "Correndo", + "sender": "Remetente", + "set_postfilter": "Marcar como postfilter", + "set_prefilter": "Marcar como pré-filtro", + "sieve_info": "Você pode armazenar vários filtros por usuário, mas somente um pré-filtro e um pós-filtro podem estar ativos ao mesmo tempo.
    \r\nCada filtro será processado na ordem descrita. Nem um script com falha nem um “keep;” emitido interromperão o processamento de outros scripts. Mudanças nos scripts globais do Sieve acionarão a reinicialização do Dovecot. Pré-filtro de

    peneira global • Pré-filtro • Scripts de usuário • Pós-filtro • Pós-filtro de peneira global", + "sieve_preset_1": "Descarte e-mails com prováveis tipos de arquivo perigosos", + "sieve_preset_2": "Sempre marque o e-mail de um remetente específico como visto", + "sieve_preset_3": "Descarte silenciosamente, interrompa todo o processamento adicional da peneira", + "sieve_preset_4": "Arquive na CAIXA DE ENTRADA, pule o processamento adicional por filtros de peneira", + "sieve_preset_5": "Resposta automática (férias)", + "sieve_preset_6": "Rejeitar e-mail com resposta", + "sieve_preset_7": "Redirecionar e manter/soltar", + "sieve_preset_8": "Descartar mensagem enviada para um endereço de alias do qual o remetente faz parte", + "sieve_preset_header": "Veja os exemplos de predefinições abaixo. Para obter mais detalhes, consulte a Wikipedia.", + "sogo_visible": "O alias é visível no SoGo", + "sogo_visible_n": "Ocultar alias no SoGo", + "sogo_visible_y": "Mostrar alias no SoGo", + "spam_aliases": "Apelido temporário", + "stats": "Estatísticas", + "status": "Status", + "sync_jobs": "Trabalhos de sincronização", + "syncjob_check_log": "Registro de verificação", + "syncjob_last_run_result": "Resultado da última corrida", + "syncjob_EX_OK": "Sucesso", + "syncjob_EXIT_CONNECTION_FAILURE": "Problema de conexão", + "syncjob_EXIT_TLS_FAILURE": "Problema com conexão criptografada", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problema de autenticação", + "syncjob_EXIT_OVERQUOTA": "A caixa de correio de destino está acima da cota", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Não é possível se conectar ao servidor remoto", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Nome de usuário ou senha incorretos", + "table_size": "Tamanho da mesa", + "table_size_show_n": "Mostrar itens %s", + "target_address": "Vá para o endereço", + "target_domain": "Domínio de destino", + "templates": "Modelos", + "template": "Modelo", + "tls_enforce_in": "Imponha a entrada de TLS", + "tls_enforce_out": "Imponha a saída TLS", + "tls_map_dest": "Destino", + "tls_map_dest_info": "Exemplos: example.org, .example.org, [mail.example.org] :25", + "tls_map_parameters": "Parâmetros", + "tls_map_parameters_info": "Vazio ou parâmetros, por exemplo: protocols=! Cifras SSLv2 = média, exclusão = 3DES", + "tls_map_policy": "Política", + "tls_policy_maps": "Mapas de políticas de TLS", + "tls_policy_maps_enforced_tls": "Essas políticas também substituirão o comportamento dos usuários de caixas de correio que impõem conexões TLS de saída. Se nenhuma política existir abaixo, esses usuários aplicarão os valores padrão especificados como smtp_tls_mandatory_protocols e smtp_tls_mandatory_ciphers.", + "tls_policy_maps_info": "Esse mapa de políticas substitui as regras de transporte TLS de saída, independentemente das configurações de política de TLS do usuário.
    \r\n Consulte a documentação do “smtp_tls_policy_maps” para obter mais informações.", + "tls_policy_maps_long": "Substituições do mapa de políticas de TLS de saída", + "toggle_all": "Alternar tudo", + "username": "Nome de usuário", + "waiting": "Esperando", + "weekly": "Semanalmente", + "yes": "✓" + }, + "oauth2": { + "access_denied": "Faça login como proprietário da caixa de correio para conceder acesso via OAuth2.", + "authorize_app": "Autorizar aplicativo", + "deny": "Negar", + "permit": "Autorizar aplicativo", + "profile": "Perfil", + "profile_desc": "Exibir informações pessoais: nome de usuário, nome completo, criado, modificado, ativo", + "scope_ask_permission": "Um aplicativo solicitou as seguintes permissões" + }, + "quarantine": { + "action": "Ação", + "atts": "Anexos", + "check_hash": "Arquivo de pesquisa hash @ VT", + "confirm": "Confirme", + "confirm_delete": "Confirme a exclusão desse elemento.", + "danger": "Perigo", + "deliver_inbox": "Entregar na caixa de entrada", + "disabled_by_config": "A configuração atual do sistema desativa a funcionalidade de quarentena. Defina “retenções por caixa de correio” e um “tamanho máximo” para os elementos de quarentena.", + "download_eml": "Baixar (.eml)", + "empty": "Sem resultados", + "high_danger": "Alto", + "info": "Informações", + "junk_folder": "Pasta de lixo eletrônico", + "learn_spam_delete": "Aprenda como spam e exclua", + "low_danger": "Baixo", + "medium_danger": "Médio", + "neutral_danger": "Neutro", + "notified": "Notificado", + "qhandler_success": "Solicitação enviada com sucesso para o sistema. Agora você pode fechar a janela.", + "qid": "Respand AID", + "qinfo": "O sistema de quarentena salvará as mensagens rejeitadas no banco de dados (o remetente não terá a impressão de uma mensagem entregue), bem como as mensagens, que são entregues como cópia na pasta Lixo eletrônico de uma caixa de correio.\r\n
    “Aprenda como spam e exclua” aprenderá uma mensagem como spam por meio do teorema bayesiano e também calculará hashes difusos para negar mensagens semelhantes no futuro.\r\n
    Esteja ciente de que aprender várias mensagens pode ser demorado, dependendo do seu sistema.
    Os elementos da lista negra são excluídos da quarentena.", + "qitem": "Item de quarentena", + "quarantine": "Quarentena", + "quick_actions": "Ações", + "quick_delete_link": "Abrir link de exclusão rápida", + "quick_info_link": "Abrir link de informações", + "quick_release_link": "Abrir link de lançamento rápido", + "rcpt": "Destinatário", + "received": "Recebido", + "recipients": "Destinatários", + "refresh": "Atualizar", + "rejected": "Rejeitado", + "release": "Lançamento", + "release_body": "Anexamos sua mensagem como arquivo eml a esta mensagem.", + "release_subject": "Item de quarentena potencialmente prejudicial %s", + "remove": "Remover", + "rewrite_subject": "Reescrever assunto", + "rspamd_result": "Resultado do Rspamd", + "sender": "Remetente (SMTP)", + "sender_header": "Remetente (cabeçalho “De”)", + "settings_info": "Quantidade máxima de elementos a serem colocados em quarentena: %s
    Tamanho máximo do e-mail: %s MiB", + "show_item": "Mostrar item", + "spam": "Spam", + "spam_score": "Ponto", + "subj": "Assunto", + "table_size": "Tamanho da mesa", + "table_size_show_n": "Mostrar itens %s", + "text_from_html_content": "Conteúdo (html convertido)", + "text_plain_content": "Conteúdo (texto/simples)", + "toggle_all": "Alternar tudo", + "type": "Tipo" + }, + "queue": { + "delete": "Excluir tudo", + "flush": "Fila de descarga", + "info": "A fila de e-mails contém todos os e-mails que estão aguardando a entrega. Se um e-mail ficar preso na fila de e-mails por um longo tempo, ele será automaticamente excluído pelo sistema.
    A mensagem de erro do respectivo e-mail fornece informações sobre o motivo pelo qual o e-mail não pôde ser entregue.", + "legend": "Funções de ações da fila de e-mails:", + "ays": "Confirme que você deseja excluir todos os itens da fila atual.", + "deliver_mail": "Entregar", + "deliver_mail_legend": "Tentativas de reenviar os e-mails selecionados.", + "hold_mail": "Espere", + "hold_mail_legend": "Guarda os e-mails selecionados. (Evita novas tentativas de entrega)", + "queue_manager": "Gerenciador de filas", + "show_message": "Mostrar mensagem", + "unban": "fila desbloqueada", + "unhold_mail": "Dessegurar", + "unhold_mail_legend": "Libera e-mails selecionados para entrega. (Requer retenção prévia)" + }, + "ratelimit": { + "disabled": "Deficiente", + "second": "msgs//segundo", + "minute": "msgs//minuto", + "hour": "msgs//hora", + "day": "msgs//dia" + }, + "start": { + "help": "Mostrar/ocultar painel de ajuda", + "imap_smtp_server_auth_info": "Use seu endereço de e-mail completo e o mecanismo de autenticação PLAIN.
    \r\nSeus dados de login serão criptografados pela criptografia obrigatória do lado do servidor.", + "mailcow_apps_detail": "Use um aplicativo mailcow para acessar seus e-mails, calendário, contatos e muito mais.", + "mailcow_panel_detail": "Os administradores de domínio criam, modificam ou excluem caixas de correio e aliases, alteram domínios e leem mais informações sobre seus domínios atribuídos.
    \r\nOs usuários de caixas de correio podem criar aliases com limite de tempo (aliases de spam), alterar suas configurações de senha e filtro de spam." + }, + "success": { + "acl_saved": "ACL para o objeto %s salvo", + "admin_added": "O administrador %s foi adicionado", + "admin_api_modified": "As alterações na API foram salvas", + "admin_modified": "As alterações no administrador foram salvas", + "admin_removed": "O administrador %s foi removido", + "alias_added": "O endereço de alias %s (%d) foi adicionado", + "alias_domain_removed": "O domínio alias %s foi removido", + "alias_modified": "As alterações no endereço de alias %s foram salvas", + "alias_removed": "O alias %s foi removido", + "aliasd_added": "Domínio de alias %s adicionado", + "aliasd_modified": "As alterações no domínio alias %s foram salvas", + "app_links": "Alterações salvas nos links do aplicativo", + "app_passwd_added": "Foi adicionada uma nova senha de aplicativo", + "app_passwd_removed": "ID de senha do aplicativo %s removida", + "bcc_deleted": "Entradas do mapa BCC excluídas: %s", + "bcc_edited": "Entrada %s do mapa BCC editada", + "bcc_saved": "Entrada do mapa BCC salva", + "cors_headers_edited": "As configurações do CORS foram salvas", + "db_init_complete": "Inicialização do banco de dados concluída", + "delete_filter": "ID de filtros excluídos %s", + "delete_filters": "Filtros excluídos: %s", + "deleted_syncjob": "ID de trabalho de sincronização excluída %s", + "deleted_syncjobs": "Trabalhos de sincronização excluídos: %s", + "dkim_added": "A chave DKIM %s foi salva", + "domain_add_dkim_available": "Já existia uma chave DKIM", + "dkim_duplicated": "A chave DKIM para o domínio %s foi copiada para %s", + "dkim_removed": "A chave DKIM %s foi removida", + "domain_added": "Domínio adicionado %s", + "domain_admin_added": "O administrador de domínio %s foi adicionado", + "domain_admin_modified": "As alterações no administrador de domínio %s foram salvas", + "domain_admin_removed": "O administrador do domínio %s foi removido", + "domain_footer_modified": "As alterações no rodapé do domínio %s foram salvas", + "domain_modified": "As alterações no domínio %s foram salvas", + "domain_removed": "O domínio %s foi removido", + "dovecot_restart_success": "O Dovecot foi reiniciado com sucesso", + "eas_reset": "Os dispositivos ActiveSync para o usuário %s foram redefinidos", + "f2b_modified": "As alterações nos parâmetros do Fail2ban foram salvas", + "forwarding_host_added": "O host de encaminhamento %s foi adicionado", + "forwarding_host_removed": "O host de encaminhamento %s foi removido", + "global_filter_written": "O filtro foi gravado com sucesso no arquivo", + "hash_deleted": "Hash excluído", + "ip_check_opt_in_modified": "A verificação de IP foi salva com sucesso", + "item_deleted": "Item %s excluído com sucesso", + "item_released": "Item %s lançado", + "items_deleted": "Item %s excluído com sucesso", + "items_released": "Os itens selecionados foram lançados", + "learned_ham": "Identificação %s como ham aprendida com sucesso", + "license_modified": "As alterações na licença foram salvas", + "logged_in_as": "Conectado como %s", + "mailbox_added": "A caixa de correio %s foi adicionada", + "mailbox_modified": "As alterações na caixa de correio %s foram salvas", + "mailbox_removed": "A caixa de correio %s foi removida", + "nginx_reloaded": "O Nginx foi recarregado", + "object_modified": "As alterações no objeto %s foram salvas", + "password_policy_saved": "A política de senha foi salva com sucesso", + "pushover_settings_edited": "Configurações de Pushover definidas com sucesso. Verifique as credenciais.", + "qlearn_spam": "A ID da mensagem %s foi detectada como spam e excluída", + "queue_command_success": "Comando de fila concluído com sucesso", + "recipient_map_entry_deleted": "A ID do mapa do destinatário %s foi excluída", + "recipient_map_entry_saved": "A entrada “%s” do mapa do destinatário foi salva", + "relayhost_added": "A entrada de mapa %s foi adicionada", + "relayhost_removed": "A entrada de mapa %s foi removida", + "reset_main_logo": "Redefinir para o logotipo padrão", + "resource_added": "O recurso %s foi adicionado", + "resource_modified": "As alterações na caixa de correio %s foram salvas", + "resource_removed": "O recurso %s foi removido", + "rl_saved": "Limite de taxa para o objeto %s salvo", + "rspamd_ui_pw_set": "Senha do Rspamd UI definida com sucesso", + "saved_settings": "Configurações salvas", + "settings_map_added": "Entrada de mapa de configurações adicionada", + "settings_map_removed": "ID do mapa de configurações removida %s", + "sogo_profile_reset": "O perfil SoGo para o usuário %s foi redefinido", + "template_added": "Modelo adicionado %s", + "template_modified": "As alterações no modelo %s foram salvas", + "template_removed": "A ID do modelo %s foi excluída", + "tls_policy_map_entry_deleted": "O ID do mapa de política TLS %s foi excluído", + "tls_policy_map_entry_saved": "A entrada “%s” do mapa de políticas TLS foi salva", + "ui_texts": "Alterações salvas nos textos da interface do usuário", + "upload_success": "Arquivo carregado com sucesso", + "verified_fido2_login": "Login FIDO2 verificado", + "verified_totp_login": "Login TOTP verificado", + "verified_webauthn_login": "Login verificado do WebAuthn", + "verified_yotp_login": "Login OTP verificado do Yubico" + }, + "tfa": { + "api_register": "%s usa a API Yubico Cloud. Obtenha uma chave de API para sua chave aqui", + "confirm": "Confirme", + "confirm_totp_token": "Confirme suas alterações inserindo o token gerado", + "delete_tfa": "Desativar o TFA", + "disable_tfa": "Desative o TFA até o próximo login bem-sucedido", + "enter_qr_code": "Seu código TOTP, caso seu dispositivo não consiga escanear códigos QR", + "error_code": "Código de erro", + "init_webauthn": "Inicializando, aguarde...", + "key_id": "Um identificador para o seu dispositivo", + "key_id_totp": "Um identificador para sua chave", + "none": "Desativar", + "reload_retry": "- (recarregue o navegador se o erro persistir)", + "scan_qr_code": "Escaneie o código a seguir com seu aplicativo autenticador ou insira o código manualmente.", + "select": "Por favor, selecione", + "set_tfa": "Defina o método de autenticação de dois fatores", + "start_webauthn_validation": "Iniciar validação", + "tfa": "Autenticação de dois fatores", + "tfa_token_invalid": "Token TFA inválido", + "totp": "OTP baseado em tempo (Google Authenticator, Authy etc.)", + "u2f_deprecated": "Parece que sua chave foi registrada usando o método U2F obsoleto. Desativaremos a autenticação de dois fatores para você e excluiremos sua chave.", + "u2f_deprecated_important": "Registre sua chave no painel de administração com o novo método WebAuthn.", + "webauthn": "Autenticação WebAuthn", + "waiting_usb_auth": "Aguardando o dispositivo USB...

    Toque no botão no seu dispositivo USB agora.", + "waiting_usb_register": "Aguardando o dispositivo USB...

    Digite sua senha acima e confirme seu registro tocando no botão no seu dispositivo USB.", + "yubi_otp": "Autenticação Yubico OTP" + }, + "user": { + "action": "Ação", + "active": "Ativo", + "active_sieve": "Filtro ativo", + "advanced_settings": "Configurações avançadas", + "alias": "Pseudônimo", + "alias_create_random": "Gere um alias aleatório", + "alias_extend_all": "Estenda os aliases em 1 hora", + "alias_full_date": "D.M.Y., H: S T", + "alias_remove_all": "Remover todos os aliases", + "alias_select_validity": "Período de validade", + "alias_time_left": "Tempo restante", + "alias_valid_until": "Válido até", + "aliases_also_send_as": "Também é permitido enviar como usuário", + "aliases_send_as_all": "Não verifique o acesso do remetente aos seguintes domínios e seus domínios de alias", + "app_hint": "As senhas de aplicativos são senhas alternativas para seu login IMAP, SMTP, CalDAV, CardDAV e EAS. O nome de usuário permanece inalterado. O webmail do SoGo não está disponível por meio de senhas de aplicativos.", + "allowed_protocols": "Protocolos permitidos", + "app_name": "Nome do aplicativo", + "app_passwds": "Senhas de aplicativos", + "apple_connection_profile": "Perfil de conexão da Apple", + "apple_connection_profile_complete": "Esse perfil de conexão inclui parâmetros IMAP e SMTP, bem como caminhos CalDAV (calendários) e CardDAV (contatos) para um dispositivo Apple.", + "apple_connection_profile_mailonly": "Esse perfil de conexão inclui parâmetros de configuração IMAP e SMTP para um dispositivo Apple.", + "apple_connection_profile_with_app_password": "Uma nova senha de aplicativo é gerada e adicionada ao perfil para que nenhuma senha precise ser inserida ao configurar seu dispositivo. Não compartilhe o arquivo, pois ele concede acesso total à sua caixa de correio.", + "change_password": "Alterar senha", + "change_password_hint_app_passwords": "Sua conta tem %d senhas de aplicativos que não serão alteradas. Para gerenciá-las, acesse a guia Senhas do aplicativo.", + "clear_recent_successful_connections": "Conexões bem-sucedidas e claras", + "client_configuration": "Mostrar guias de configuração para clientes de e-mail e smartphones", + "create_app_passwd": "Crie a senha do aplicativo", + "create_syncjob": "Criar um novo trabalho de sincronização", + "created_on": "Criado em", + "daily": "Diariamente", + "day": "dia", + "delete_ays": "Confirme o processo de exclusão.", + "direct_aliases": "Endereços de alias diretos", + "direct_aliases_desc": "Os endereços de alias diretos são afetados pelo filtro de spam e pelas configurações da política TLS.", + "direct_protocol_access": "Esse usuário da caixa de correio tem acesso externo direto aos seguintes protocolos e aplicativos. Essa configuração é controlada pelo administrador. As senhas de aplicativos podem ser criadas para conceder acesso a protocolos e aplicativos individuais.
    O botão “Login no webmail” fornece login único no SoGo e está sempre disponível.", + "eas_reset": "Redefinir o cache do dispositivo ActiveSync", + "eas_reset_help": "Em muitos casos, uma redefinição do cache do dispositivo ajudará a recuperar um perfil quebrado do ActiveSync.
    Atenção: Todos os elementos serão baixados novamente!", + "eas_reset_now": "Reinicie agora", + "edit": "Editar", + "email": "E-mail", + "email_and_dav": "E-mail, calendários e contatos", + "empty": "Sem resultados", + "encryption": "Criptografia", + "excludes": "Exclui", + "expire_in": "Expirar em", + "fido2_webauthn": "FIDO2/WebAuthn", + "force_pw_update": "Você deve definir uma nova senha para poder acessar os serviços relacionados ao groupware.", + "from": "desde", + "generate": "geram", + "hour": "hora", + "hourly": "A cada hora", + "hours": "horas", + "in_use": "Usado", + "interval": "Intervalo", + "is_catch_all": "Abrangente para domínio/s", + "last_mail_login": "Último login por e-mail", + "last_pw_change": "Última alteração de senha", + "last_run": "Última corrida", + "last_ui_login": "Último login na interface do usuário", + "loading": "Carregando...", + "login_history": "Histórico de login", + "mailbox": "Caixa de correio", + "mailbox_details": "Detalhes", + "mailbox_general": "Geral", + "mailbox_settings": "Configurações", + "messages": "mensagens", + "month": "mês", + "months": "meses", + "never": "Nunca", + "new_password": "Nova senha", + "new_password_repeat": "Senha de confirmação (repetição)", + "no_active_filter": "Nenhum filtro ativo disponível", + "no_last_login": "Nenhuma informação de login da última interface", + "no_record": "Sem registro", + "open_logs": "Registros abertos", + "open_webmail_sso": "Faça login no webmail", + "password": "Senha", + "password_now": "Senha atual (confirme as alterações)", + "password_repeat": "Senha (repetição)", + "pushover_evaluate_x_prio": "Escale e-mails de alta prioridade [X-Priority: 1]", + "pushover_info": "As configurações de notificação push serão aplicadas a todos os e-mails limpos (sem spam) entregues a %s, incluindo aliases (compartilhados, não compartilhados, marcados).", + "pushover_only_x_prio": "Considere somente e-mails de alta prioridade [X-Priority: 1]", + "pushover_sender_array": "Considere os seguintes endereços de e-mail do remetente (separados por vírgula)", + "pushover_sender_regex": "Combine os remetentes pelo seguinte regex", + "pushover_text": "Texto de notificação", + "pushover_title": "Título da notificação", + "pushover_sound": "Som", + "pushover_vars": "Quando nenhum filtro de remetente for definido, todos os e-mails serão considerados.
    Os filtros Regex, bem como as verificações exatas do remetente, podem ser definidos individualmente e serão considerados sequencialmente. Eles não dependem um do outro.
    Variáveis utilizáveis para texto e título (observe as políticas de proteção de dados)", + "pushover_verify": "Verifique as credenciais", + "q_add_header": "Pasta de lixo eletrônico", + "q_all": "Todas as categorias", + "q_reject": "Rejeitado", + "quarantine_category": "Categoria de notificação de quarentena", + "quarantine_category_info": "A categoria de notificação “Rejeitado” inclui e-mails que foram rejeitados, enquanto “Pasta de lixo eletrônico” notificará o usuário sobre e-mails que foram colocados na pasta de lixo eletrônico.", + "quarantine_notification": "Notificações de quarentena", + "quarantine_notification_info": "Depois que uma notificação for enviada, os itens serão marcados como “notificados” e nenhuma outra notificação será enviada para esse item específico.", + "recent_successful_connections": "Conexões bem-sucedidas vistas", + "remove": "Remover", + "running": "Correndo", + "save": "Salvar alterações", + "save_changes": "Salvar alterações", + "sender_acl_disabled": "A verificação do remetente está desativada", + "shared_aliases": "Endereços de alias compartilhados", + "shared_aliases_desc": "Os aliases compartilhados não são afetados pelas configurações específicas do usuário, como o filtro de spam ou a política de criptografia. Os filtros de spam correspondentes só podem ser criados por um administrador como uma política de todo o domínio.", + "show_sieve_filters": "Mostrar filtro de filtragem de usuário ativo", + "sogo_profile_reset": "Redefinir perfil SoGo", + "sogo_profile_reset_help": "Isso destruirá o perfil SoGo de um usuário e excluirá todos os dados de contato e calendário irrecuperáveis.", + "sogo_profile_reset_now": "Redefina o perfil agora", + "spam_aliases": "Aliases de e-mail temporários", + "spam_score_reset": "Redefinir para o padrão do servidor", + "spamfilter": "Filtro de spam", + "spamfilter_behavior": "Avaliação", + "spamfilter_bl": "Lista negra", + "spamfilter_bl_desc": "Endereços de e-mail na lista negra para sempre serem classificados como spam e rejeitados. E-mails rejeitados não serão copiados para a quarentena. Podem ser usados curingas. Um filtro só é aplicado a aliases diretos (aliases com uma única caixa de correio de destino), excluindo aliases abrangentes e a própria caixa de correio.", + "spamfilter_default_score": "Valores padrão", + "spamfilter_green": "Verde: esta mensagem não é spam", + "spamfilter_hint": "O primeiro valor descreve a “pontuação baixa de spam”, o segundo representa a “alta pontuação de spam”.", + "spamfilter_red": "Vermelho: Esta mensagem é spam e será rejeitada pelo servidor", + "spamfilter_table_action": "Ação", + "spamfilter_table_add": "Adicionar item", + "spamfilter_table_domain_policy": "n/a (política de domínio)", + "spamfilter_table_empty": "Não há dados para exibir", + "spamfilter_table_remove": "remover", + "spamfilter_table_rule": "Regra", + "spamfilter_wl": "Lista branca", + "spamfilter_wl_desc": "Os endereços de e-mail incluídos na lista branca são programados para nunca serem classificados como spam. Podem ser usados curingas. Um filtro só é aplicado a aliases diretos (aliases com uma única caixa de correio de destino), excluindo aliases abrangentes e a própria caixa de correio.", + "spamfilter_yellow": "Amarelo: esta mensagem pode ser spam, será marcada como spam e movida para sua pasta de lixo eletrônico", + "status": "Status", + "sync_jobs": "Trabalhos de sincronização", + "syncjob_check_log": "Registro de verificação", + "syncjob_last_run_result": "Resultado da última corrida", + "syncjob_EX_OK": "Sucesso", + "syncjob_EXIT_CONNECTION_FAILURE": "Problema de conexão", + "syncjob_EXIT_TLS_FAILURE": "Problema com conexão criptografada", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problema de autenticação", + "syncjob_EXIT_OVERQUOTA": "A caixa de correio de destino está acima da cota", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Não é possível se conectar ao servidor remoto", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Nome de usuário ou senha incorretos", + "tag_handling": "Definir o tratamento para e-mails marcados", + "tag_help_example": "Exemplo de um endereço de e-mail marcado: me +Facebook @example .org", + "tag_help_explain": "Na subpasta: uma nova subpasta com o nome da tag será criada abaixo da CAIXA DE ENTRADA (“Caixa de entrada/Facebook”).
    \r\nNo assunto: o nome das tags será anexado ao assunto do e-mail, por exemplo: “[Facebook] Minhas notícias”.", + "tag_in_none": "Não faça nada", + "tag_in_subfolder": "Na subpasta", + "tag_in_subject": "No assunto", + "text": "Texto", + "title": "Título", + "tls_enforce_in": "Imponha a entrada de TLS", + "tls_enforce_out": "Imponha a saída TLS", + "tls_policy": "Política de criptografia", + "tls_policy_warning": "Aviso: Se você decidir impor a transferência de e-mail criptografada, poderá perder e-mails.
    As mensagens que não satisfizerem a política serão devolvidas com uma falha grave pelo sistema de correio.
    Essa opção se aplica ao seu endereço de e-mail principal (nome de login), a todos os endereços derivados de domínios de alias, bem como aos endereços de alias com apenas essa única caixa de correio como destino.", + "user_settings": "Configurações do usuário", + "username": "Nome de usuário", + "verify": "Verificar", + "waiting": "Esperando", + "week": "semana", + "weekly": "Semanalmente", + "weeks": "semanas", + "with_app_password": "com senha do aplicativo", + "year": "ano", + "years": "anos" + }, + "warning": { + "cannot_delete_self": "Não é possível excluir o usuário conectado", + "domain_added_sogo_failed": "Domínio adicionado, mas falha ao reiniciar o SoGo. Verifique os registros do servidor.", + "dovecot_restart_failed": "Falha ao reiniciar o Dovecot, verifique os registros", + "fuzzy_learn_error": "Erro de aprendizado de hash difuso: %s", + "hash_not_found": "Hash não encontrado ou já foi excluído", + "ip_invalid": "IP inválido ignorado: %s", + "is_not_primary_alias": "Alias não primário ignorado %s", + "no_active_admin": "Não é possível desativar o último administrador ativo", + "quota_exceeded_scope": "Cota de domínio excedida: somente caixas de correio ilimitadas podem ser criadas nesse escopo de domínio.", + "session_token": "Token de formulário inválido: incompatibilidade de token", + "session_ua": "Token de formulário inválido: erro de validação do agente de usuário" + } +} \ No newline at end of file From 59c1e7a18a65feeb98c59365837337cfe4c64035 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 14 Oct 2023 14:26:06 +0200 Subject: [PATCH 117/174] [Web] Updated lang.pt-br.json (#5471) Co-authored-by: Peter --- data/web/lang/lang.pt-br.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/lang/lang.pt-br.json b/data/web/lang/lang.pt-br.json index 1f9228c25..8e5b06a0f 100644 --- a/data/web/lang/lang.pt-br.json +++ b/data/web/lang/lang.pt-br.json @@ -1292,4 +1292,4 @@ "session_token": "Token de formulário inválido: incompatibilidade de token", "session_ua": "Token de formulário inválido: erro de validação do agente de usuário" } -} \ No newline at end of file +} From 87b0683f77c25229a6a903a0e06a89e471934224 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 14 Oct 2023 22:58:28 +0200 Subject: [PATCH 118/174] Translations update from Weblate (#5472) * [Web] Updated lang.cs-cz.json Co-authored-by: Peter Co-authored-by: milkmaker * [Web] Updated lang.sk-sk.json Co-authored-by: Peter --------- Co-authored-by: Peter --- data/web/lang/lang.cs-cz.json | 42 +++++++++++++++++------------------ data/web/lang/lang.sk-sk.json | 25 ++++++++------------- 2 files changed, 30 insertions(+), 37 deletions(-) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index d8ec9bf6b..76b7f2311 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -461,27 +461,27 @@ "yotp_verification_failed": "Yubico OTP ověření selhalo: %s" }, "datatables": { - "emptyTable": "Tabulka neobsahuje žádná data", - "info": "Zobrazuji _START_ až _END_ z celkem _TOTAL_ záznamů", - "infoEmpty": "Zobrazuji 0 až 0 z 0 záznamů", - "infoFiltered": "(filtrováno z celkem _MAX_ záznamů)", - "loadingRecords": "Načítám...", - "zeroRecords": "Žádné záznamy nebyly nalezeny", - "paginate": { - "first": "První", - "last": "Poslední", - "next": "Další", - "previous": "Předchozí" - }, - "aria": { - "sortAscending": ": aktivujte pro seřazení vzestupně", - "sortDescending": ": aktivujte pro seřazení sestupně" - }, - "lengthMenu": "Zobrazit _MENU_ výsledků", - "processing": "Zpracovávání...", - "search": "Vyhledávání:", - "decimal": ",", - "thousands": " " + "emptyTable": "Tabulka neobsahuje žádná data", + "info": "Zobrazuji _START_ až _END_ z celkem _TOTAL_ záznamů", + "infoEmpty": "Zobrazuji 0 až 0 z 0 záznamů", + "infoFiltered": "(filtrováno z celkem _MAX_ záznamů)", + "loadingRecords": "Načítám...", + "zeroRecords": "Žádné záznamy nebyly nalezeny", + "paginate": { + "first": "První", + "last": "Poslední", + "next": "Další", + "previous": "Předchozí" + }, + "aria": { + "sortAscending": ": aktivujte pro seřazení vzestupně", + "sortDescending": ": aktivujte pro seřazení sestupně" + }, + "lengthMenu": "Zobrazit _MENU_ výsledků", + "processing": "Zpracovávání...", + "search": "Vyhledávání:", + "decimal": ",", + "thousands": " " }, "debug": { "chart_this_server": "Graf (tento server)", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 20694e9c0..13e239b75 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -41,7 +41,7 @@ "alias_domain": "Alias doména", "alias_domain_info": "Len platné mená domén (oddelené čiarkou).", "app_name": "Meno aplikácie", - "app_passwd_protocols": "Povolené protokoly pre heslá aplikácií", + "app_passwd_protocols": "Povolené protokoly k heslu aplikácie", "app_password": "Pridať heslo aplikácie", "automap": "Skúsiť automaticky mapovať priečinky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti preposielania", @@ -107,7 +107,6 @@ "username": "Používateľské meno", "validate": "Overiť", "validation_success": "Úspešne overené", - "app_passwd_protocols": "Povolené protokoly k heslu aplikácie", "tags": "Štítky" }, "admin": { @@ -529,7 +528,7 @@ "allowed_protocols": "Povolené protokoly", "app_name": "Meno aplikácie", "app_passwd": "Heslo aplikácie", - "app_passwd_protocols": "Povolené protokoly pre heslá aplikácií", + "app_passwd_protocols": "Povolené protokoly", "automap": "Skúsiť automapovať priečinky (\"Sent items\", \"Sent\" => \"Sent\" atd.)", "backup_mx_options": "Možnosti preposielania", "bcc_dest_format": "Cieľ kópie musí byť jedna platná emailová adresa. Pokiaľ potrebujete posielať kópie na viac adries, vytvorte Alias a použite ho tu.", @@ -614,8 +613,8 @@ "sieve_desc": "Krátky popis", "sieve_type": "Typ filtru", "skipcrossduplicates": "Preskočiť duplikované správy naprieč priečinkami (akceptuje sa prvý nález)", - "sogo_access": "Udeliť priamy prístup k prihláseniu do služby SOGo", - "sogo_access_info": "Jednotné prihlásenie (SSO) z mail UI zostáva funkčné. Toto nastavenie nemá vplyv na prístup k všetkým ostatným službám, ani neodstraňuje alebo nemení existujúci profil používateľa SOGo.", + "sogo_access": "Prideliť priame prihlásenie do SOGo", + "sogo_access_info": "Jednotné prihlásenie z používateľského mail rozhrania zostáva funkčné. Toto nastavenie nemá vplyv na prístup k ostatným službám, ani neodstraňuje alebo nemení existujúci profil používateľa SOGo.", "sogo_visible": "Alias je viditeľný v SOGo", "sogo_visible_info": "Táto voľba ovplyvňuje len objekty, ktoré dokážu byť zobrazené v SOGo (zdieľané alebo nezdieľané alias adresy ukazujúc na minimálne jednu lokálnu mailovú schránku). Ak je skrytý, alias nebude prezentovaný ako voliteľný odosielateľ v SOGo.", "spam_alias": "Vytvoriť alebo zmeniť časovo limitované alias adresy", @@ -631,10 +630,7 @@ "title": "Upraviť objekt", "unchanged_if_empty": "Ak nemeníte, nechajte prázdne", "username": "Používateľské meno", - "validate_save": "Validovať a uložiť", - "sogo_access": "Prideliť priame prihlásenie do SOGo", - "sogo_access_info": "Jednotné prihlásenie z používateľského mail rozhrania zostáva funkčné. Toto nastavenie nemá vplyv na prístup k ostatným službám, ani neodstraňuje alebo nemení existujúci profil používateľa SOGo.", - "app_passwd_protocols": "Povolené protokoly" + "validate_save": "Validovať a uložiť" }, "fido2": { "confirm": "Potvrdiť", @@ -1065,9 +1061,9 @@ "apple_connection_profile": "Apple konfiguračný profil", "apple_connection_profile_complete": "Tento profil zahŕňa IMAP a SMTP parametre, ako aj CalDAV (kalendáre) a CardDAV (kontakty) pre zariadenia Apple.", "apple_connection_profile_mailonly": "Tento profil zahŕňa IMAP a SMTP konfiguračné parametre pre zariadenia Apple.", - "apple_connection_profile_with_app_password": "Nové heslo aplikácie sa vygeneruje a pridá do profilu, takže pri nastavovaní zariadenia nie je potrebné zadávať žiadne heslo. Súbor nezdieľajte, pretože poskytuje úplný prístup k vašej poštovej schránke.", + "apple_connection_profile_with_app_password": "Nové heslo aplikácie sa vygeneruje a pridá do profilu, takže pri nastavovaní zariadenia nie je potrebné zadávať žiadne heslo. Súbor nezdieľajte, pretože poskytuje úplný prístup k vašej mail schránke.", "change_password": "Zmeniť heslo", - "change_password_hint_app_passwords": "Váš účet má %d hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", + "change_password_hint_app_passwords": "Vaše konto má %d hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", "clear_recent_successful_connections": "Vymazať nedávne úspešné prihlásenia", "client_configuration": "Zobraziť konfiguračné pokyny pre emailových klientov a smartfóny", "create_app_passwd": "Vytvoriť heslo aplikácie", @@ -1078,7 +1074,7 @@ "delete_ays": "Potvrďte zmazanie.", "direct_aliases": "Priame alias adresy", "direct_aliases_desc": "Priame aliasy sú ovplyvnené spam filtrom a nastavením TLS pravidiel.", - "direct_protocol_access": "Tento používateľ mailovej schránky má priamy, externý prístup k nasledujúcim protokolom a aplikáciám. Toto nastavenie má pod kontrolou Váš správca. Na udelenie prístupu k jednotlivým protokolom a aplikáciám je možné vytvoriť heslá aplikácií.
    Tlačidlo \" Prihláste sa do webmailu\" poskytuje jednotné prihlásenie do systému SOGo a je vždy k dispozícii.", + "direct_protocol_access": "Tento používateľ mailovej schránky má priamy, externý prístup k nasledujúcim protokolom a aplikáciám. Toto nastavenie kontroluje administrátor. Na udelenie prístupu k jednotlivým protokolom a aplikáciám je možné vytvoriť heslá aplikácií.
    Tlačidlo \"Prihlásenie do webmailu\" poskytuje jednotné prihlásenie do systému SOGo a je vždy k dispozícii.", "eas_reset": "Resetovať medzipamäť u ActiveSync zariadení", "eas_reset_help": "Vo väčšine prípadov, reset medzipamäte ActiveSync pomôže opravit nefunkčný profil.
    Pozor: Všetky potrebné dáta budú opäť stiahnuté!", "eas_reset_now": "Reset ActiveSync", @@ -1202,10 +1198,7 @@ "weeks": "týždne", "with_app_password": "s heslom aplikácie", "year": "rok", - "years": "rokov", - "apple_connection_profile_with_app_password": "Nové heslo aplikácie sa vygeneruje a pridá do profilu, takže pri nastavovaní zariadenia nie je potrebné zadávať žiadne heslo. Súbor nezdieľajte, pretože poskytuje úplný prístup k vašej mail schránke.", - "change_password_hint_app_passwords": "Vaše konto má %d hesiel aplikácií, ktoré nebudú zmenené. Ak ich chcete spravovať, prejdite na kartu Heslá aplikácií.", - "direct_protocol_access": "Tento používateľ mailovej schránky má priamy, externý prístup k nasledujúcim protokolom a aplikáciám. Toto nastavenie kontroluje administrátor. Na udelenie prístupu k jednotlivým protokolom a aplikáciám je možné vytvoriť heslá aplikácií.
    Tlačidlo \"Prihlásenie do webmailu\" poskytuje jednotné prihlásenie do systému SOGo a je vždy k dispozícii." + "years": "rokov" }, "warning": { "cannot_delete_self": "Nemožno vymazať prihláseného používateľa", From 6c649debc963741dae858175d2c22ab0cd763a3d Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 18 Oct 2023 10:31:49 +0200 Subject: [PATCH 119/174] Update DockerAPI to implement CPU load fix --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 8d84e3a75..3d4897b88 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -526,7 +526,7 @@ services: - watchdog dockerapi-mailcow: - image: mailcow/dockerapi:2.05 + image: mailcow/dockerapi:2.06 security_opt: - label=disable restart: always From 61e23b6b81f5f5eaf8b389874c2c25ebecb1e83f Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 19 Oct 2023 12:14:27 +0200 Subject: [PATCH 120/174] Added Dev Mode option for git diff creation --- update.sh | 60 +++++++++++++++++++++++++++++-------------------------- 1 file changed, 32 insertions(+), 28 deletions(-) diff --git a/update.sh b/update.sh index 1d0a3af66..f3bc9c2d1 100755 --- a/update.sh +++ b/update.sh @@ -904,34 +904,38 @@ if [ "$CURRENT_REPO" != "$DEFAULT_REPO" ]; then fi fi -echo -e "\e[32mCommitting current status...\e[0m" -[[ -z "$(git config user.name)" ]] && git config user.name moo -[[ -z "$(git config user.email)" ]] && git config user.email moo@cow.moo -[[ ! -z $(git ls-files data/conf/rspamd/override.d/worker-controller-password.inc) ]] && git rm data/conf/rspamd/override.d/worker-controller-password.inc -git add -u -git commit -am "Before update on ${DATE}" > /dev/null -echo -e "\e[32mFetching updated code from remote...\e[0m" -git fetch origin #${BRANCH} -echo -e "\e[32mMerging local with remote code (recursive, strategy: \"${MERGE_STRATEGY:-theirs}\", options: \"patience\"...\e[0m" -git config merge.defaultToUpstream true -git merge -X${MERGE_STRATEGY:-theirs} -Xpatience -m "After update on ${DATE}" -# Need to use a variable to not pass return codes of if checks -MERGE_RETURN=$? -if [[ ${MERGE_RETURN} == 128 ]]; then - echo -e "\e[31m\nOh no, what happened?\n=> You most likely added files to your local mailcow instance that were now added to the official mailcow repository. Please move them to another location before updating mailcow.\e[0m" - exit 1 -elif [[ ${MERGE_RETURN} == 1 ]]; then - echo -e "\e[93mPotenial conflict, trying to fix...\e[0m" - git status --porcelain | grep -E "UD|DU" | awk '{print $2}' | xargs rm -v - git add -A - git commit -m "After update on ${DATE}" > /dev/null - git checkout . - echo -e "\e[32mRemoved and recreated files if necessary.\e[0m" -elif [[ ${MERGE_RETURN} != 0 ]]; then - echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m" - echo - echo "Run $COMPOSE_COMMAND up -d to restart your stack without updates or try again after fixing the mentioned errors." - exit 1 +if [ ! $DEV ]; then + echo -e "\e[32mCommitting current status...\e[0m" + [[ -z "$(git config user.name)" ]] && git config user.name moo + [[ -z "$(git config user.email)" ]] && git config user.email moo@cow.moo + [[ ! -z $(git ls-files data/conf/rspamd/override.d/worker-controller-password.inc) ]] && git rm data/conf/rspamd/override.d/worker-controller-password.inc + git add -u + git commit -am "Before update on ${DATE}" > /dev/null + echo -e "\e[32mFetching updated code from remote...\e[0m" + git fetch origin #${BRANCH} + echo -e "\e[32mMerging local with remote code (recursive, strategy: \"${MERGE_STRATEGY:-theirs}\", options: \"patience\"...\e[0m" + git config merge.defaultToUpstream true + git merge -X${MERGE_STRATEGY:-theirs} -Xpatience -m "After update on ${DATE}" + # Need to use a variable to not pass return codes of if checks + MERGE_RETURN=$? + if [[ ${MERGE_RETURN} == 128 ]]; then + echo -e "\e[31m\nOh no, what happened?\n=> You most likely added files to your local mailcow instance that were now added to the official mailcow repository. Please move them to another location before updating mailcow.\e[0m" + exit 1 + elif [[ ${MERGE_RETURN} == 1 ]]; then + echo -e "\e[93mPotenial conflict, trying to fix...\e[0m" + git status --porcelain | grep -E "UD|DU" | awk '{print $2}' | xargs rm -v + git add -A + git commit -m "After update on ${DATE}" > /dev/null + git checkout . + echo -e "\e[32mRemoved and recreated files if necessary.\e[0m" + elif [[ ${MERGE_RETURN} != 0 ]]; then + echo -e "\e[31m\nOh no, something went wrong. Please check the error message above.\e[0m" + echo + echo "Run $COMPOSE_COMMAND up -d to restart your stack without updates or try again after fixing the mentioned errors." + exit 1 + fi +elif [ $DEV ]; then + echo -e "\e[33mDEVELOPER MODE: Not creating a git diff and commiting it to prevent development stuff within a backup diff...\e[0m" fi echo -e "\e[32mFetching new images, if any...\e[0m" From 6c6fde8e2e5c39be9042df8d1390d578340c73b4 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 19 Oct 2023 12:31:13 +0200 Subject: [PATCH 121/174] Improved docker image pruning --- update.sh | 67 +++++++++++++++++++++++++------------------------------ 1 file changed, 30 insertions(+), 37 deletions(-) diff --git a/update.sh b/update.sh index f3bc9c2d1..68dcbda1e 100755 --- a/update.sh +++ b/update.sh @@ -32,51 +32,44 @@ prefetch_images() { } docker_garbage() { + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" IMGS_TO_DELETE=() - for container in $(grep -oP "image: \Kmailcow.+" "${SCRIPT_DIR}/docker-compose.yml"); do - REPOSITORY=${container/:*} - TAG=${container/*:} - V_MAIN=${container/*.} - V_SUB=${container/*.} - EXISTING_TAGS=$(docker images | grep ${REPOSITORY} | awk '{ print $2 }') - for existing_tag in ${EXISTING_TAGS[@]}; do - V_MAIN_EXISTING=${existing_tag/*.} - V_SUB_EXISTING=${existing_tag/*.} - # Not an integer - [[ ! $V_MAIN_EXISTING =~ ^[0-9]+$ ]] && continue - [[ ! $V_SUB_EXISTING =~ ^[0-9]+$ ]] && continue - if [[ $V_MAIN_EXISTING == "latest" ]]; then - echo "Found deprecated label \"latest\" for repository $REPOSITORY, it should be deleted." - IMGS_TO_DELETE+=($REPOSITORY:$existing_tag) - elif [[ $V_MAIN_EXISTING -lt $V_MAIN ]]; then - echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted." - IMGS_TO_DELETE+=($REPOSITORY:$existing_tag) - elif [[ $V_SUB_EXISTING -lt $V_SUB ]]; then - echo "Found tag $existing_tag for $REPOSITORY, which is older than the current tag $TAG and should be deleted." - IMGS_TO_DELETE+=($REPOSITORY:$existing_tag) + declare -A IMAGES_INFO + COMPOSE_IMAGES=($(grep -oP "image: \Kmailcow.+" "${SCRIPT_DIR}/docker-compose.yml")) + + for existing_image in $(docker images --format "{{.ID}}:{{.Repository}}:{{.Tag}}" | grep 'mailcow/'); do + ID=$(echo $existing_image | cut -d ':' -f 1) + REPOSITORY=$(echo $existing_image | cut -d ':' -f 2) + TAG=$(echo $existing_image | cut -d ':' -f 3) + + if [[ " ${COMPOSE_IMAGES[@]} " =~ " ${REPOSITORY}:${TAG} " ]]; then + continue + else + IMGS_TO_DELETE+=("$ID") + IMAGES_INFO["$ID"]="$REPOSITORY:$TAG" fi - done done if [[ ! -z ${IMGS_TO_DELETE[*]} ]]; then - echo "Run the following command to delete unused image tags:" - echo - echo " docker rmi ${IMGS_TO_DELETE[*]}" - echo - if [ ! $FORCE ]; then - read -r -p "Do you want to delete old image tags right now? [y/N] " response - if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then - docker rmi ${IMGS_TO_DELETE[*]} + echo "The following unused mailcow images were found:" + for id in "${IMGS_TO_DELETE[@]}"; do + echo " ${IMAGES_INFO[$id]} ($id)" + done + + if [ ! $FORCE ]; then + read -r -p "Do you want to delete them to free up some space? [y/N] " response + if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + docker rmi ${IMGS_TO_DELETE[*]} + else + echo "OK, skipped." + fi else - echo "OK, skipped." + echo "Running in forced mode! Force removing old mailcow images..." + docker rmi ${IMGS_TO_DELETE[*]} fi - else - echo "Running image removal without extra confirmation due to force mode." - docker rmi ${IMGS_TO_DELETE[*]} - fi - echo -e "\e[32mFurther cleanup...\e[0m" - echo "If you want to cleanup further garbage collected by Docker, please make sure all containers are up and running before cleaning your system by executing \"docker system prune\"" + echo -e "\e[32mFurther cleanup...\e[0m" + echo "If you want to cleanup further garbage collected by Docker, please make sure all containers are up and running before cleaning your system by executing \"docker system prune\"" fi } From 3b183933e3a83cca8d1605c7a24294a8d332c596 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Fri, 20 Oct 2023 10:48:04 +0200 Subject: [PATCH 122/174] [Web] add api get spam-score endpoint --- data/web/api/openapi.yaml | 34 ++++++++++++++++++++++++++++++++++ data/web/json_api.php | 6 ++++++ 2 files changed, 40 insertions(+) diff --git a/data/web/api/openapi.yaml b/data/web/api/openapi.yaml index 1d2621689..e8e963e6a 100644 --- a/data/web/api/openapi.yaml +++ b/data/web/api/openapi.yaml @@ -5646,6 +5646,40 @@ paths: items: type: string summary: Edit Cross-Origin Resource Sharing (CORS) settings + "/api/v1/get/spam-score/{mailbox}": + get: + parameters: + - description: name of mailbox or empty for current user - admin user will retrieve the global spam filter score + in: path + name: mailbox + required: true + schema: + type: string + - description: e.g. api-key-string + example: api-key-string + in: header + name: X-API-Key + required: false + schema: + type: string + responses: + "401": + $ref: "#/components/responses/Unauthorized" + "200": + content: + application/json: + examples: + response: + value: + spam_score: "8,15" + description: OK + headers: {} + tags: + - Mailboxes + description: >- + Using this endpoint you can get the global spam filter score or the spam filter score of a certain mailbox. + operationId: Get mailbox or global spam filter score + summary: Get mailbox or global spam filter score tags: - name: Domains diff --git a/data/web/json_api.php b/data/web/json_api.php index b375bc8e4..b8c465fb2 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -1591,6 +1591,12 @@ if (isset($_GET['query'])) { } } break; + case "spam-score": + $score = mailbox('get', 'spam_score', $object); + if ($score) + $score = array("score" => preg_replace("/\s+/", "", $score)); + process_get_return($score); + break; break; // return no route found if no case is matched default: From 53543ccf26c0da15b70dab45fcf6df00f098059d Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 21 Oct 2023 12:10:34 +0200 Subject: [PATCH 123/174] Update thollander/actions-comment-pull-request action to v2.4.3 (#5484) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/check_prs_if_on_staging.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/check_prs_if_on_staging.yml b/.github/workflows/check_prs_if_on_staging.yml index c28454f65..060481d6a 100644 --- a/.github/workflows/check_prs_if_on_staging.yml +++ b/.github/workflows/check_prs_if_on_staging.yml @@ -10,7 +10,7 @@ jobs: if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging steps: - name: Send message - uses: thollander/actions-comment-pull-request@v2.4.2 + uses: thollander/actions-comment-pull-request@v2.4.3 with: GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }} message: | From 03ed81dc3f7c3cd60652d3dcae66e51041f40d59 Mon Sep 17 00:00:00 2001 From: artemislena Date: Mon, 23 Oct 2023 19:44:28 +0200 Subject: [PATCH 124/174] T.: Added a script for generating CAA records --- helper-scripts/generate_caa_record.py | 122 ++++++++++++++++++++++++++ 1 file changed, 122 insertions(+) create mode 100755 helper-scripts/generate_caa_record.py diff --git a/helper-scripts/generate_caa_record.py b/helper-scripts/generate_caa_record.py new file mode 100755 index 000000000..5ccfbd030 --- /dev/null +++ b/helper-scripts/generate_caa_record.py @@ -0,0 +1,122 @@ +#!/usr/bin/env python3 +# Based on github.com/diafygi/acme-tiny, original copyright: +# Copyright Daniel Roesler, under MIT license, see LICENSE at github.com/diafygi/acme-tiny +import argparse, subprocess, json, os, sys, base64, binascii, time, hashlib, re, copy, textwrap, logging +try: + from urllib.request import urlopen, Request # Python 3 +except ImportError: # pragma: no cover + from urllib2 import urlopen, Request # Python 2 + +DEFAULT_DIRECTORY_URL = "https://acme-v02.api.letsencrypt.org/directory" + +LOGGER = logging.getLogger(__name__) +LOGGER.addHandler(logging.StreamHandler()) +LOGGER.setLevel(logging.INFO) + +def get_id(account_key, log=LOGGER, directory_url=DEFAULT_DIRECTORY_URL, contact=None): + directory, acct_headers, alg, jwk = None, None, None, None # global variables + + # helper functions - base64 encode for jose spec + def _b64(b): + return base64.urlsafe_b64encode(b).decode('utf8').replace("=", "") + + # helper function - run external commands + def _cmd(cmd_list, stdin=None, cmd_input=None, err_msg="Command Line Error"): + proc = subprocess.Popen(cmd_list, stdin=stdin, stdout=subprocess.PIPE, stderr=subprocess.PIPE) + out, err = proc.communicate(cmd_input) + if proc.returncode != 0: + raise IOError("{0}\n{1}".format(err_msg, err)) + return out + + # helper function - make request and automatically parse json response + def _do_request(url, data=None, err_msg="Error", depth=0): + try: + resp = urlopen(Request(url, data=data, headers={"Content-Type": "application/jose+json", "User-Agent": "acme-tiny"})) + resp_data, code, headers = resp.read().decode("utf8"), resp.getcode(), resp.headers + except IOError as e: + resp_data = e.read().decode("utf8") if hasattr(e, "read") else str(e) + code, headers = getattr(e, "code", None), {} + try: + resp_data = json.loads(resp_data) # try to parse json results + except ValueError: + pass # ignore json parsing errors + if depth < 100 and code == 400 and resp_data['type'] == "urn:ietf:params:acme:error:badNonce": + raise IndexError(resp_data) # allow 100 retrys for bad nonces + if code not in [200, 201, 204]: + raise ValueError("{0}:\nUrl: {1}\nData: {2}\nResponse Code: {3}\nResponse: {4}".format(err_msg, url, data, code, resp_data)) + return resp_data, code, headers + + # helper function - make signed requests + def _send_signed_request(url, payload, err_msg, depth=0): + payload64 = "" if payload is None else _b64(json.dumps(payload).encode('utf8')) + new_nonce = _do_request(directory['newNonce'])[2]['Replay-Nonce'] + protected = {"url": url, "alg": alg, "nonce": new_nonce} + protected.update({"jwk": jwk} if acct_headers is None else {"kid": acct_headers['Location']}) + protected64 = _b64(json.dumps(protected).encode('utf8')) + protected_input = "{0}.{1}".format(protected64, payload64).encode('utf8') + out = _cmd(["openssl", "dgst", "-sha256", "-sign", account_key], stdin=subprocess.PIPE, cmd_input=protected_input, err_msg="OpenSSL Error") + data = json.dumps({"protected": protected64, "payload": payload64, "signature": _b64(out)}) + try: + return _do_request(url, data=data.encode('utf8'), err_msg=err_msg, depth=depth) + except IndexError: # retry bad nonces (they raise IndexError) + return _send_signed_request(url, payload, err_msg, depth=(depth + 1)) + + # helper function - poll until complete + def _poll_until_not(url, pending_statuses, err_msg): + result, t0 = None, time.time() + while result is None or result['status'] in pending_statuses: + assert (time.time() - t0 < 3600), "Polling timeout" # 1 hour timeout + time.sleep(0 if result is None else 2) + result, _, _ = _send_signed_request(url, None, err_msg) + return result + + # parse account key to get public key + log.info("Parsing account key...") + out = _cmd(["openssl", "rsa", "-in", account_key, "-noout", "-text"], err_msg="OpenSSL Error") + pub_pattern = r"modulus:[\s]+?00:([a-f0-9\:\s]+?)\npublicExponent: ([0-9]+)" + pub_hex, pub_exp = re.search(pub_pattern, out.decode('utf8'), re.MULTILINE|re.DOTALL).groups() + pub_exp = "{0:x}".format(int(pub_exp)) + pub_exp = "0{0}".format(pub_exp) if len(pub_exp) % 2 else pub_exp + alg, jwk = "RS256", { + "e": _b64(binascii.unhexlify(pub_exp.encode("utf-8"))), + "kty": "RSA", + "n": _b64(binascii.unhexlify(re.sub(r"(\s|:)", "", pub_hex).encode("utf-8"))), + } + accountkey_json = json.dumps(jwk, sort_keys=True, separators=(',', ':')) + thumbprint = _b64(hashlib.sha256(accountkey_json.encode('utf8')).digest()) + + # get the ACME directory of urls + log.info("Getting directory...") + directory, _, _ = _do_request(directory_url, err_msg="Error getting directory") + log.info("Directory found!") + + # create account and get the global key identifier + log.info("Registering account...") + reg_payload = {"termsOfServiceAgreed": True} if contact is None else {"termsOfServiceAgreed": True, "contact": contact} + account, code, acct_headers = _send_signed_request(directory['newAccount'], reg_payload, "Error registering") + log.info("Registered!" if code == 201 else "Already registered!") + + return acct_headers['Location'] + +def main(argv=None): + parser = argparse.ArgumentParser( + formatter_class=argparse.RawDescriptionHelpFormatter, + description=textwrap.dedent("""\ + Generate a CAA record for Mailcow. + + Example Usage: python mailcow_gencaa.py --account-key data/assets/ssl/acme/account.pem + """) + ) + parser.add_argument("--account-key", required=True, help="path to your Let's Encrypt account private key") + parser.add_argument("--quiet", action="store_const", const=logging.ERROR, help="suppress output except for errors") + parser.add_argument("--directory-url", default=DEFAULT_DIRECTORY_URL, help="certificate authority directory url, default is Let's Encrypt") + parser.add_argument("--contact", metavar="CONTACT", default=None, nargs="*", help="Contact details (e.g. mailto:aaa@bbb.com) for your account-key") + + args = parser.parse_args(argv) + LOGGER.setLevel(args.quiet or LOGGER.level) + id = get_id(args.account_key, log=LOGGER, directory_url=args.directory_url, contact=args.contact) + print("Use this as your CAA record:") + print('issue 128 "letsencrypt.org;accounturi={}"'.format(id)) + +if __name__ == "__main__": # pragma: no cover + main(sys.argv[1:]) From 473713219f612243e2f6f4180462fe0aee2b2d14 Mon Sep 17 00:00:00 2001 From: yvan-algoo <138122659+yvan-algoo@users.noreply.github.com> Date: Wed, 25 Oct 2023 18:38:01 +0200 Subject: [PATCH 125/174] Update lang.fr-fr.json (#5492) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix typos - Replace "..." by "…" --- data/web/lang/lang.fr-fr.json | 24 ++++++++++++------------ 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index ca67b592d..6c93f4ddb 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -89,7 +89,7 @@ "relay_transport_info": "
    Info
    Vous pouvez définir des cartes de transport vers une destination personnalisée pour ce domaine. sinon, une recherche MX sera effectuée.", "relay_unknown_only": "Relayer uniquement les boîtes inexistantes. Les boîtes existantes seront livrées localement.", "relayhost_wrapped_tls_info": "Veuillez ne pas utiliser des ports TLS wrappés (généralement utilisés sur le port 465).
    \r\nUtilisez n'importe quel port non encapsulé et lancez STARTTLS. Une politique TLS pour appliquer TLS peut être créée dans \"Cartes de politique TLS\".", - "select": "Veuillez sélectionner...", + "select": "Veuillez sélectionner…", "select_domain": "Sélectionner d'abord un domaine", "sieve_desc": "Description courte", "sieve_type": "Type de filtre", @@ -207,7 +207,7 @@ "last_applied": "Dernière application", "license_info": "Une licence n’est pas requise, mais contribue au développement.
    Enregistrer votre GUID ici or acheter le support pour votre intallation Mailcow.", "link": "Lien", - "loading": "Veuillez patienter...", + "loading": "Veuillez patienter…", "logo_info": "Votre image sera redimensionnée à une hauteur de 40 pixels pour la barre de navigation du haut et à un maximum de 250 pixels en largeur pour la page d'accueil. Un graphique extensible est fortement recommandé.", "lookup_mx": "Faire correspondre la destination à MX (.outlook.com pour acheminer tous les messages ciblés vers un MX * .outlook.com sur ce tronçon)", "main_name": "\"mailcow UI\" nom", @@ -598,9 +598,9 @@ "delete_these_items": "Veuillez confirmer les modifications apportées à l’identifiant d’objet suivant", "hibp_nok": "Trouvé ! Il s’agit d’un mot de passe potentiellement dangereux !", "hibp_ok": "Aucune correspondance trouvée.", - "loading": "Veuillez patienter...", + "loading": "Veuillez patienter…", "restart_container": "Redémarrer le conteneur", - "restart_container_info": "Important: Un redémarrage en douceur peut prendre un certain temps, veuillez attendre qu’il soit terminé..", + "restart_container_info": "Important: Un redémarrage en douceur peut prendre un certain temps, veuillez attendre qu’il soit terminé.", "restart_now": "Redémarrer maintenant", "restarting_container": "Redémarrage du conteneur, cela peut prendre un certain temps" }, @@ -935,7 +935,7 @@ "disable_tfa": "Désactiver TFA jusqu’à la prochaine ouverture de session réussie", "enter_qr_code": "Votre code TOTP si votre appareil ne peut pas scanner les codes QR", "error_code": "Code d'erreur", - "init_webauthn": "Initialisation, veuillez patienter...", + "init_webauthn": "Initialisation, veuillez patienter…", "key_id": "Un identifiant pour votre Périphérique", "key_id_totp": "Un identifiant pour votre clé", "none": "Désactiver", @@ -948,8 +948,8 @@ "tfa_token_invalid": "Token TFA invalide", "totp": "OTP (One Time Password = Mot de passe à usage unique : Google Authenticator, Authy, etc.)", "webauthn": "Authentification WebAuthn", - "waiting_usb_auth": "En attente d’un périphérique USB...

    S’il vous plaît appuyez maintenant sur le bouton de votre périphérique USB WebAuthn.", - "waiting_usb_register": "En attente d’un périphérique USB...

    Veuillez entrer votre mot de passe ci-dessus et confirmer votre inscription WebAuthn en appuyant sur le bouton de votre périphérique USB WebAuthn.", + "waiting_usb_auth": "En attente d’un périphérique USB…

    S’il vous plaît appuyez maintenant sur le bouton de votre périphérique USB WebAuthn.", + "waiting_usb_register": "En attente d’un périphérique USB…

    Veuillez entrer votre mot de passe ci-dessus et confirmer votre inscription WebAuthn en appuyant sur le bouton de votre périphérique USB WebAuthn.", "yubi_otp": "Authentification OTP Yubico" }, "fido2": { @@ -999,9 +999,9 @@ "eas_reset": "Réinitialiser le cache de l’appareil Activesync", "eas_reset_help": "Dans de nombreux cas, une réinitialisation du cache de l’appareil aidera à récupérer un profil Activesync cassé.
    Attention : Tous les éléments seront à nouveau téléchargés !", "eas_reset_now": "Réinitialiser maintenant", - "edit": "Editer", - "email": "Email", - "email_and_dav": "Email, calendriers et contacts", + "edit": "Éditer", + "email": "E-mail", + "email_and_dav": "E-mail, calendriers et contacts", "encryption": "Cryptage", "excludes": "Exclut", "expire_in": "Expire dans", @@ -1015,7 +1015,7 @@ "is_catch_all": "Attrape-tout pour le domaine(s)", "last_mail_login": "Dernière connexion mail", "last_run": "Dernière exécution", - "loading": "Chargement...", + "loading": "Chargement…", "mailbox_details": "Détails de la boîte", "messages": "messages", "never": "jamais", @@ -1051,7 +1051,7 @@ "shared_aliases": "Adresses alias partagées", "shared_aliases_desc": "Les alias partagés ne sont pas affectés par les paramètres spécifiques à l’utilisateur tels que le filtre anti-spam ou la politique de chiffrement. Les filtres anti-spam correspondants ne peuvent être effectués que par un administrateur en tant que politique de domaine.", "show_sieve_filters": "Afficher le filtre de tamis actif de l’utilisateur", - "sogo_profile_reset": "Remise é zéro du profil SOGo", + "sogo_profile_reset": "Remise à zéro du profil SOGo", "sogo_profile_reset_help": "Ceci détruira un profil Sogo des utilisateurs et supprimera toutes les données de contact et de calendrier irrécupérables.", "sogo_profile_reset_now": "Remise à zéro du profil maintenant", "spam_aliases": "Alias de courriel temporaire", From f60c4f39ee8f909e6d13e3cffc99ca6e2327207b Mon Sep 17 00:00:00 2001 From: milkmaker Date: Wed, 25 Oct 2023 19:46:19 +0200 Subject: [PATCH 126/174] [Web] Updated lang.si-si.json (#5494) Co-authored-by: gomiunik --- data/web/lang/lang.si-si.json | 132 +++++++++++++++++++++++++++++++++- 1 file changed, 130 insertions(+), 2 deletions(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 7c3ddbfdc..cf653e752 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -342,7 +342,12 @@ "username": "Uporabniško ime", "validate_license_now": "Potrdi GUID z licenčnim strežnikom", "verify": "Preveri", - "yes": "✓" + "yes": "✓", + "logo_normal_label": "Navadno", + "logo_dark_label": "Za temni način", + "cors_settings": "Nastavitve CORS", + "allowed_methods": "Dovoljene metode za upravljanje dostopa", + "allowed_origins": "Upravljanje-dostopa-Dovoljeni-Viri" }, "danger": { "alias_goto_identical": "Alias in goto naslov morata biti identična", @@ -391,6 +396,129 @@ "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": "Neveljaven mime type", + "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č", + "release_send_failed": "Sporočila ni bilo mogoče sprostiti: %s", + "tls_policy_map_dest_invalid": "Cilj politike ni veljaven", + "webauthn_authenticator_failed": "Izbrani avtentikator ni bil najden", + "reset_f2b_regex": "Regex filter ni bilo možno ponastaviti v ustreznem času. Prosim poskusite ponovno ali počakajte nekaj sekund in ponovno naložite stran.", + "target_domain_invalid": "Ciljna domena %s ni veljavna", + "validity_missing": "Prosim nastavite obdobje veljavnosti", + "invalid_recipient_map_old": "Naveden neveljaven izvirni prejemnik: %s", + "ip_list_empty": "Seznam dovoljenih IPjev ne sme biti prazen", + "is_alias": "%s je že znan kot alias naslov", + "is_alias_or_mailbox": "%s je že znan kot alias, poštni naslov, ali alias izveden iz alias domene", + "is_spam_alias": "%s že obstaja kot začasen alias (spam alias naslov)", + "last_key": "Zadnji ključ ne more biti izbrisan, prosim raje deaktivirajte dvofaktorsko avtentikacijo (TFA)", + "login_failed": "Prijava ni uspela", + "mailbox_defquota_exceeds_mailbox_maxquota": "Privzeta kvota presega najvišjo omejitev", + "mailbox_invalid": "Ime poštnega predala ni veljavno", + "mailbox_quota_exceeded": "Kvota presega omejitev domene (maksimalno %d MB)", + "mailbox_quota_exceeds_domain_quota": "Najvišja kvota presega omejitev domene", + "mailbox_quota_left_exceeded": "Ni dovolj prostora (preostali prostor: %d MB)", + "mailboxes_in_use": "Največje število poštnih predalov mora biti večje ali enako %d", + "malformed_username": "Nepravilno oblikovano uporabniško ime", + "map_content_empty": "Preslikava vsebine ne more biti prazna", + "max_alias_exceeded": "Preseženo največje število aliasov", + "max_mailbox_exceeded": "Preseženo največje število poštnih predalov (%d od %d)", + "maxquota_empty": "Največja kvota na poštni predal ne more biti 0", + "mysql_error": "Napaka MySQL: %s", + "network_host_invalid": "Nepravilno omrežje ali gostitel: %s", + "next_hop_interferes": "% moti naslednji skok %s", + "next_hop_interferes_any": "Obstoječi naslednji skok moti %s", + "nginx_reload_failed": "Ponovni zagon Nginx ni uspel: %s", + "no_user_defined": "Uporabnik ni določen", + "object_exists": "Objekt %s že obstaja", + "object_is_not_numeric": "Vrednost %s ni numerična", + "password_empty": "Geslo ne sme biti prazno", + "password_mismatch": "Potrditev gesla se ne ujema z geslom", + "policy_list_from_exists": "Zapis z tem imenom že obstaja", + "policy_list_from_invalid": "Zapis ima nepravilno obliko", + "private_key_error": "Napaka zasebnega ključa: %s", + "pushover_key": "Pushover ključ ni v pravilni obliki", + "pushover_token": "Pushover token ni v pravilni obliki", + "quota_not_0_not_numeric": "Quota mora biti število in večje ali enako 0", + "recipient_map_entry_exists": "Preslikava prejemnika \"%s\" že obstaja", + "redis_error": "Napaka Redis: %s", + "relayhost_invalid": "Vnos preslikave %s ni pravilen", + "resource_invalid": "Ime vira je neveljavno", + "rl_timeframe": "Časovni okvir za rate limit je nepravilen", + "rspamd_ui_pw_length": "Rspamd UI geslo mora biti dolgo vsaj 6 znakov", + "script_empty": "Script ne more biti prazen", + "sender_acl_invalid": "Vrednost ACL pošiljatelja %s ni veljavna", + "set_acl_failed": "Ni uspelo nastaviti ACL", + "settings_map_invalid": "ID preslikave nastavitev %s ni veljaven", + "sieve_error": "Napaka Sieve parserja: %s", + "spam_learn_error": "Napaka pri učenju spama: %s", + "subject_empty": "Predmet ne sme biti prazno", + "targetd_not_found": "Ciljna domena %s ni bila najdena", + "targetd_relay_domain": "Ciljna domena %s je relay domena", + "template_exists": "Predloga %s že obstaja", + "template_id_invalid": "ID predloge %s ni veljaven", + "template_name_invalid": "Ime predloge ni veljavno", + "text_empty": "Besedilo ne sme biti prazno", + "tfa_token_invalid": "Neveljaven token TFA", + "tls_policy_map_entry_exists": "Vpis preslikave TLS \"%s\" že obstaja", + "tls_policy_map_parameter_invalid": "Parameter politike ni pravilen", + "totp_verification_failed": "Neuspešno preverjanje TOTP", + "transport_dest_exists": "Cilj transporta \"%s\" že obstaja", + "webauthn_verification_failed": "Preverjanje WebAuthn ni uspelo: %s", + "webauthn_publickey_failed": "Na izbranem avtentikatorju ni shranjenega javnega ključa", + "webauthn_username_failed": "Izbrani avtentikator pripada drugemu uporabniškemu računu", + "unknown": "Pojavila se je neznana napaka", + "unknown_tfa_method": "Neznana metoda TFA", + "unlimited_quota_acl": "Neomejena kvota je prepovedana z ACL", + "username_invalid": "Uporabniško ime %s ne more biti uporabljeno", + "value_missing": "Prosim vnesite vse vrednosti", + "yotp_verification_failed": "Preverjanje Yubico OTP ni uspelo: %s", + "temp_error": "Začasna napaka", + "cors_invalid_method": "Navedena neveljavna Allow metoda", + "cors_invalid_origin": "Naveden neveljaven Allow-Origin", + "invalid_recipient_map_new": "Naveden neveljaven nov prejemnik: %s" + }, + "debug": { + "containers_info": "Informacije o vsebniku (containerju)", + "architecture": "Arhitektura", + "chart_this_server": "Diagram (ta strežnik)", + "container_running": "Aktiven", + "container_disabled": "Ustavljen ali onemogočen", + "container_stopped": "Ustavljen", + "cores": "Jedra", + "current_time": "Sistemski čas", + "disk_usage": "Zasedenost diska", + "docs": "Dokumenti", + "error_show_ip": "Ni mogoče preveriti javnega IP naslova", + "external_logs": "Zunanji dnevniki", + "last_modified": "Nazadnje spremenjeno", + "history_all_servers": "Zgodovina (vsi strežniki)", + "in_memory_logs": "In-memory dnevniki", + "jvm_memory_solr": "JVM zasedenost spomina" + }, + "datatables": { + "infoFiltered": "(filtrirano od _MAX_ skupaj zapisov)", + "collapse_all": "Strni vse", + "decimal": ",", + "emptyTable": "Ni podatkov", + "expand_all": "Razširi vse", + "info": "Prikazano _START_ do _END_ od _TOTAL_ zapisov", + "infoEmpty": "Prikazano 0 do 0 od 0 zapisov", + "thousands": ".", + "lengthMenu": "Prikaži _MENU_ zapise", + "loadingRecords": "Nalaganje...", + "processing": "Prosim počakajte...", + "search": "Iskanje:", + "zeroRecords": "Ni ujemajočih zapisov", + "paginate": { + "first": "Prva", + "last": "Zadnja", + "previous": "Prejšnja", + "next": "Naslednja" + }, + "aria": { + "sortAscending": ": aktivirajte za razvrstitev stolpca naraščajoče", + "sortDescending": ": aktivirajte za razvrstitev stolpca padajoče" + } } } From 7079000ee06469ef3c75e374b21b43ddd6b2621f Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 27 Oct 2023 22:56:51 +0200 Subject: [PATCH 127/174] Update nextcloud.conf when updating nextcloud --- helper-scripts/nextcloud.sh | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 730e61244..5c703837a 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -106,6 +106,10 @@ elif [[ ${NC_UPDATE} == "y" ]]; then exit 1 else docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar" + NC_SUBD=$(docker exec -i -u www-data $(docker ps -f name=php-fpm-mailcow -q) /web/nextcloud/occ config:system:get overwritehost) + mv ./data/conf/nginx/nextcloud.conf ./data/conf/nginx/nextcloud.conf-$(date +%s).bak + cp ./data/assets/nextcloud/nextcloud.conf ./data/conf/nginx/ + sed -i "s/NC_SUBD/${NC_SUBD}/g" ./data/conf/nginx/nextcloud.conf fi elif [[ ${NC_INSTALL} == "y" ]]; then From cfa47eb873d4fbb0b51e378f027c7af7a1390389 Mon Sep 17 00:00:00 2001 From: Peter Date: Fri, 27 Oct 2023 22:59:46 +0200 Subject: [PATCH 128/174] Update nextcloud.conf --- data/assets/nextcloud/nextcloud.conf | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/data/assets/nextcloud/nextcloud.conf b/data/assets/nextcloud/nextcloud.conf index eda2c7799..81567d39a 100644 --- a/data/assets/nextcloud/nextcloud.conf +++ b/data/assets/nextcloud/nextcloud.conf @@ -86,7 +86,7 @@ server { deny all; } - location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|oc[ms]-provider\/.+)\.php(?:$|\/) { + location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+)\.php(?:$|\/) { fastcgi_split_path_info ^(.+?\.php)(\/.*|)$; set $path_info $fastcgi_path_info; try_files $fastcgi_script_name =404; @@ -105,7 +105,7 @@ server { fastcgi_read_timeout 1200; } - location ~ ^\/(?:updater|oc[ms]-provider)(?:$|\/) { + location ~ ^\/(?:updater|ocs-provider)(?:$|\/) { try_files $uri/ =404; index index.php; } From 687fe044b21b8e63be92d389a7135f123151eef3 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 28 Oct 2023 15:10:30 +0200 Subject: [PATCH 129/174] [Web] Updated lang.si-si.json (#5499) Co-authored-by: gomiunik --- data/web/lang/lang.si-si.json | 34 +++++++++++++++++++++++++++++++++- 1 file changed, 33 insertions(+), 1 deletion(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index cf653e752..cf1cf799c 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -494,7 +494,24 @@ "last_modified": "Nazadnje spremenjeno", "history_all_servers": "Zgodovina (vsi strežniki)", "in_memory_logs": "In-memory dnevniki", - "jvm_memory_solr": "JVM zasedenost spomina" + "jvm_memory_solr": "JVM zasedenost spomina", + "service": "Servis", + "show_ip": "Prikaži javni IP", + "size": "Velikost", + "solr_dead": "Solr se zaganja, je onemogočen ali se je ustavil.", + "solr_status": "Status Solr", + "started_at": "Zagnano ob", + "started_on": "Zagnano na", + "static_logs": "Statični dnevniki", + "success": "Uspešno", + "system_containers": "Sistem in Containerji", + "timezone": "Časovni pas", + "uptime": "Čas delovanja", + "update_available": "Posodobitev je na voljo", + "no_update_available": "Sistem je na najnovejši verziji", + "update_failed": "Ni mogoče preveriti za posodobitve", + "username": "Uporabniško ime", + "wip": "Trenutno v delu" }, "datatables": { "infoFiltered": "(filtrirano od _MAX_ skupaj zapisov)", @@ -520,5 +537,20 @@ "sortAscending": ": aktivirajte za razvrstitev stolpca naraščajoče", "sortDescending": ": aktivirajte za razvrstitev stolpca padajoče" } + }, + "diagnostics": { + "cname_from_a": "Vrednost pridobljena iz A/AAAA zapisa. To je podprto, če zapis kaže na pravilen resurs.", + "dns_records": "DNS zapisi", + "dns_records_24hours": "Prosim upoštevajte, da lahko traja do 24 ur da se spremembe v DNS pravilno prikažejo na tej strani. Namen je da lahko enostavno vidite, kako konfigurirati svoje DNS zapise in preverite ali so vaši zapisi pravilno shranjeni v DNS.", + "dns_records_data": "Pravilni podatki", + "dns_records_docs": "Prosim preverite tudi dokumentacijo.", + "dns_records_name": "Ime", + "dns_records_status": "Trenutno stanje", + "dns_records_type": "Vrsta", + "optional": "Ta zapis je opcijski." + }, + "edit": { + "acl": "ACL (Dovoljenje)", + "active": "Aktivno" } } From 015f9b663f5794db471ba0b2f85af4016d13eb15 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Sat, 28 Oct 2023 14:40:08 +0000 Subject: [PATCH 130/174] Update dependency nextcloud/server to v27.1.3 Signed-off-by: milkmaker --- helper-scripts/nextcloud.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/nextcloud.sh b/helper-scripts/nextcloud.sh index 730e61244..afb702fdd 100755 --- a/helper-scripts/nextcloud.sh +++ b/helper-scripts/nextcloud.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash # renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?.*)$ -NEXTCLOUD_VERSION=27.1.2 +NEXTCLOUD_VERSION=27.1.3 echo -ne "Checking prerequisites..." sleep 1 From b568a335813c6005b2094ac567907bdcc8adefbe Mon Sep 17 00:00:00 2001 From: Kristian Feldsam Date: Mon, 30 Oct 2023 10:09:22 +0100 Subject: [PATCH 131/174] [web] sk and cz translations (#5502) Signed-off-by: Kristian Feldsam --- data/web/lang/lang.cs-cz.json | 18 ++++++++++++++++++ data/web/lang/lang.sk-sk.json | 18 ++++++++++++++++++ 2 files changed, 36 insertions(+) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index 76b7f2311..d14bab1d5 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -147,6 +147,8 @@ "ays": "Opravdu chcete pokračovat?", "ban_list_info": "Seznam blokovaných IP adres je zobrazen níže: síť (zbývající čas blokování) - [akce].
    IP adresy zařazené pro odblokování budou z aktivního seznamu odebrány během několika sekund.
    Červeně označené položky jsou pernamentní bloky z blacklistu.", "change_logo": "Změnit logo", + "logo_normal_label": "Normální", + "logo_dark_label": "Inverzní pro tmavý režim", "configuration": "Nastavení", "convert_html_to_text": "Převést HTML do prostého textu", "credentials_transport_warning": "Upozornění: Přidání položky do transportní mapy aktualizuje také přihlašovací údaje všech záznamů s odpovídajícím skokem.", @@ -206,6 +208,9 @@ "include_exclude": "Zahrnout/Vyloučit", "include_exclude_info": "Ve výchozím nastavení (bez výběru), jsou adresovány všechny mailové schránky", "includes": "Zahrnout tyto přijemce", + "ip_check": "Kontrola IP", + "ip_check_disabled": "Kontrola IP je zakázána. Můžete ji povolit v nabídce
    Systém > Nastavení > Možnosti > Přizpůsobení.", + "ip_check_opt_in": "Přihlásit se k používání služby třetí strany ipv4.mailcow.email a ipv6.mailcow.email pro zjištění externích IP adres.", "is_mx_based": "Na základě MX", "last_applied": "Naposledy použité", "license_info": "Licence není povinná, pomůžete však dalšímu vývoji.
    Registrujte si své GUID, nebo si zaplaťte podporu pro svou instalaci mailcow.", @@ -232,6 +237,7 @@ "oauth2_renew_secret": "Vytvořit nový tajný klíč", "oauth2_revoke_tokens": "Odvolat všechny klientské tokeny", "optional": "volitelné", + "options": "Možnosti", "password": "Heslo", "password_length": "Délka hesla", "password_policy": "Politika hesel", @@ -443,6 +449,9 @@ "target_domain_invalid": "Cílová doména %s je neplatná", "targetd_not_found": "Cílová doména %s nenalezena", "targetd_relay_domain": "Cílová doména %s je předávaná", + "template_exists": "Šablona %s již existuje", + "template_id_invalid": "Šablona ID %s je neplatná", + "template_name_invalid": "Název šablony je neplatný", "temp_error": "Dočasná chyba", "text_empty": "Text nesmí být prázdný", "tfa_token_invalid": "Neplatný TFA token", @@ -670,6 +679,7 @@ "apps": "Aplikace", "debug": "Systémové informace", "email": "E-Mail", + "mailcow_system": "Systém", "mailcow_config": "Nastavení", "quarantine": "Karanténa", "restart_netfilter": "Restartovat netfilter", @@ -705,6 +715,7 @@ "add_mailbox": "Přidat mailovou schránku", "add_recipient_map_entry": "Přidat mapu příjemce", "add_resource": "Přidat zdroj", + "add_template": "Přidat šablonu", "add_tls_policy_map": "Přidat mapu TLS pravidel", "address_rewriting": "Přepisování adres", "alias": "Alias", @@ -747,6 +758,7 @@ "domain": "Doména", "domain_admins": "Správci domén", "domain_aliases": "Doménové aliasy", + "domain_templates": "Šablony domén", "domain_quota": "Kvóta", "domain_quota_total": "Celková kvóta domény", "domains": "Domény", @@ -775,6 +787,7 @@ "mailbox_defaults": "Výchozí nastavení", "mailbox_defaults_info": "Definuje výchozí nastavení pro nové schránky", "mailbox_defquota": "Výchozí velikost schránky", + "mailbox_templates": "Šablony schránek", "mailbox_quota": "Max. velikost schránky", "mailboxes": "Mailové schránky", "max_aliases": "Max. počet aliasů", @@ -842,6 +855,8 @@ "table_size_show_n": "Zobrazit %s položek", "target_address": "Cílová adresa", "target_domain": "Cílová doména", + "templates": "Šablony", + "template": "Šablona", "tls_enforce_in": "Vynutit TLS pro příchozí", "tls_enforce_out": "Vynutit TLS pro odchozí", "tls_map_dest": "Cíl", @@ -1006,6 +1021,9 @@ "settings_map_added": "Přidána položka mapování nastavení", "settings_map_removed": "Položka mapování nastavení: %s smazána", "sogo_profile_reset": "SOGo profil uživatele %s vyresetován", + "template_added": "Přidána šablona %s", + "template_modified": "Změny šablony %s byly uloženy", + "template_removed": "Šablona ID %s byla odstraněna", "tls_policy_map_entry_deleted": "Položka mapy TLS pravidel ID %s smazána", "tls_policy_map_entry_saved": "Položka mapy TLS pravidel \"%s\" uložena", "ui_texts": "Změny UI textů uloženy", diff --git a/data/web/lang/lang.sk-sk.json b/data/web/lang/lang.sk-sk.json index 13e239b75..794902613 100644 --- a/data/web/lang/lang.sk-sk.json +++ b/data/web/lang/lang.sk-sk.json @@ -147,6 +147,8 @@ "ays": "Naozaj chcete pokračovať?", "ban_list_info": "Zoznam zakázaných IP je zobrazený nižšie: sieť (zostávajúci čas zákazu) - [akcia].
    IP adresy zaradené na unban budú odstránené z aktívneho zoznamu v priebehu niekoľkých sekúnd.
    Červené položky zobrazujú permanentné blokovanie.", "change_logo": "Zmeniť logo", + "logo_normal_label": "Normálne", + "logo_dark_label": "Inverzné pre tmavý režim", "configuration": "Konfigurácia", "convert_html_to_text": "Konvertovať HTML do obyčajného textu", "credentials_transport_warning": "Upozornenie: Pridaním ďalšieho záznamu do transportnej mapy bude mať za následok aktualizovanie údajov pre všetky záznamy so zhodným ďalším skokom.", @@ -206,6 +208,9 @@ "include_exclude": "Zahrnúť/Vylúčiť", "include_exclude_info": "Ak nič nevyberiete tak bude adresované všetkým schránkam", "includes": "Zahrnúť týchto príjemcov", + "ip_check": "Kontrola IP", + "ip_check_disabled": "Kontrola IP je vypnutá. Môžete ju zapnúť v ponuke
    Systém > Konfigurácia > Možnosti > Prispôsobiť", + "ip_check_opt_in": "Prihlásiť sa k používaniu služby tretej strany ipv4.mailcow.email a ipv6.mailcow.email za účelom zistenia externých IP adries.", "is_mx_based": "Na základe MX", "last_applied": "Naposledy aplikované", "license_info": "Licencia nie je potrebná, ale napomáha ďalšiemu vývoju.
    Registrujte váš GUID tu alebo zakúpte si podporu pre vašu mailcow inštaláciu.", @@ -232,6 +237,7 @@ "oauth2_renew_secret": "Vygenerovať nový tajný kľuč", "oauth2_revoke_tokens": "Odobrať všetky tokeny klienta", "optional": "voliteľné", + "options": "Možnosti", "password": "Heslo", "password_length": "Dĺžka hesla", "password_policy": "Politika hesiel", @@ -439,6 +445,9 @@ "target_domain_invalid": "Cieľová doména %s je neplatná", "targetd_not_found": "Cieľová doména %s sa nenašla", "targetd_relay_domain": "Cieľová doména %s je posielaná ďalej (relay)", + "template_exists": "Šablóna %s už existuje", + "template_id_invalid": "Šablóna ID %s je neplatná", + "template_name_invalid": "Názov šablóny je neplatný", "temp_error": "Dočasná chyba", "text_empty": "Text nemôže byť prázdny", "tfa_token_invalid": "Neplatný TFA token", @@ -667,6 +676,7 @@ "apps": "Aplikácie", "debug": "Systémové informácie", "email": "E-Mail", + "mailcow_system": "Systém", "mailcow_config": "Konfigurácia", "quarantine": "Karanténa", "restart_netfilter": "Reštartovať netfilter", @@ -702,6 +712,7 @@ "add_mailbox": "Pridať mailovú schránku", "add_recipient_map_entry": "Pridať mapu príjemcu", "add_resource": "Pridať zdroj", + "add_template": "Pridať šablónu", "add_tls_policy_map": "Pridať TLS mapu pravidiel", "address_rewriting": "Prepisovanie adries", "alias": "Alias", @@ -744,6 +755,7 @@ "domain": "Doména", "domain_admins": "Administrátori domény", "domain_aliases": "Alias domény", + "domain_templates": "Šablóny domén", "domain_quota": "Kvóta", "domain_quota_total": "Celkové kvóta domény", "domains": "Domény", @@ -772,6 +784,7 @@ "mailbox_defaults": "Predvolené nastavenia", "mailbox_defaults_info": "Definuje predvolené nastavenia pre nové schránky.", "mailbox_defquota": "Predvolená veľkosť schránky", + "mailbox_templates": "Šablóny schránok", "mailbox_quota": "Max. veľkosť schránky", "mailboxes": "Mailové schránky", "max_aliases": "Max. počet aliasov", @@ -839,6 +852,8 @@ "table_size_show_n": "Zobraziť %s položiek", "target_address": "Cieľová adresa", "target_domain": "Cieľová doména", + "templates": "Šablóny", + "template": "Šablóna", "tls_enforce_in": "Vynútiť TLS pre prichádzajúcu poštu", "tls_enforce_out": "Vynútiť TLS pre odchádzajúcu poštu", "tls_map_dest": "Cieľ", @@ -1003,6 +1018,9 @@ "settings_map_added": "Pridaná mapa nastavení", "settings_map_removed": "Odstránená mapa nastavení ID %s", "sogo_profile_reset": "SOGo profil pre používateľa %s resetovaný", + "template_added": "Pridaná šablóna %s", + "template_modified": "Zmeny šablóny %s boli uložené", + "template_removed": "Šablóna ID %s bola odstránená", "tls_policy_map_entry_deleted": "Položka mapy TLS pravidiel %s vymazaná", "tls_policy_map_entry_saved": "Položka mapy TLS pravidiel \"%s\" uložená", "ui_texts": "Zmeny v UI textoch uložené", From f39005b72ddd41662855e9f83d2021e6a23bffa6 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 30 Oct 2023 11:54:14 +0100 Subject: [PATCH 132/174] [Netfilter] add nftables support --- data/Dockerfiles/netfilter/Dockerfile | 14 +- .../netfilter/docker-entrypoint.sh | 29 + data/Dockerfiles/netfilter/main.py | 459 ++++++++++++++++ .../Dockerfiles/netfilter/modules/IPTables.py | 213 ++++++++ data/Dockerfiles/netfilter/modules/Logger.py | 23 + .../Dockerfiles/netfilter/modules/NFTables.py | 495 ++++++++++++++++++ .../Dockerfiles/netfilter/modules/__init__.py | 0 docker-compose.yml | 2 +- 8 files changed, 1232 insertions(+), 3 deletions(-) create mode 100755 data/Dockerfiles/netfilter/docker-entrypoint.sh create mode 100644 data/Dockerfiles/netfilter/main.py create mode 100644 data/Dockerfiles/netfilter/modules/IPTables.py create mode 100644 data/Dockerfiles/netfilter/modules/Logger.py create mode 100644 data/Dockerfiles/netfilter/modules/NFTables.py create mode 100644 data/Dockerfiles/netfilter/modules/__init__.py diff --git a/data/Dockerfiles/netfilter/Dockerfile b/data/Dockerfiles/netfilter/Dockerfile index 4fcb5eef7..8f76ec639 100644 --- a/data/Dockerfiles/netfilter/Dockerfile +++ b/data/Dockerfiles/netfilter/Dockerfile @@ -1,6 +1,8 @@ FROM alpine:3.17 LABEL maintainer "The Infrastructure Company GmbH " +WORKDIR /app + ENV XTABLES_LIBDIR /usr/lib/xtables ENV PYTHON_IPTABLES_XTABLES_VERSION 12 ENV IPTABLES_LIBDIR /usr/lib @@ -14,10 +16,13 @@ RUN apk add --virtual .build-deps \ iptables \ ip6tables \ xtables-addons \ + nftables \ tzdata \ py3-pip \ + py3-nftables \ musl-dev \ && pip3 install --ignore-installed --upgrade pip \ + jsonschema \ python-iptables \ redis \ ipaddress \ @@ -26,5 +31,10 @@ RUN apk add --virtual .build-deps \ # && pip3 install --upgrade pip python-iptables==0.13.0 redis ipaddress dnspython \ -COPY server.py / -CMD ["python3", "-u", "/server.py"] +COPY modules /app/modules +COPY main.py /app/ +COPY ./docker-entrypoint.sh /app/ + +RUN chmod +x /app/docker-entrypoint.sh + +CMD ["/bin/sh", "-c", "/app/docker-entrypoint.sh"] \ No newline at end of file diff --git a/data/Dockerfiles/netfilter/docker-entrypoint.sh b/data/Dockerfiles/netfilter/docker-entrypoint.sh new file mode 100755 index 000000000..47370a1fe --- /dev/null +++ b/data/Dockerfiles/netfilter/docker-entrypoint.sh @@ -0,0 +1,29 @@ +#!/bin/sh + +backend=iptables + +nft list table ip filter &>/dev/null +nftables_found=$? + +iptables -L -n &>/dev/null +iptables_found=$? + +if [ $nftables_found -lt $iptables_found ]; then + backend=nftables +fi + +if [ $nftables_found -gt $iptables_found ]; then + backend=iptables +fi + +if [ $nftables_found -eq 0 ] && [ $nftables_found -eq $iptables_found ]; then + nftables_lines=$(nft list ruleset | wc -l) + iptables_lines=$(iptables-save | wc -l) + if [ $nftables_lines -gt $iptables_lines ]; then + backend=nftables + else + backend=iptables + fi +fi + +exec python -u /app/main.py $backend diff --git a/data/Dockerfiles/netfilter/main.py b/data/Dockerfiles/netfilter/main.py new file mode 100644 index 000000000..a6859c95f --- /dev/null +++ b/data/Dockerfiles/netfilter/main.py @@ -0,0 +1,459 @@ +#!/usr/bin/env python3 + +import re +import os +import sys +import time +import atexit +import signal +import ipaddress +from collections import Counter +from random import randint +from threading import Thread +from threading import Lock +import redis +import json +import dns.resolver +import dns.exception +from modules.Logger import Logger +from modules.IPTables import IPTables +from modules.NFTables import NFTables + + +# connect to redis +while True: + try: + redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '') + redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '') + if "".__eq__(redis_slaveof_ip): + r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0) + else: + r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0) + r.ping() + except Exception as ex: + print('%s - trying again in 3 seconds' % (ex)) + time.sleep(3) + else: + break +pubsub = r.pubsub() + +# rename fail2ban to netfilter +if r.exists('F2B_LOG'): + r.rename('F2B_LOG', 'NETFILTER_LOG') + + +# globals +WHITELIST = [] +BLACKLIST= [] +bans = {} +quit_now = False +exit_code = 0 +lock = Lock() + + +# init Logger +logger = Logger(r) +# init backend +backend = sys.argv[1] +if backend == "nftables": + logger.logInfo('Using NFTables backend') + tables = NFTables("MAILCOW", logger) +else: + logger.logInfo('Using IPTables backend') + tables = IPTables("MAILCOW", logger) + + +def refreshF2boptions(): + global f2boptions + global quit_now + global exit_code + + f2boptions = {} + + if not r.get('F2B_OPTIONS'): + f2boptions['ban_time'] = r.get('F2B_BAN_TIME') + f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME') + f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT') + f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') + f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') + f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') + f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') + else: + try: + f2boptions = json.loads(r.get('F2B_OPTIONS')) + except ValueError: + logger.logCrit('Error loading F2B options: F2B_OPTIONS is not json') + quit_now = True + exit_code = 2 + + verifyF2boptions(f2boptions) + r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False)) + +def verifyF2boptions(f2boptions): + verifyF2boption(f2boptions,'ban_time', 1800) + verifyF2boption(f2boptions,'max_ban_time', 10000) + verifyF2boption(f2boptions,'ban_time_increment', True) + verifyF2boption(f2boptions,'max_attempts', 10) + verifyF2boption(f2boptions,'retry_window', 600) + verifyF2boption(f2boptions,'netban_ipv4', 32) + verifyF2boption(f2boptions,'netban_ipv6', 128) + +def verifyF2boption(f2boptions, f2boption, f2bdefault): + f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault + +def refreshF2bregex(): + global f2bregex + global quit_now + global exit_code + if not r.get('F2B_REGEX'): + f2bregex = {} + f2bregex[1] = 'mailcow UI: Invalid password for .+ by ([0-9a-f\.:]+)' + f2bregex[2] = 'Rspamd UI: Invalid password by ([0-9a-f\.:]+)' + f2bregex[3] = 'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+' + f2bregex[4] = 'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+' + f2bregex[5] = 'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+' + f2bregex[6] = '-login: Disconnected.+ \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),' + f2bregex[7] = '-login: Aborted login.+ \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' + f2bregex[8] = '-login: Aborted login.+ \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' + f2bregex[9] = 'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked' + f2bregex[10] = '([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+' + r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False)) + else: + try: + f2bregex = {} + f2bregex = json.loads(r.get('F2B_REGEX')) + except ValueError: + logger.logCrit('Error loading F2B options: F2B_REGEX is not json') + quit_now = True + exit_code = 2 + +def get_ip(address): + ip = ipaddress.ip_address(address) + if type(ip) is ipaddress.IPv6Address and ip.ipv4_mapped: + ip = ip.ipv4_mapped + if ip.is_private or ip.is_loopback: + return False + + return ip + +def ban(address): + global lock + + refreshF2boptions() + BAN_TIME = int(f2boptions['ban_time']) + BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) + MAX_ATTEMPTS = int(f2boptions['max_attempts']) + RETRY_WINDOW = int(f2boptions['retry_window']) + NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4']) + NETBAN_IPV6 = '/' + str(f2boptions['netban_ipv6']) + + ip = get_ip(address) + if not ip: return + address = str(ip) + self_network = ipaddress.ip_network(address) + + with lock: + temp_whitelist = set(WHITELIST) + if temp_whitelist: + for wl_key in temp_whitelist: + wl_net = ipaddress.ip_network(wl_key, False) + if wl_net.overlaps(self_network): + logger.logInfo('Address %s is whitelisted by rule %s' % (self_network, wl_net)) + return + + net = ipaddress.ip_network((address + (NETBAN_IPV4 if type(ip) is ipaddress.IPv4Address else NETBAN_IPV6)), strict=False) + net = str(net) + + if not net in bans: + bans[net] = {'attempts': 0, 'last_attempt': 0, 'ban_counter': 0} + + bans[net]['attempts'] += 1 + bans[net]['last_attempt'] = time.time() + + if bans[net]['attempts'] >= MAX_ATTEMPTS: + cur_time = int(round(time.time())) + NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + logger.logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 )) + if type(ip) is ipaddress.IPv4Address: + with lock: + tables.banIPv4(net) + else: + with lock: + tables.banIPv6(net) + + r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + NET_BAN_TIME) + else: + logger.logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net)) + +def unban(net): + global lock + + if not net in bans: + logger.logInfo('%s is not banned, skipping unban and deleting from queue (if any)' % net) + r.hdel('F2B_QUEUE_UNBAN', '%s' % net) + return + + logger.logInfo('Unbanning %s' % net) + if type(ipaddress.ip_network(net)) is ipaddress.IPv4Network: + with lock: + tables.unbanIPv4(net) + else: + with lock: + tables.unbanIPv6(net) + + r.hdel('F2B_ACTIVE_BANS', '%s' % net) + r.hdel('F2B_QUEUE_UNBAN', '%s' % net) + if net in bans: + bans[net]['attempts'] = 0 + bans[net]['ban_counter'] += 1 + +def permBan(net, unban=False): + global lock + + is_unbanned = False + is_banned = False + if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network: + with lock: + if unban: + is_unbanned = tables.unbanIPv4(net) + else: + is_banned = tables.banIPv4(net) + else: + with lock: + if unban: + is_unbanned = tables.unbanIPv6(net) + else: + is_banned = tables.banIPv6(net) + + + if is_unbanned: + r.hdel('F2B_PERM_BANS', '%s' % net) + logger.logCrit('Removed host/network %s from blacklist' % net) + elif is_banned: + r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time()))) + logger.logCrit('Added host/network %s to blacklist' % net) + +def clear(): + global lock + logger.logInfo('Clearing all bans') + for net in bans.copy(): + unban(net) + with lock: + tables.clearIPv4Table() + tables.clearIPv6Table() + r.delete('F2B_ACTIVE_BANS') + r.delete('F2B_PERM_BANS') + pubsub.unsubscribe() + +def watch(): + logger.logInfo('Watching Redis channel F2B_CHANNEL') + pubsub.subscribe('F2B_CHANNEL') + + global quit_now + global exit_code + + while not quit_now: + try: + for item in pubsub.listen(): + refreshF2bregex() + for rule_id, rule_regex in f2bregex.items(): + if item['data'] and item['type'] == 'message': + try: + result = re.search(rule_regex, item['data']) + except re.error: + result = False + if result: + addr = result.group(1) + ip = ipaddress.ip_address(addr) + if ip.is_private or ip.is_loopback: + continue + logger.logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data'])) + ban(addr) + except Exception as ex: + logger.logWarn('Error reading log line from pubsub: %s' % ex) + quit_now = True + exit_code = 2 + +def snat4(snat_target): + global lock + global quit_now + + while not quit_now: + time.sleep(10) + with lock: + tables.snat4(snat_target, os.getenv('IPV4_NETWORK', '172.22.1') + '.0/24') + +def snat6(snat_target): + global lock + global quit_now + + while not quit_now: + time.sleep(10) + with lock: + tables.snat6(snat_target, os.getenv('IPV6_NETWORK', 'fd4d:6169:6c63:6f77::/64')) + +def autopurge(): + while not quit_now: + time.sleep(10) + refreshF2boptions() + BAN_TIME = int(f2boptions['ban_time']) + MAX_BAN_TIME = int(f2boptions['max_ban_time']) + BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment']) + MAX_ATTEMPTS = int(f2boptions['max_attempts']) + QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN') + if QUEUE_UNBAN: + for net in QUEUE_UNBAN: + unban(str(net)) + for net in bans.copy(): + if bans[net]['attempts'] >= MAX_ATTEMPTS: + NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter'] + TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt'] + if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME: + unban(net) + +def mailcowChainOrder(): + global lock + global quit_now + global exit_code + while not quit_now: + time.sleep(10) + with lock: + quit_now, exit_code = tables.checkIPv4ChainOrder() + if quit_now: return + quit_now, exit_code = tables.checkIPv6ChainOrder() + +def isIpNetwork(address): + try: + ipaddress.ip_network(address, False) + except ValueError: + return False + return True + +def genNetworkList(list): + resolver = dns.resolver.Resolver() + hostnames = [] + networks = [] + for key in list: + if isIpNetwork(key): + networks.append(key) + else: + hostnames.append(key) + for hostname in hostnames: + hostname_ips = [] + for rdtype in ['A', 'AAAA']: + try: + answer = resolver.resolve(qname=hostname, rdtype=rdtype, lifetime=3) + except dns.exception.Timeout: + logger.logInfo('Hostname %s timedout on resolve' % hostname) + break + except (dns.resolver.NXDOMAIN, dns.resolver.NoAnswer): + continue + except dns.exception.DNSException as dnsexception: + logger.logInfo('%s' % dnsexception) + continue + for rdata in answer: + hostname_ips.append(rdata.to_text()) + networks.extend(hostname_ips) + return set(networks) + +def whitelistUpdate(): + global lock + global quit_now + global WHITELIST + while not quit_now: + start_time = time.time() + list = r.hgetall('F2B_WHITELIST') + new_whitelist = [] + if list: + new_whitelist = genNetworkList(list) + with lock: + if Counter(new_whitelist) != Counter(WHITELIST): + WHITELIST = new_whitelist + logger.logInfo('Whitelist was changed, it has %s entries' % len(WHITELIST)) + time.sleep(60.0 - ((time.time() - start_time) % 60.0)) + +def blacklistUpdate(): + global quit_now + global BLACKLIST + while not quit_now: + start_time = time.time() + list = r.hgetall('F2B_BLACKLIST') + new_blacklist = [] + if list: + new_blacklist = genNetworkList(list) + if Counter(new_blacklist) != Counter(BLACKLIST): + addban = set(new_blacklist).difference(BLACKLIST) + delban = set(BLACKLIST).difference(new_blacklist) + BLACKLIST = new_blacklist + logger.logInfo('Blacklist was changed, it has %s entries' % len(BLACKLIST)) + if addban: + for net in addban: + permBan(net=net) + if delban: + for net in delban: + permBan(net=net, unban=True) + time.sleep(60.0 - ((time.time() - start_time) % 60.0)) + +def quit(signum, frame): + global quit_now + quit_now = True + + +if __name__ == '__main__': + # In case a previous session was killed without cleanup + clear() + # Reinit MAILCOW chain + # Is called before threads start, no locking + logger.logInfo("Initializing mailcow netfilter chain") + tables.initChainIPv4() + tables.initChainIPv6() + + watch_thread = Thread(target=watch) + watch_thread.daemon = True + watch_thread.start() + + if os.getenv('SNAT_TO_SOURCE') and os.getenv('SNAT_TO_SOURCE') != 'n': + try: + snat_ip = os.getenv('SNAT_TO_SOURCE') + snat_ipo = ipaddress.ip_address(snat_ip) + if type(snat_ipo) is ipaddress.IPv4Address: + snat4_thread = Thread(target=snat4,args=(snat_ip,)) + snat4_thread.daemon = True + snat4_thread.start() + except ValueError: + print(os.getenv('SNAT_TO_SOURCE') + ' is not a valid IPv4 address') + + if os.getenv('SNAT6_TO_SOURCE') and os.getenv('SNAT6_TO_SOURCE') != 'n': + try: + snat_ip = os.getenv('SNAT6_TO_SOURCE') + snat_ipo = ipaddress.ip_address(snat_ip) + if type(snat_ipo) is ipaddress.IPv6Address: + snat6_thread = Thread(target=snat6,args=(snat_ip,)) + snat6_thread.daemon = True + snat6_thread.start() + except ValueError: + print(os.getenv('SNAT6_TO_SOURCE') + ' is not a valid IPv6 address') + + autopurge_thread = Thread(target=autopurge) + autopurge_thread.daemon = True + autopurge_thread.start() + + mailcowchainwatch_thread = Thread(target=mailcowChainOrder) + mailcowchainwatch_thread.daemon = True + mailcowchainwatch_thread.start() + + blacklistupdate_thread = Thread(target=blacklistUpdate) + blacklistupdate_thread.daemon = True + blacklistupdate_thread.start() + + whitelistupdate_thread = Thread(target=whitelistUpdate) + whitelistupdate_thread.daemon = True + whitelistupdate_thread.start() + + signal.signal(signal.SIGTERM, quit) + atexit.register(clear) + + while not quit_now: + time.sleep(0.5) + + sys.exit(exit_code) diff --git a/data/Dockerfiles/netfilter/modules/IPTables.py b/data/Dockerfiles/netfilter/modules/IPTables.py new file mode 100644 index 000000000..c60ecc613 --- /dev/null +++ b/data/Dockerfiles/netfilter/modules/IPTables.py @@ -0,0 +1,213 @@ +import iptc +import time + +class IPTables: + def __init__(self, chain_name, logger): + self.chain_name = chain_name + self.logger = logger + + def initChainIPv4(self): + if not iptc.Chain(iptc.Table(iptc.Table.FILTER), self.chain_name) in iptc.Table(iptc.Table.FILTER).chains: + iptc.Table(iptc.Table.FILTER).create_chain(self.chain_name) + for c in ['FORWARD', 'INPUT']: + chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), c) + rule = iptc.Rule() + rule.src = '0.0.0.0/0' + rule.dst = '0.0.0.0/0' + target = iptc.Target(rule, self.chain_name) + rule.target = target + if rule not in chain.rules: + chain.insert_rule(rule) + + def initChainIPv6(self): + if not iptc.Chain(iptc.Table6(iptc.Table6.FILTER), self.chain_name) in iptc.Table6(iptc.Table6.FILTER).chains: + iptc.Table6(iptc.Table6.FILTER).create_chain(self.chain_name) + for c in ['FORWARD', 'INPUT']: + chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), c) + rule = iptc.Rule6() + rule.src = '::/0' + rule.dst = '::/0' + target = iptc.Target(rule, self.chain_name) + rule.target = target + if rule not in chain.rules: + chain.insert_rule(rule) + + def checkIPv4ChainOrder(self): + filter_table = iptc.Table(iptc.Table.FILTER) + filter_table.refresh() + return self.checkChainOrder(filter_table) + + def checkIPv6ChainOrder(self): + filter_table = iptc.Table6(iptc.Table6.FILTER) + filter_table.refresh() + return self.checkChainOrder(filter_table) + + def checkChainOrder(self, filter_table): + err = False + exit_code = None + + forward_chain = iptc.Chain(filter_table, 'FORWARD') + input_chain = iptc.Chain(filter_table, 'INPUT') + for chain in [forward_chain, input_chain]: + target_found = False + for position, item in enumerate(chain.rules): + if item.target.name == self.chain_name: + target_found = True + if position > 2: + self.logger.logCrit('Error in %s chain: %s target not found, restarting container' % (chain.name, self.chain_name)) + err = True + exit_code = 2 + if not target_found: + self.logger.logCrit('Error in %s chain: %s target not found, restarting container' % (chain.name, self.chain_name)) + err = True + exit_code = 2 + + return err, exit_code + + def clearIPv4Table(self): + self.clearTable(iptc.Table(iptc.Table.FILTER)) + + def clearIPv6Table(self): + self.clearTable(iptc.Table6(iptc.Table6.FILTER)) + + def clearTable(self, filter_table): + filter_table.autocommit = False + forward_chain = iptc.Chain(filter_table, "FORWARD") + input_chain = iptc.Chain(filter_table, "INPUT") + mailcow_chain = iptc.Chain(filter_table, self.chain_name) + if mailcow_chain in filter_table.chains: + for rule in mailcow_chain.rules: + mailcow_chain.delete_rule(rule) + for rule in forward_chain.rules: + if rule.target.name == self.chain_name: + forward_chain.delete_rule(rule) + for rule in input_chain.rules: + if rule.target.name == self.chain_name: + input_chain.delete_rule(rule) + filter_table.delete_chain(self.chain_name) + filter_table.commit() + filter_table.refresh() + filter_table.autocommit = True + + def banIPv4(self, source): + chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), self.chain_name) + rule = iptc.Rule() + rule.src = source + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule in chain.rules: + return False + chain.insert_rule(rule) + return True + + def banIPv6(self, source): + chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), self.chain_name) + rule = iptc.Rule6() + rule.src = source + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule in chain.rules: + return False + chain.insert_rule(rule) + return True + + def unbanIPv4(self, source): + chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), self.chain_name) + rule = iptc.Rule() + rule.src = source + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule not in chain.rules: + return False + chain.delete_rule(rule) + return True + + def unbanIPv6(self, source): + chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), self.chain_name) + rule = iptc.Rule6() + rule.src = source + target = iptc.Target(rule, "REJECT") + rule.target = target + if rule not in chain.rules: + return False + chain.delete_rule(rule) + return True + + def snat4(self, snat_target, source): + try: + table = iptc.Table('nat') + table.refresh() + chain = iptc.Chain(table, 'POSTROUTING') + table.autocommit = False + new_rule = self.getSnat4Rule(snat_target, source) + + if not chain.rules: + # if there are no rules in the chain, insert the new rule directly + self.logger.logInfo(f'Added POSTROUTING rule for source network {new_rule.src} to SNAT target {snat_target}') + chain.insert_rule(new_rule) + else: + for position, rule in enumerate(chain.rules): + if not hasattr(rule.target, 'parameter'): + continue + match = all(( + new_rule.get_src() == rule.get_src(), + new_rule.get_dst() == rule.get_dst(), + new_rule.target.parameters == rule.target.parameters, + new_rule.target.name == rule.target.name + )) + if position == 0: + if not match: + self.logger.logInfo(f'Added POSTROUTING rule for source network {new_rule.src} to SNAT target {snat_target}') + chain.insert_rule(new_rule) + else: + if match: + self.logger.logInfo(f'Remove rule for source network {new_rule.src} to SNAT target {snat_target} from POSTROUTING chain at position {position}') + chain.delete_rule(rule) + + table.commit() + table.autocommit = True + return True + except: + self.logger.logCrit('Error running SNAT4, retrying...') + return False + + def snat6(self, snat_target, source): + try: + table = iptc.Table6('nat') + table.refresh() + chain = iptc.Chain(table, 'POSTROUTING') + table.autocommit = False + new_rule = self.getSnat6Rule(snat_target, source) + + if new_rule not in chain.rules: + self.logger.logInfo('Added POSTROUTING rule for source network %s to SNAT target %s' % (new_rule.src, snat_target)) + chain.insert_rule(new_rule) + else: + for position, item in enumerate(chain.rules): + if item == new_rule: + if position != 0: + chain.delete_rule(new_rule) + + table.commit() + table.autocommit = True + except: + self.logger.logCrit('Error running SNAT6, retrying...') + + + def getSnat4Rule(self, snat_target, source): + rule = iptc.Rule() + rule.src = source + rule.dst = '!' + rule.src + target = rule.create_target("SNAT") + target.to_source = snat_target + match = rule.create_match("comment") + match.comment = f'{int(round(time.time()))}' + return rule + + def getSnat6Rule(self, snat_target, source): + rule = iptc.Rule6() + rule.src = source + rule.dst = '!' + rule.src + target = rule.create_target("SNAT") + target.to_source = snat_target + return rule diff --git a/data/Dockerfiles/netfilter/modules/Logger.py b/data/Dockerfiles/netfilter/modules/Logger.py new file mode 100644 index 000000000..d60d52fad --- /dev/null +++ b/data/Dockerfiles/netfilter/modules/Logger.py @@ -0,0 +1,23 @@ +import time +import json + +class Logger: + def __init__(self, redis): + self.r = redis + + def log(self, priority, message): + tolog = {} + tolog['time'] = int(round(time.time())) + tolog['priority'] = priority + tolog['message'] = message + self.r.lpush('NETFILTER_LOG', json.dumps(tolog, ensure_ascii=False)) + print(message) + + def logWarn(self, message): + self.log('warn', message) + + def logCrit(self, message): + self.log('crit', message) + + def logInfo(self, message): + self.log('info', message) diff --git a/data/Dockerfiles/netfilter/modules/NFTables.py b/data/Dockerfiles/netfilter/modules/NFTables.py new file mode 100644 index 000000000..d341dc36b --- /dev/null +++ b/data/Dockerfiles/netfilter/modules/NFTables.py @@ -0,0 +1,495 @@ +import nftables +import ipaddress + +class NFTables: + def __init__(self, chain_name, logger): + self.chain_name = chain_name + self.logger = logger + + self.nft = nftables.Nftables() + self.nft.set_json_output(True) + self.nft.set_handle_output(True) + self.nft_chain_names = {'ip': {'filter': {'input': '', 'forward': ''}, 'nat': {'postrouting': ''} }, + 'ip6': {'filter': {'input': '', 'forward': ''}, 'nat': {'postrouting': ''} } } + + self.search_current_chains() + + def initChainIPv4(self): + self.insert_mailcow_chains("ip") + + def initChainIPv6(self): + self.insert_mailcow_chains("ip6") + + def checkIPv4ChainOrder(self): + return self.checkChainOrder("ip") + + def checkIPv6ChainOrder(self): + return self.checkChainOrder("ip6") + + def checkChainOrder(self, filter_table): + err = False + exit_code = None + + for chain in ['input', 'forward']: + chain_position = self.check_mailcow_chains(filter_table, chain) + if chain_position is None: continue + + if chain_position is False: + self.logger.logCrit(f'MAILCOW target not found in {filter_table} {chain} table, restarting container to fix it...') + err = True + exit_code = 2 + + if chain_position > 0: + self.logger.logCrit(f'MAILCOW target is in position {chain_position} in the {filter_table} {chain} table, restarting container to fix it...') + err = True + exit_code = 2 + + return err, exit_code + + def clearIPv4Table(self): + self.clearTable("ip") + + def clearIPv6Table(self): + self.clearTable("ip6") + + def clearTable(self, _family): + is_empty_dict = True + json_command = self.get_base_dict() + chain_handle = self.get_chain_handle(_family, "filter", self.chain_name) + # if no handle, the chain doesn't exists + if chain_handle is not None: + is_empty_dict = False + # flush chain + mailcow_chain = {'family': _family, 'table': 'filter', 'name': self.chain_name} + flush_chain = {'flush': {'chain': mailcow_chain}} + json_command["nftables"].append(flush_chain) + + # remove rule in forward chain + # remove rule in input chain + chains_family = [self.nft_chain_names[_family]['filter']['input'], + self.nft_chain_names[_family]['filter']['forward'] ] + + for chain_base in chains_family: + if not chain_base: continue + + rules_handle = self.get_rules_handle(_family, "filter", chain_base) + if rules_handle is not None: + for r_handle in rules_handle: + is_empty_dict = False + mailcow_rule = {'family':_family, + 'table': 'filter', + 'chain': chain_base, + 'handle': r_handle } + delete_rules = {'delete': {'rule': mailcow_rule} } + json_command["nftables"].append(delete_rules) + + # remove chain + # after delete all rules referencing this chain + if chain_handle is not None: + mc_chain_handle = {'family':_family, + 'table': 'filter', + 'name': self.chain_name, + 'handle': chain_handle } + delete_chain = {'delete': {'chain': mc_chain_handle} } + json_command["nftables"].append(delete_chain) + + if is_empty_dict == False: + if self.nft_exec_dict(json_command): + self.logger.logInfo(f"Clear completed: {_family}") + + def banIPv4(self, source): + ban_dict = self.get_ban_ip_dict(source, "ip") + return self.nft_exec_dict(ban_dict) + + def banIPv6(self, source): + ban_dict = self.get_ban_ip_dict(source, "ip6") + return self.nft_exec_dict(ban_dict) + + def unbanIPv4(self, source): + unban_dict = self.get_unban_ip_dict(source, "ip") + if not unban_dict: + return False + return self.nft_exec_dict(unban_dict) + + def unbanIPv6(self, source): + unban_dict = self.get_unban_ip_dict(source, "ip6") + if not unban_dict: + return False + return self.nft_exec_dict(unban_dict) + + def snat4(self, snat_target, source): + self.snat_rule("ip", snat_target, source) + + def snat6(self, snat_target, source): + self.snat_rule("ip6", snat_target, source) + + + def nft_exec_dict(self, query: dict): + if not query: return False + + rc, output, error = self.nft.json_cmd(query) + if rc != 0: + #self.logger.logCrit(f"Nftables Error: {error}") + return False + + # Prevent returning False or empty string on commands that do not produce output + if rc == 0 and len(output) == 0: + return True + + return output + + def get_base_dict(self): + return {'nftables': [{ 'metainfo': { 'json_schema_version': 1} } ] } + + def search_current_chains(self): + nft_chain_priority = {'ip': {'filter': {'input': None, 'forward': None}, 'nat': {'postrouting': None} }, + 'ip6': {'filter': {'input': None, 'forward': None}, 'nat': {'postrouting': None} } } + + # Command: 'nft list chains' + _list = {'list' : {'chains': 'null'} } + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + if kernel_ruleset: + for _object in kernel_ruleset['nftables']: + chain = _object.get("chain") + if not chain: continue + + _family = chain['family'] + _table = chain['table'] + _hook = chain.get("hook") + _priority = chain.get("prio") + _name = chain['name'] + + if _family not in self.nft_chain_names: continue + if _table not in self.nft_chain_names[_family]: continue + if _hook not in self.nft_chain_names[_family][_table]: continue + if _priority is None: continue + + _saved_priority = nft_chain_priority[_family][_table][_hook] + if _saved_priority is None or _priority < _saved_priority: + # at this point, we know the chain has: + # hook and priority set + # and it has the lowest priority + nft_chain_priority[_family][_table][_hook] = _priority + self.nft_chain_names[_family][_table][_hook] = _name + + def search_for_chain(self, kernel_ruleset: dict, chain_name: str): + found = False + for _object in kernel_ruleset["nftables"]: + chain = _object.get("chain") + if not chain: + continue + ch_name = chain.get("name") + if ch_name == chain_name: + found = True + break + return found + + def get_chain_dict(self, _family: str, _name: str): + # nft (add | create) chain [] + _chain_opts = {'family': _family, 'table': 'filter', 'name': _name } + _add = {'add': {'chain': _chain_opts} } + final_chain = self.get_base_dict() + final_chain["nftables"].append(_add) + return final_chain + + def get_mailcow_jump_rule_dict(self, _family: str, _chain: str): + _jump_rule = self.get_base_dict() + _expr_opt=[] + _expr_counter = {'family': _family, 'table': 'filter', 'packets': 0, 'bytes': 0} + _counter_dict = {'counter': _expr_counter} + _expr_opt.append(_counter_dict) + + _jump_opts = {'jump': {'target': self.chain_name} } + + _expr_opt.append(_jump_opts) + + _rule_params = {'family': _family, + 'table': 'filter', + 'chain': _chain, + 'expr': _expr_opt, + 'comment': "mailcow" } + + _add_rule = {'insert': {'rule': _rule_params} } + + _jump_rule["nftables"].append(_add_rule) + + return _jump_rule + + def insert_mailcow_chains(self, _family: str): + nft_input_chain = self.nft_chain_names[_family]['filter']['input'] + nft_forward_chain = self.nft_chain_names[_family]['filter']['forward'] + # Command: 'nft list table filter' + _table_opts = {'family': _family, 'name': 'filter'} + _list = {'list': {'table': _table_opts} } + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + if kernel_ruleset: + # chain + if not self.search_for_chain(kernel_ruleset, self.chain_name): + cadena = self.get_chain_dict(_family, self.chain_name) + if self.nft_exec_dict(cadena): + self.logger.logInfo(f"MAILCOW {_family} chain created successfully.") + + input_jump_found, forward_jump_found = False, False + + for _object in kernel_ruleset["nftables"]: + if not _object.get("rule"): + continue + + rule = _object["rule"] + if nft_input_chain and rule["chain"] == nft_input_chain: + if rule.get("comment") and rule["comment"] == "mailcow": + input_jump_found = True + if nft_forward_chain and rule["chain"] == nft_forward_chain: + if rule.get("comment") and rule["comment"] == "mailcow": + forward_jump_found = True + + if not input_jump_found: + command = self.get_mailcow_jump_rule_dict(_family, nft_input_chain) + self.nft_exec_dict(command) + + if not forward_jump_found: + command = self.get_mailcow_jump_rule_dict(_family, nft_forward_chain) + self.nft_exec_dict(command) + + def delete_nat_rule(self, _family:str, _chain: str, _handle:str): + delete_command = self.get_base_dict() + _rule_opts = {'family': _family, + 'table': 'nat', + 'chain': _chain, + 'handle': _handle } + _delete = {'delete': {'rule': _rule_opts} } + delete_command["nftables"].append(_delete) + + return self.nft_exec_dict(delete_command) + + def snat_rule(self, _family: str, snat_target: str, source_address: str): + chain_name = self.nft_chain_names[_family]['nat']['postrouting'] + + # no postrouting chain, may occur if docker has ipv6 disabled. + if not chain_name: return + + # Command: nft list chain nat + _chain_opts = {'family': _family, 'table': 'nat', 'name': chain_name} + _list = {'list':{'chain': _chain_opts} } + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + if not kernel_ruleset: + return + + rule_position = 0 + rule_handle = None + rule_found = False + for _object in kernel_ruleset["nftables"]: + if not _object.get("rule"): + continue + + rule = _object["rule"] + if not rule.get("comment") or not rule["comment"] == "mailcow": + rule_position +=1 + continue + + rule_found = True + rule_handle = rule["handle"] + break + + dest_net = ipaddress.ip_network(source_address) + target_net = ipaddress.ip_network(snat_target) + + if rule_found: + saddr_ip = rule["expr"][0]["match"]["right"]["prefix"]["addr"] + saddr_len = int(rule["expr"][0]["match"]["right"]["prefix"]["len"]) + + daddr_ip = rule["expr"][1]["match"]["right"]["prefix"]["addr"] + daddr_len = int(rule["expr"][1]["match"]["right"]["prefix"]["len"]) + + target_ip = rule["expr"][3]["snat"]["addr"] + + saddr_net = ipaddress.ip_network(saddr_ip + '/' + str(saddr_len)) + daddr_net = ipaddress.ip_network(daddr_ip + '/' + str(daddr_len)) + current_target_net = ipaddress.ip_network(target_ip) + + match = all(( + dest_net == saddr_net, + dest_net == daddr_net, + target_net == current_target_net + )) + try: + if rule_position == 0: + if not match: + # Position 0 , it is a mailcow rule , but it does not have the same parameters + if self.delete_nat_rule(_family, chain_name, rule_handle): + self.logger.logInfo(f'Remove rule for source network {saddr_net} to SNAT target {target_net} from {_family} nat {chain_name} chain, rule does not match configured parameters') + else: + # Position > 0 and is mailcow rule + if self.delete_nat_rule(_family, chain_name, rule_handle): + self.logger.logInfo(f'Remove rule for source network {saddr_net} to SNAT target {target_net} from {_family} nat {chain_name} chain, rule is at position {rule_position}') + except: + self.logger.logCrit(f"Error running SNAT on {_family}, retrying..." ) + else: + # rule not found + json_command = self.get_base_dict() + try: + snat_dict = {'snat': {'addr': str(target_net.network_address)} } + + expr_counter = {'family': _family, 'table': 'nat', 'packets': 0, 'bytes': 0} + counter_dict = {'counter': expr_counter} + + prefix_dict = {'prefix': {'addr': str(dest_net.network_address), 'len': int(dest_net.prefixlen)} } + payload_dict = {'payload': {'protocol': _family, 'field': "saddr"} } + match_dict1 = {'match': {'op': '==', 'left': payload_dict, 'right': prefix_dict} } + + payload_dict2 = {'payload': {'protocol': _family, 'field': "daddr"} } + match_dict2 = {'match': {'op': '!=', 'left': payload_dict2, 'right': prefix_dict } } + expr_list = [ + match_dict1, + match_dict2, + counter_dict, + snat_dict + ] + rule_fields = {'family': _family, + 'table': 'nat', + 'chain': chain_name, + 'comment': "mailcow", + 'expr': expr_list } + + insert_dict = {'insert': {'rule': rule_fields} } + json_command["nftables"].append(insert_dict) + if self.nft_exec_dict(json_command): + self.logger.logInfo(f'Added {_family} nat {chain_name} rule for source network {dest_net} to {target_net}') + except: + self.logger.logCrit(f"Error running SNAT on {_family}, retrying...") + + def get_chain_handle(self, _family: str, _table: str, chain_name: str): + chain_handle = None + # Command: 'nft list chains {family}' + _list = {'list': {'chains': {'family': _family} } } + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + if kernel_ruleset: + for _object in kernel_ruleset["nftables"]: + if not _object.get("chain"): + continue + chain = _object["chain"] + if chain["family"] == _family and chain["table"] == _table and chain["name"] == chain_name: + chain_handle = chain["handle"] + break + return chain_handle + + def get_rules_handle(self, _family: str, _table: str, chain_name: str): + rule_handle = [] + # Command: 'nft list chain {family} {table} {chain_name}' + _chain_opts = {'family': _family, 'table': _table, 'name': chain_name} + _list = {'list': {'chain': _chain_opts} } + command = self.get_base_dict() + command['nftables'].append(_list) + + kernel_ruleset = self.nft_exec_dict(command) + if kernel_ruleset: + for _object in kernel_ruleset["nftables"]: + if not _object.get("rule"): + continue + + rule = _object["rule"] + if rule["family"] == _family and rule["table"] == _table and rule["chain"] == chain_name: + if rule.get("comment") and rule["comment"] == "mailcow": + rule_handle.append(rule["handle"]) + return rule_handle + + def get_ban_ip_dict(self, ipaddr: str, _family: str): + json_command = self.get_base_dict() + + expr_opt = [] + ipaddr_net = ipaddress.ip_network(ipaddr) + right_dict = {'prefix': {'addr': str(ipaddr_net.network_address), 'len': int(ipaddr_net.prefixlen) } } + + left_dict = {'payload': {'protocol': _family, 'field': 'saddr'} } + match_dict = {'op': '==', 'left': left_dict, 'right': right_dict } + expr_opt.append({'match': match_dict}) + + counter_dict = {'counter': {'family': _family, 'table': "filter", 'packets': 0, 'bytes': 0} } + expr_opt.append(counter_dict) + + expr_opt.append({'drop': "null"}) + + rule_dict = {'family': _family, 'table': "filter", 'chain': self.chain_name, 'expr': expr_opt} + + base_dict = {'insert': {'rule': rule_dict} } + json_command["nftables"].append(base_dict) + + return json_command + + def get_unban_ip_dict(self, ipaddr:str, _family: str): + json_command = self.get_base_dict() + # Command: 'nft list chain {s_family} filter MAILCOW' + _chain_opts = {'family': _family, 'table': 'filter', 'name': self.chain_name} + _list = {'list': {'chain': _chain_opts} } + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + rule_handle = None + if kernel_ruleset: + for _object in kernel_ruleset["nftables"]: + if not _object.get("rule"): + continue + + rule = _object["rule"]["expr"][0]["match"] + left_opt = rule["left"]["payload"] + if not left_opt["protocol"] == _family: + continue + if not left_opt["field"] =="saddr": + continue + + # ip currently banned + rule_right = rule["right"] + if isinstance(rule_right, dict): + current_rule_ip = rule_right["prefix"]["addr"] + '/' + str(rule_right["prefix"]["len"]) + else: + current_rule_ip = rule_right + current_rule_net = ipaddress.ip_network(current_rule_ip) + + # ip to ban + candidate_net = ipaddress.ip_network(ipaddr) + + if current_rule_net == candidate_net: + rule_handle = _object["rule"]["handle"] + break + + if rule_handle is not None: + mailcow_rule = {'family': _family, 'table': 'filter', 'chain': self.chain_name, 'handle': rule_handle} + delete_rule = {'delete': {'rule': mailcow_rule} } + json_command["nftables"].append(delete_rule) + else: + return False + + return json_command + + def check_mailcow_chains(self, family: str, chain: str): + position = 0 + rule_found = False + chain_name = self.nft_chain_names[family]['filter'][chain] + + if not chain_name: return None + + _chain_opts = {'family': family, 'table': 'filter', 'name': chain_name} + _list = {'list': {'chain': _chain_opts}} + command = self.get_base_dict() + command['nftables'].append(_list) + kernel_ruleset = self.nft_exec_dict(command) + if kernel_ruleset: + for _object in kernel_ruleset["nftables"]: + if not _object.get("rule"): + continue + rule = _object["rule"] + if rule.get("comment") and rule["comment"] == "mailcow": + rule_found = True + break + + position+=1 + + return position if rule_found else False diff --git a/data/Dockerfiles/netfilter/modules/__init__.py b/data/Dockerfiles/netfilter/modules/__init__.py new file mode 100644 index 000000000..e69de29bb diff --git a/docker-compose.yml b/docker-compose.yml index 8d84e3a75..bba0610f7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -434,7 +434,7 @@ services: - acme netfilter-mailcow: - image: mailcow/netfilter:1.52 + image: mailcow/netfilter:1.53 stop_grace_period: 30s depends_on: - dovecot-mailcow From b93375b67166deb48a46cd30c7939a120e56925d Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 30 Oct 2023 12:05:10 +0100 Subject: [PATCH 133/174] [Web] Updated lang.hu-hu.json (#5505) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Bence Kócsi --- data/web/lang/lang.hu-hu.json | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/data/web/lang/lang.hu-hu.json b/data/web/lang/lang.hu-hu.json index 327f07526..1c798bd90 100644 --- a/data/web/lang/lang.hu-hu.json +++ b/data/web/lang/lang.hu-hu.json @@ -394,7 +394,12 @@ "filters": "Szűrők", "login_as": "Bejelentkezés mint", "quarantine": "Karantén műveletek", - "bcc_maps": "BCC címek" + "bcc_maps": "BCC címek", + "domain_relayhost": "Relayhost megváltoztatása egy domainhez", + "protocol_access": "Protokoll-hozzáférés módosítása", + "quarantine_attachments": "Karantén mellékletek", + "quarantine_category": "Karantén értesítési kategória módosítása", + "quarantine_notification": "Karantén értesítések módosítása" }, "diagnostics": { "dns_records": "DNS bejegyzések" From a28ba5bebbf57880c03f5ea1658305144791dec8 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 30 Oct 2023 16:07:10 +0100 Subject: [PATCH 134/174] [Web] fix broken github links in changelog --- data/web/js/site/debug.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/js/site/debug.js b/data/web/js/site/debug.js index 10b1e8cf3..512d9551e 100644 --- a/data/web/js/site/debug.js +++ b/data/web/js/site/debug.js @@ -1684,7 +1684,7 @@ function showVersionModal(title, version){ function parseGithubMarkdownLinks(inputText) { var replacedText, replacePattern1; - replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])/gim; + replacePattern1 = /(\b(https?):\/\/[-A-Z0-9+&@#\/%?=~_|!:,.;]*[-A-Z0-9+&@#\/%=~_|])(?![^<]*>)/gim; replacedText = inputText.replace(replacePattern1, (matched, index, original, input_string) => { if (matched.includes('github.com')){ // return short link if it's github link From 413354ff29ac28a9b2bc52e2499407f20dfd27a8 Mon Sep 17 00:00:00 2001 From: HardikBandhiya Date: Tue, 31 Oct 2023 02:07:46 +0530 Subject: [PATCH 135/174] Update README.md MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit changed the name of Twitter to 𝕏 --- README.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 2dacac9ae..3d6599caf 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ Please see [the official documentation](https://docs.mailcow.email/) for install [Telegram mailcow Off-Topic channel](https://t.me/mailcowOfftopic) -[Official Twitter Account](https://twitter.com/mailcow_email) +[Official 𝕏 (Twitter) Account](https://twitter.com/mailcow_email) Telegram desktop clients are available for [multiple platforms](https://desktop.telegram.org). You can search the groups history for keywords. @@ -38,4 +38,4 @@ mailcow is a registered word mark of The Infrastructure Company GmbH, Parkstr. 4 The project is managed and maintained by The Infrastructure Company GmbH. -Originated from @andryyy (André) \ No newline at end of file +Originated from @andryyy (André) From a1895ad92489c9cb8804ee6a46230be1466eb1b2 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Wed, 1 Nov 2023 00:14:25 +0000 Subject: [PATCH 136/174] update postscreen_access.cidr --- data/conf/postfix/postscreen_access.cidr | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 61aac6443..23e3d62df 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Sun Oct 1 00:14:59 UTC 2023 +# Whitelist generated by Postwhite v3.4 on Wed Nov 1 00:14:24 UTC 2023 # https://github.com/stevejenkins/postwhite/ -# 2019 total rules +# 2030 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:8000::/50 permit @@ -211,6 +211,7 @@ 52.96.222.194 permit 52.96.222.226 permit 52.96.223.2 permit +52.96.228.130 permit 52.96.229.242 permit 52.100.0.0/14 permit 52.103.0.0/17 permit @@ -1369,6 +1370,8 @@ 128.245.0.0/20 permit 128.245.64.0/20 permit 128.245.176.0/20 permit +128.245.240.0/24 permit +128.245.241.0/24 permit 128.245.242.0/24 permit 128.245.242.16 permit 128.245.242.17 permit @@ -1378,6 +1381,7 @@ 128.245.245.0/24 permit 128.245.246.0/24 permit 128.245.247.0/24 permit +128.245.248.0/21 permit 129.41.77.70 permit 129.41.169.249 permit 129.80.5.164 permit @@ -1492,6 +1496,8 @@ 158.101.211.207 permit 158.120.80.0/21 permit 158.247.16.0/20 permit +159.92.154.0/24 permit +159.92.155.0/24 permit 159.92.157.0/24 permit 159.92.157.16 permit 159.92.157.17 permit @@ -1501,6 +1507,9 @@ 159.92.160.0/24 permit 159.92.161.0/24 permit 159.92.162.0/24 permit +159.92.163.0/24 permit +159.92.164.0/22 permit +159.92.168.0/21 permit 159.112.240.0/20 permit 159.112.242.162 permit 159.135.132.128/25 permit @@ -1549,6 +1558,7 @@ 168.245.127.231 permit 169.148.129.0/24 permit 169.148.131.0/24 permit +169.148.144.0/25 permit 170.10.68.0/22 permit 170.10.128.0/24 permit 170.10.129.0/24 permit @@ -1706,6 +1716,7 @@ 199.16.156.0/22 permit 199.33.145.1 permit 199.33.145.32 permit +199.34.22.36 permit 199.59.148.0/22 permit 199.67.84.0/24 permit 199.67.86.0/24 permit From 4e52542e3333fe7d09265ce66827542645c5fd0b Mon Sep 17 00:00:00 2001 From: Burak Buylu Date: Wed, 1 Nov 2023 11:26:05 +0300 Subject: [PATCH 137/174] Update lang.tr-tr.json (#5510) Every day I will translate :) --- data/web/lang/lang.tr-tr.json | 139 +++++++++++++++++++++++++--------- 1 file changed, 102 insertions(+), 37 deletions(-) diff --git a/data/web/lang/lang.tr-tr.json b/data/web/lang/lang.tr-tr.json index 20091db1e..5219c41d2 100644 --- a/data/web/lang/lang.tr-tr.json +++ b/data/web/lang/lang.tr-tr.json @@ -1,61 +1,113 @@ { "acl": { - "alias_domains": "Takma alan adı ekle", + "alias_domains": "Alias domain ekle", "app_passwds": "Uygulama şifrelerini yönet", - "delimiter_action": "Sınırlama işlemi", - "domain_relayhost": "Bir alan adı için relayhost sunucusunu değiştir", - "eas_reset": "EAS cihazlarını sıfırla", - "mailbox_relayhost": "Bir posta kutusunun relayhost sunucularını değiştir", - "pushover": "Bildirim", - "quarantine": "Karantina işlemleri", - "quarantine_attachments": "Ekleri karantinaya al", - "quarantine_notification": "Karantina bildirimlerini değiştir", - "smtp_ip_access": "SMTP sunucularının değiştirilmesine izin ver", - "sogo_access": "SOGo erişiminin yönetilmesine izin ver", + "bcc_maps": "BCC haritası", + "delimiter_action": "Sınırlandırma işlemi", "domain_desc": "Alan adı açıklamasını değiştir", - "extend_sender_acl": "Gönderenin acl'sini harici adreslere göre genişletmeye izin ver", - "spam_policy": "Engellenenler / İzin verilenler", - "filters": "Fitreler" + "domain_relayhost": "Alan adı için relayhost sunucusunu değiştir", + "eas_reset": "EAS cihazlarını sıfırla", + "extend_sender_acl": "Gönderen ACL'sini harici adreslerle genişletmeye izin ver", + "filters": "Filtreler", + "login_as": "E-posta kullanıcısı olarak giriş yapın", + "mailbox_relayhost": "Bir e-posta için relayhost'u değiştirin", + "prohibited": "ACL tarafından yasaklandı", + "protocol_access": "Protokol erişimini değiştirin", + "pushover": "Pushover", + "quarantine": "Karantina eylemleri", + "quarantine_attachments": "Ekleri karantinaya al", + "quarantine_category": "Karantina bildirim kategorisini değiştir", + "quarantine_notification": "Karantina bildirimlerini değiştir", + "ratelimit": "Rate limit", + "recipient_maps": "Alıcı haritaları", + "smtp_ip_access": "SMTP için izin verilen host değerlerini değiştirme", + "sogo_access": "SOGo erişiminin yönetilmesine izin verin", + "sogo_profile_reset": "SOGo profilini sıfırla", + "spam_alias": "Geçici alias değerleri", + "spam_policy": "Kara Liste/Beyaz Liste", + "spam_score": "Spam skoru", + "syncjobs": "Görevleri senkronize et", + "tls_policy": "TLS ilkesi", + "unlimited_quota": "E-postalar için sınırsız kota" }, "add": { "activate_filter_warn": "Aktif edilirse diğer tüm filtreler devre dışı bırakılacak.", + "active": "Aktif", + "add": "Ekle", "add_domain_only": "Sadece alan adı ekle", - "alias_address": "Takma ad adres(leri)", + "add_domain_restart": "Alan adını ekleyin ve SOGo'yu yeniden başlatın", + "alias_address": "Takma adres", + "alias_address_info": "Bir alan adına ilişkin tüm iletileri yakalamak için tam e-posta adresi veya @example.com olacak şeklinde girin (virgülle ayırın).sadece mailcow alan adları.", "alias_domain": "Takma alan adı", - "alias_domain_info": "Sadece geçerli alan adları (virgülle ayırın).", - "backup_mx_options": "İletme ayarları", - "delete2": "Kaynakta olmayan hedefteki mesajları sil", + "alias_domain_info": "Sadece geçerli alan adları (virgülle ayrılmış).", + "app_name": "Uygulama adı", + "app_password": "Uygulama şifresi ekle", + "app_passwd_protocols": "Uygulama şifresi için izin verilen protokoller", + "automap": "Klasörleri otomatik eşleştirmeyi deneyin (\"Gönderilen postalar\", \"Gönderilen\" => \"Gönderilen\" vb.)", + "backup_mx_options": "Relay ayarları", + "bcc_dest_format": "BCC hedefi tek bir geçerli e-posta adresi olmalıdır.
    Bir kopyayı birden fazla adrese göndermeniz gerekiyorsa, bir takma ad oluşturun ve bunu burada kullanın.", + "comment_info": "Özel bir yorum kullanıcı tarafından görülemezken, herkese açık bir yorum kullanıcının genel görünümünde üzerine gelindiğinde tooltip olarak gösterilir", + "custom_params": "Özel parametreler", + "custom_params_hint": "Doğru: --param=xy, yanlış: --param xy", + "delete1": "Tamamlandığında kaynaktan sil", + "delete2": "Eğer kaynakta yoksa hedefteki mesajları sil", "delete2duplicates": "Hedefteki kopyaları sil", - "disable_login": "Giriş yapmaya izin verme ( Gelen mailler yine de kabul edilir)", + "description": "Açıklama", + "destination": "Hedef", + "disable_login": "Giriş yapmaya izin verme (gelen mailler yine de kabul edilir)", "domain": "Alan adı", "domain_matches_hostname": "Alan adı %s ana bilgisayar adıyla eşleşiyor", - "add_domain_restart": "Alan adı ekleyin ve SOGo'yu yeniden başlatın", - "alias_address_info": "Bir alan adına ilişkin tüm iletileri yakalamak için tam e-posta adresi veya @example.com olacak şeklinde girin (virgülle ayırın).sadece mailcow alan adları.", "domain_quota_m": "Toplam alan adı kotası (MiB)", + "enc_method": "Şifreleme yöntemi", + "exclude": "Hariç tutma kuralı (regex)", + "full_name": "Tam isim", + "gal": "Global Adres Listesi", + "gal_info": "GAL bir alan alanının tüm nesnelerini içerir ve herhangi bir kullanıcı tarafından düzenlenemez. Eğer devre dışı bırakırsanız SOGo üzerindeki free/busy bilgileri kaybolur! Değişiklikleri uygulamak için SOGo'yu yeniden başlatın.", "generate": "oluştur", "goto_ham": "Ham olarakişaretle", - "goto_null": "Postaları sessizce çöpe at", + "goto_null": "Postaları çöpe at", "goto_spam": "Spam olarakişaretle", "hostname": "Ana sunucu", + "inactive": "İnaktif", "kind": "Tür", - "mailbox_quota_m": "Posta kutusu başına maksimum kota (MiB)", - "max_aliases": "Maksimum olası takma adı", - "max_mailboxes": "Maksimum olası posta kutusu", - "nexthop": "Sonraki atlama", + "mailbox_quota_def": "Varsayılan e-posta kotası", + "mailbox_quota_m": "E-posta başına maksimum kota (MiB)", + "mailbox_username": "Kullanıcı adı (e-posta adresinin sol kısmı)", + "max_aliases": "Maksimum takma adı limiti", + "max_mailboxes": "Maksimum e-posta hesabı", + "mins_interval": "Sorgulama döngüsü (dakika)", + "multiple_bookings": "Birden fazla rezervasyon", + "nexthop": "Next hop", + "password": "Şifre", + "password_repeat": "Şifre (tekrar)", "port": "Port", - "public_comment": "Genel yorum", - "relay_all": "Tüm alıcılara ilet", - "relay_all_info": "Eğer hiçbir alıcıya iletilmemesini seçerseniz, aktarılması gereken her alıcı için bir (\"kör\") posta kutusu eklemeniz gerekecektir.", - "relay_domain": "Bu alan adını ilet", - "relay_transport_info": "
    Bilgi
    Bu etki alanı için özel bir hedef için aktarım eşlemeleri tanımlayabilirsiniz. Ayarlanmazsa, bir MX araması yapılacaktır.", - "relay_unknown_only": "Yalnızca mevcut olmayan posta kutularını ilet. Mevcut posta kutuları yerel olarak teslim edilecektir.", - "relayhost_wrapped_tls_info": "Lütfen TLS ile örtülmüş portları kullanmayın (çoğu 465 portunda çalışır).
    \nÖrtülmemiş port kullan ve STARTTLS üzerinden yayınla. TLS'yi zorlamak için bir TLS ilkesi \"TLS ilke eşlemeleri\" sayfası içinde oluşturulabilir.", - "skipcrossduplicates": "Klasörler arasında yinelenen mesajları atlayın (ilk mesaj seçilir)", + "post_domain_add": "SOGo konteynerinin \"sogo-mailcow\" yeni bir alan adı eklendikten sonra yeniden başlatılması gerekiyor!

    Ayrıca alan adlarının DNS yapılandırması da gözden geçirilmelidir. DNS yapılandırması onaylandıktan sonra, yeni etki alanınız için otomatik olarak sertifika oluşturmak üzere \"acme-mailcow\"u yeniden başlatın (autoconfig.<domain>, autodiscover.<domain>).
    Bu adım isteğe bağlıdır ve her 24 saatte bir yeniden denenecektir.", + "private_comment": "Özel not", + "public_comment": "Herkese açık not", + "quota_mb": "Kota (MiB)", + "relay_all": "Tüm alıcıları aktar", + "relay_all_info": "↪ Tüm alıcıları aktarmamayı seçerseniz, aktarılması gereken her alıcı için bir (\"kör\") posta kutusu eklemeniz gerekecektir.", + "relay_domain": "Bu etki alanını aktarın", + "relay_transport_info": "
    Bilgi
    Bu alan adı nezdinde özel bir hedef için transport haritası tanımlayabilirsiniz. Eğer ayarlanmazsa, MX taraması yapılacaktır.", + "relay_unknown_only": "Yalnızca mevcut olmayan e-postaları aktarın. Mevcut e-postalar local olarak teslim edilecektir.", + "relayhost_wrapped_tls_info": "Lütfen örtülü TLS portları kullanmayın (çoğunlukla 465 portunda kullanılır).
    \r\nÖrtülmüş olmayan herhangi bir bağlantı noktası kullanın ve STARTTLS üzerinden yayınlayın. TLS'yi zorlamak için bir TLS ilkesi \"TLS ilke eşlemeleri\" sayfası içinde oluşturulabilir.", + "select": "Lütfen seçiniz...", + "select_domain": "Lütfen önce alan adı seçin", + "sieve_desc": "Kısa açıklama", + "sieve_type": "Filtre türü", + "skipcrossduplicates": "Klasörler arasında yinelenen(kopya) mesajları es geçin (ilk gelen mail baz alınır)", + "subscribeall": "Tüm klasörlere abone ol", + "syncjob": "Senkronizasyon görevi ekle", + "syncjob_hint": "Parolaların düz metin olarak kaydedilmesi gerektiğini unutmayın!", + "tags": "Etiketler", "target_address": "Adreslere git", - "target_address_info": "Tam e-posta adres(leri) girin ( virgülle ayırın).", + "target_address_info": "Tam e-posta adresleri (virgülle ayrılmış).", "target_domain": "Hedef alan adı", - "timeout1": "Uzak ana bilgisayara bağlantısı zaman aşımına uğradı", - "timeout2": "Yerel ana bilgisayara bağlantı zaman aşımına uğradı" + "timeout1": "Uzak ana bilgisayara bağlantı için zaman aşımı", + "timeout2": "Yerel ana bilgisayara bağlantı için zaman aşımı", + "username": "Kullanıcı Adı", + "validate": "Doğrula", + "validation_success": "Doğrulama başarılı" }, "admin": { "action": "İşlem", @@ -82,5 +134,18 @@ "f2b_ban_time": "Yasaklama süresi (saniye)", "f2b_max_attempts": "Maksimum giriş denemesi", "f2b_retry_window": "Maksimum girişim için deneme pencere(leri)" + }, + "warning": { + "cannot_delete_self": "Cannot delete logged in user", + "domain_added_sogo_failed": "Alan adı eklendi ancak SOGo yeniden başlatılamadı, lütfen sunucu log kayıtlarını kontrol edin.", + "dovecot_restart_failed": "Dovecot yeniden başlatılamadı, lütfen log kayıtlarını kontrol edin", + "fuzzy_learn_error": "Fuzzy hash hatayı öğrendi: %s", + "hash_not_found": "Hash bulunamadı veya zaten silinmiş", + "ip_invalid": "Geçersiz IP atlandı: %s", + "is_not_primary_alias": "Birincil olmayan alias %s atlandı", + "no_active_admin": "Son etkin yönetici devre dışı bırakılamaz", + "quota_exceeded_scope": "Domain kotası aşıldı: Bu domain kapsamında yalnızca sınırsız e-posta oluşturulabilir!", + "session_token": "Form token geçersiz: Token uyuşmadı", + "session_ua": "Form token geçersiz: User-Agent doğrulama hatası" } } From 9a7e1c2b5a872b4b85600ea17f5a99fe67b84dab Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 2 Nov 2023 17:15:10 +0100 Subject: [PATCH 138/174] Added new Sieve Template. Thanks to @EricThi --- data/web/inc/presets/sieve/sieve_8.yml | 18 ++++++++++++++++++ data/web/lang/lang.de-de.json | 2 +- data/web/lang/lang.en-gb.json | 2 +- 3 files changed, 20 insertions(+), 2 deletions(-) create mode 100644 data/web/inc/presets/sieve/sieve_8.yml diff --git a/data/web/inc/presets/sieve/sieve_8.yml b/data/web/inc/presets/sieve/sieve_8.yml new file mode 100644 index 000000000..bd44a7368 --- /dev/null +++ b/data/web/inc/presets/sieve/sieve_8.yml @@ -0,0 +1,18 @@ +headline: lang.sieve_preset_8 +content: | + require "fileinto"; + require "mailbox"; + require "variables"; + require "subaddress"; + require "envelope"; + require "duplicate"; + require "imap4flags"; + if header :matches "To" "*mail@domain.tld*" { + redirect "anothermail@anotherdomain.tld"; + setflag "\\seen"; /* Mark mail as read */ + fileInto "INBOX/SubFolder"; /* Move mail on subfolder after */ + } else { + # The rest goes into INBOX + # default is "implicit keep", we do it explicitly here + keep; + } \ No newline at end of file diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index ee3d225c0..5d051615d 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -857,7 +857,7 @@ "sieve_preset_5": "Auto-Responder (Vacation, Urlaub)", "sieve_preset_6": "E-Mails mit Nachricht abweisen", "sieve_preset_7": "Weiterleiten und behalten oder verwerfen", - "sieve_preset_8": "Nachricht verwerfen, wenn Absender und Alias-Ziel identisch sind.", + "sieve_preset_8": "E-Mail eines bestimmten Absenders umleiten, als gelesen markieren und in Unterordner sortieren", "sieve_preset_header": "Beispielinhalte zur Einsicht stehen nachstehend bereit. Siehe auch Wikipedia.", "sogo_visible": "Alias Sichtbarkeit in SOGo", "sogo_visible_n": "Alias in SOGo verbergen", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 63b6e80db..36eb4ab48 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -873,7 +873,7 @@ "sieve_preset_5": "Auto responder (vacation)", "sieve_preset_6": "Reject mail with reponse", "sieve_preset_7": "Redirect and keep/drop", - "sieve_preset_8": "Discard message sent to an alias address the sender is part of", + "sieve_preset_8": "Redirect e-mail from a specific sender, mark as read and sort into subfolder", "sieve_preset_header": "Please see the example presets below. For more details see Wikipedia.", "sogo_visible": "Alias is visible in SOGo", "sogo_visible_n": "Hide alias in SOGo", From afed94cc0ebb1af25815e3c4e93c435740d6a584 Mon Sep 17 00:00:00 2001 From: Raphael Date: Thu, 9 Nov 2023 15:24:16 +0100 Subject: [PATCH 139/174] Allow `--dry` IMAPsync --- data/web/inc/vars.inc.php | 1 + 1 file changed, 1 insertion(+) diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 392b0d49e..1110319dd 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -242,6 +242,7 @@ $IMAPSYNC_OPTIONS = array( 'authuser2', 'debugcontent', 'disarmreadreceipts', + 'dry', 'logdir', 'debugcrossduplicates', 'maxsize', From 5ec9c4c75008378423d94c15524e5d2d3f538b83 Mon Sep 17 00:00:00 2001 From: Peter Date: Sun, 12 Nov 2023 18:00:20 +0100 Subject: [PATCH 140/174] Fix renovate regex --- data/Dockerfiles/dovecot/Dockerfile | 4 ++-- data/Dockerfiles/phpfpm/Dockerfile | 6 +++--- data/Dockerfiles/sogo/Dockerfile | 2 +- data/Dockerfiles/solr/Dockerfile | 2 +- 4 files changed, 7 insertions(+), 7 deletions(-) diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index 90a6af938..2ace9029e 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -2,9 +2,9 @@ FROM debian:bullseye-slim LABEL maintainer "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive -# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-tags depName=dovecot/core versioning=semver-coerced extractVersion=(?.*)$ ARG DOVECOT=2.3.21 -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?.*)$ ARG GOSU_VERSION=1.16 ENV LC_ALL C diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index ea8c78a5b..490310336 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -3,15 +3,15 @@ LABEL maintainer "The Infrastructure Company GmbH " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$ ARG APCU_PECL_VERSION=5.1.22 -# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?.*)$ ARG IMAGICK_PECL_VERSION=3.7.0 # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ ARG MAILPARSE_PECL_VERSION=3.1.6 # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ ARG MEMCACHED_PECL_VERSION=3.2.0 -# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?.*)$ ARG REDIS_PECL_VERSION=6.0.1 -# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?.*)$ ARG COMPOSER_VERSION=2.6.5 RUN apk add -U --no-cache autoconf \ diff --git a/data/Dockerfiles/sogo/Dockerfile b/data/Dockerfiles/sogo/Dockerfile index 35e0721ec..e8a7410f5 100644 --- a/data/Dockerfiles/sogo/Dockerfile +++ b/data/Dockerfiles/sogo/Dockerfile @@ -3,7 +3,7 @@ LABEL maintainer "The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive ARG SOGO_DEBIAN_REPOSITORY=http://packages.sogo.nu/nightly/5/debian/ -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$ ARG GOSU_VERSION=1.16 ENV LC_ALL C diff --git a/data/Dockerfiles/solr/Dockerfile b/data/Dockerfiles/solr/Dockerfile index dd465b4d4..a6359876b 100644 --- a/data/Dockerfiles/solr/Dockerfile +++ b/data/Dockerfiles/solr/Dockerfile @@ -2,7 +2,7 @@ FROM solr:7.7-slim USER root -# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^v(?.*)$ +# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?.*)$ ARG GOSU_VERSION=1.16 COPY solr.sh / From 46b995f9e3c09bca82a8de60a6adac6df233d0db Mon Sep 17 00:00:00 2001 From: Quiwy <20048264+Quiwy@users.noreply.github.com> Date: Tue, 14 Nov 2023 10:11:25 +0100 Subject: [PATCH 141/174] fix: support utf-8 in password synchronization --- data/Dockerfiles/dovecot/imapsync_runner.pl | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/dovecot/imapsync_runner.pl b/data/Dockerfiles/dovecot/imapsync_runner.pl index 5b297abd9..3ecd212c6 100644 --- a/data/Dockerfiles/dovecot/imapsync_runner.pl +++ b/data/Dockerfiles/dovecot/imapsync_runner.pl @@ -117,7 +117,9 @@ while ($row = $sth->fetchrow_arrayref()) { my $template = $run_dir . '/imapsync.XXXXXXX'; my $passfile1 = File::Temp->new(TEMPLATE => $template); my $passfile2 = File::Temp->new(TEMPLATE => $template); - + + binmode( $passfile1, ":utf8" ); + print $passfile1 "$password1\n"; print $passfile2 trim($master_pass) . "\n"; From 547d2ca3087a9a3b1e383c8edd6c38fd02c455b9 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 15 Nov 2023 16:18:18 +0100 Subject: [PATCH 142/174] Add Dry Mode Option for ImapSyncs (Button) --- data/Dockerfiles/dovecot/imapsync_runner.pl | 5 ++++- data/web/inc/functions.mailbox.inc.php | 9 +++++++-- data/web/inc/init_db.inc.php | 3 ++- data/web/lang/lang.de-de.json | 1 + data/web/lang/lang.en-gb.json | 1 + data/web/templates/edit/syncjob.twig | 10 +++++++++- data/web/templates/modals/mailbox.twig | 11 +++++++++-- data/web/templates/modals/user.twig | 7 +++++++ docker-compose.yml | 2 +- 9 files changed, 41 insertions(+), 8 deletions(-) diff --git a/data/Dockerfiles/dovecot/imapsync_runner.pl b/data/Dockerfiles/dovecot/imapsync_runner.pl index 5b297abd9..f13f9abdb 100644 --- a/data/Dockerfiles/dovecot/imapsync_runner.pl +++ b/data/Dockerfiles/dovecot/imapsync_runner.pl @@ -75,7 +75,8 @@ my $sth = $dbh->prepare("SELECT id, custom_params, subscribeall, timeout1, - timeout2 + timeout2, + dry FROM imapsync WHERE active = 1 AND is_running = 0 @@ -111,6 +112,7 @@ while ($row = $sth->fetchrow_arrayref()) { $subscribeall = @$row[18]; $timeout1 = @$row[19]; $timeout2 = @$row[20]; + $dry = @$row[21]; if ($enc1 eq "TLS") { $enc1 = "--tls1"; } elsif ($enc1 eq "SSL") { $enc1 = "--ssl1"; } else { undef $enc1; } @@ -148,6 +150,7 @@ while ($row = $sth->fetchrow_arrayref()) { "--host2", "localhost", "--user2", $user2 . '*' . trim($master_user), "--passfile2", $passfile2->filename, + ($dry eq "1" ? ('--dry') : ()), '--no-modulesversion', '--noreleasecheck']; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 68cb50f1b..298f607dc 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -325,6 +325,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $timeout2 = intval($_data['timeout2']); $skipcrossduplicates = intval($_data['skipcrossduplicates']); $automap = intval($_data['automap']); + $dry = intval($_data['dry']); $port1 = $_data['port1']; $host1 = strtolower($_data['host1']); $password1 = $_data['password1']; @@ -435,8 +436,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); return false; } - $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`) - VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)"); + $stmt = $pdo->prepare("INSERT INTO `imapsync` (`user2`, `exclude`, `delete1`, `delete2`, `timeout1`, `timeout2`, `automap`, `skipcrossduplicates`, `maxbytespersecond`, `subscribeall`, `dry`, `maxage`, `subfolder2`, `host1`, `authmech1`, `user1`, `password1`, `mins_interval`, `port1`, `enc1`, `delete2duplicates`, `custom_params`, `active`) + VALUES (:user2, :exclude, :delete1, :delete2, :timeout1, :timeout2, :automap, :skipcrossduplicates, :maxbytespersecond, :subscribeall, :dry, :maxage, :subfolder2, :host1, :authmech1, :user1, :password1, :mins_interval, :port1, :enc1, :delete2duplicates, :custom_params, :active)"); $stmt->execute(array( ':user2' => $username, ':custom_params' => $custom_params, @@ -450,6 +451,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':skipcrossduplicates' => $skipcrossduplicates, ':maxbytespersecond' => $maxbytespersecond, ':subscribeall' => $subscribeall, + ':dry' => $dry, ':subfolder2' => $subfolder2, ':host1' => $host1, ':authmech1' => 'PLAIN', @@ -2031,6 +2033,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $success = (isset($_data['success'])) ? NULL : $is_now['success']; $delete2duplicates = (isset($_data['delete2duplicates'])) ? intval($_data['delete2duplicates']) : $is_now['delete2duplicates']; $subscribeall = (isset($_data['subscribeall'])) ? intval($_data['subscribeall']) : $is_now['subscribeall']; + $dry = (isset($_data['dry'])) ? intval($_data['dry']) : $is_now['dry']; $delete1 = (isset($_data['delete1'])) ? intval($_data['delete1']) : $is_now['delete1']; $delete2 = (isset($_data['delete2'])) ? intval($_data['delete2']) : $is_now['delete2']; $automap = (isset($_data['automap'])) ? intval($_data['automap']) : $is_now['automap']; @@ -2164,6 +2167,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { `timeout1` = :timeout1, `timeout2` = :timeout2, `subscribeall` = :subscribeall, + `dry` = :dry, `active` = :active WHERE `id` = :id"); $stmt->execute(array( @@ -2189,6 +2193,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ':timeout1' => $timeout1, ':timeout2' => $timeout2, ':subscribeall' => $subscribeall, + ':dry' => $dry, ':active' => $active, )); $_SESSION['return'][] = array( diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index e286ab553..2ce6a28c1 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "14022023_1000"; + $db_version = "15112023_1536"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -704,6 +704,7 @@ function init_db_schema() { "timeout1" => "SMALLINT NOT NULL DEFAULT '600'", "timeout2" => "SMALLINT NOT NULL DEFAULT '600'", "subscribeall" => "TINYINT(1) NOT NULL DEFAULT '1'", + "dry" => "TINYINT(1) NOT NULL DEFAULT '0'", "is_running" => "TINYINT(1) NOT NULL DEFAULT '0'", "returned_text" => "LONGTEXT", "last_run" => "TIMESTAMP NULL DEFAULT NULL", diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 5d051615d..5811e150c 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -58,6 +58,7 @@ "domain": "Domain", "domain_matches_hostname": "Domain %s darf nicht dem Hostnamen entsprechen", "domain_quota_m": "Domain-Speicherplatz gesamt (MiB)", + "dry": "Simuliere Synchronisation (Probedurchlauf)", "enc_method": "Verschlüsselung", "exclude": "Elemente ausschließen (Regex)", "full_name": "Vor- und Nachname", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index 36eb4ab48..da97bebde 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -58,6 +58,7 @@ "domain": "Domain", "domain_matches_hostname": "Domain %s matches hostname", "domain_quota_m": "Total domain quota (MiB)", + "dry": "Simulate synchronization", "enc_method": "Encryption method", "exclude": "Exclude objects (regex)", "full_name": "Full name", diff --git a/data/web/templates/edit/syncjob.twig b/data/web/templates/edit/syncjob.twig index 6f6cdedac..801009849 100644 --- a/data/web/templates/edit/syncjob.twig +++ b/data/web/templates/edit/syncjob.twig @@ -11,6 +11,7 @@ +
    @@ -95,7 +96,7 @@
    - + {{ lang.add.custom_params_hint }}
    @@ -141,6 +142,13 @@
    +
    +
    +
    + +
    +
    +
    diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 1f96851fc..22807c8d3 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -955,7 +955,7 @@
    - + {{ lang.add.custom_params_hint }}
    @@ -994,13 +994,20 @@
    -
    +
    +
    +
    +
    + +
    +
    +
    diff --git a/data/web/templates/modals/user.twig b/data/web/templates/modals/user.twig index 96051841b..b4188773c 100644 --- a/data/web/templates/modals/user.twig +++ b/data/web/templates/modals/user.twig @@ -167,6 +167,13 @@
    +
    +
    +
    + +
    +
    +
    diff --git a/docker-compose.yml b/docker-compose.yml index cdc686fb5..d942fad70 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -218,7 +218,7 @@ services: - sogo dovecot-mailcow: - image: mailcow/dovecot:1.25 + image: mailcow/dovecot:1.26 depends_on: - mysql-mailcow dns: From 63df547306f2e7a22e30cbfc77adb5c2c5d312f1 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 15 Nov 2023 16:45:27 +0100 Subject: [PATCH 143/174] Tweaked German Translation --- 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 5811e150c..75c66af61 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -58,7 +58,7 @@ "domain": "Domain", "domain_matches_hostname": "Domain %s darf nicht dem Hostnamen entsprechen", "domain_quota_m": "Domain-Speicherplatz gesamt (MiB)", - "dry": "Simuliere Synchronisation (Probedurchlauf)", + "dry": "Synchronisation simulieren", "enc_method": "Verschlüsselung", "exclude": "Elemente ausschließen (Regex)", "full_name": "Vor- und Nachname", From 0aa520c03031e3ec16a50a4e3dccecb6fb89c851 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 09:29:15 +0000 Subject: [PATCH 144/174] Update actions/cache action to v3 Signed-off-by: milkmaker --- .../directorytree/ldaprecord/.github/workflows/run-tests.yml | 4 ++-- .../lib/vendor/twig/twig/.github/workflows/documentation.yml | 2 +- 2 files changed, 3 insertions(+), 3 deletions(-) diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml index 8c7b5314c..cc4f4ddb5 100644 --- a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml +++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml @@ -22,7 +22,7 @@ jobs: uses: actions/checkout@v2 - name: Cache dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.composer/cache/files key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} @@ -55,7 +55,7 @@ jobs: uses: actions/checkout@v2 - name: Cache dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ~/.composer/cache/files key: dependencies-php-${{ matrix.php }}-composer-${{ hashFiles('composer.json') }} diff --git a/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml b/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml index ee83b5887..907befc6b 100644 --- a/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml +++ b/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml @@ -33,7 +33,7 @@ jobs: run: echo "::set-output name=dir::$(composer config cache-files-dir)" - name: Cache dependencies - uses: actions/cache@v2 + uses: actions/cache@v3 with: path: ${{ steps.composercache.outputs.dir }} key: ${{ runner.os }}-composer-${{ hashFiles('**/composer.lock') }} From 7c5248388755273dc803494219cf18eeea0f8158 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Thu, 16 Nov 2023 09:29:22 +0000 Subject: [PATCH 145/174] Update actions/checkout action to v4 Signed-off-by: milkmaker --- .../ldaprecord/.github/workflows/run-tests.yml | 4 ++-- .../php-mime-mail-parser/.github/workflows/main.yml | 6 +++--- .../robthree/twofactorauth/.github/workflows/test.yml | 2 +- .../tightenco/collect/.github/workflows/run-tests.yml | 2 +- data/web/inc/lib/vendor/twig/twig/.github/workflows/ci.yml | 4 ++-- .../vendor/twig/twig/.github/workflows/documentation.yml | 4 ++-- 6 files changed, 11 insertions(+), 11 deletions(-) diff --git a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml index 8c7b5314c..5075f25a6 100644 --- a/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml +++ b/data/web/inc/lib/vendor/directorytree/ldaprecord/.github/workflows/run-tests.yml @@ -19,7 +19,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Cache dependencies uses: actions/cache@v2 @@ -52,7 +52,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: Cache dependencies uses: actions/cache@v2 diff --git a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml index 34c8210fe..7931d00bc 100644 --- a/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml +++ b/data/web/inc/lib/vendor/php-mime-mail-parser/php-mime-mail-parser/.github/workflows/main.yml @@ -12,7 +12,7 @@ jobs: dependency-version: [prefer-lowest, prefer-stable] steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 @@ -31,7 +31,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Install dependencies run: composer update --no-progress --ignore-platform-reqs @@ -43,7 +43,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml b/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml index 8b31e2363..ba08ef230 100644 --- a/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml +++ b/data/web/inc/lib/vendor/robthree/twofactorauth/.github/workflows/test.yml @@ -13,7 +13,7 @@ jobs: php-version: ['5.6', '7.0', '7.1', '7.2', '7.3', '7.4', '8.0'] steps: - - uses: actions/checkout@v2 + - uses: actions/checkout@v4 - uses: shivammathur/setup-php@v2 with: diff --git a/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml b/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml index 2a0d42f9a..c9325213f 100644 --- a/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml +++ b/data/web/inc/lib/vendor/tightenco/collect/.github/workflows/run-tests.yml @@ -25,7 +25,7 @@ jobs: steps: - name: Checkout code - uses: actions/checkout@v1 + uses: actions/checkout@v4 - name: Setup PHP uses: shivammathur/setup-php@v2 diff --git a/data/web/inc/lib/vendor/twig/twig/.github/workflows/ci.yml b/data/web/inc/lib/vendor/twig/twig/.github/workflows/ci.yml index 50f23f9a4..65c2c4077 100644 --- a/data/web/inc/lib/vendor/twig/twig/.github/workflows/ci.yml +++ b/data/web/inc/lib/vendor/twig/twig/.github/workflows/ci.yml @@ -32,7 +32,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "Install PHP with extensions" uses: shivammathur/setup-php@v2 @@ -86,7 +86,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "Install PHP with extensions" uses: shivammathur/setup-php@v2 diff --git a/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml b/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml index ee83b5887..b8bf8e585 100644 --- a/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml +++ b/data/web/inc/lib/vendor/twig/twig/.github/workflows/documentation.yml @@ -18,7 +18,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "Set-up PHP" uses: shivammathur/setup-php@v2 @@ -54,7 +54,7 @@ jobs: steps: - name: "Checkout code" - uses: actions/checkout@v2 + uses: actions/checkout@v4 - name: "Run DOCtor-RST" uses: docker://oskarstark/doctor-rst From 85641794c3f1ff6889b174fddaf373c6b2eef145 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 16 Nov 2023 11:18:50 +0100 Subject: [PATCH 146/174] Added f1f2 + sorted whitelist for imapsync --- data/web/inc/vars.inc.php | 179 +++++++++++++++++++------------------- 1 file changed, 90 insertions(+), 89 deletions(-) diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 1110319dd..5578dfd3c 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -236,119 +236,120 @@ $RSPAMD_MAPS = array( $IMAPSYNC_OPTIONS = array( 'whitelist' => array( + 'abort', + 'authmd51', + 'authmd52', 'authmech1', 'authmech2', 'authuser1', 'authuser2', - 'debugcontent', - 'disarmreadreceipts', - 'dry', - 'logdir', - 'debugcrossduplicates', - 'maxsize', - 'minsize', - 'minage', - 'search', - 'noabletosearch', - 'pidfile', - 'pidfilelocking', - 'search1', - 'search2', - 'sslargs1', - 'sslargs2', - 'syncduplicates', - 'usecache', - 'synclabels', - 'truncmess', - 'domino2', - 'expunge1', - 'filterbuggyflags', - 'justconnect', - 'justfolders', - 'maxlinelength', - 'useheader', - 'noabletosearch1', - 'nolog', - 'prefix1', - 'prefix2', - 'sep1', - 'sep2', - 'nofoldersizesatend', - 'justfoldersizes', - 'proxyauth1', - 'skipemptyfolders', - 'include', - 'subfolder1', - 'subscribed', - 'subscribe', 'debug', + 'debugcontent', + 'debugcrossduplicates', + 'debugflags', + 'debugfolders', + 'debugimap', + 'debugimap1', 'debugimap2', + 'debugmemory', + 'debugssl', + 'delete1emptyfolders', + 'delete2folders', + 'disarmreadreceipts', + 'domain1', + 'domain2', 'domino1', + 'domino2', + 'dry', + 'errorsmax', 'exchange1', 'exchange2', + 'exitwhenover', + 'expunge1', + 'f1f2', + 'filterbuggyflags', + 'folder', + 'folderfirst', + 'folderlast', + 'folderrec', + 'gmail1', + 'gmail2', + 'idatefromheader', + 'include', + 'inet4', + 'inet6', + 'justconnect', + 'justfolders', + 'justfoldersizes', 'justlogin', 'keepalive1', 'keepalive2', + 'log', + 'logdir', + 'logfile', + 'maxbytesafter', + 'maxlinelength', + 'maxmessagespersecond', + 'maxsize', + 'maxsleep', + 'minage', + 'minsize', + 'noabletosearch', + 'noabletosearch1', 'noabletosearch2', + 'noexpunge1', 'noexpunge2', + 'nofoldersizesatend', + 'noid', + 'nolog', + 'nomixfolders', 'noresyncflags', 'nossl1', - 'nouidexpunge2', - 'syncinternaldates', - 'idatefromheader', - 'useuid', - 'debugflags', - 'debugimap', - 'delete1emptyfolders', - 'delete2folders', - 'gmail2', - 'office1', - 'testslive6', - 'debugimap1', - 'errorsmax', - 'tests', - 'gmail1', - 'maxmessagespersecond', - 'maxbytesafter', - 'maxsleep', - 'abort', - 'resyncflags', - 'resynclabels', - 'syncacls', + 'nossl2', 'nosyncacls', + 'notls1', + 'notls2', + 'nouidexpunge2', 'nousecache', - 'office2', - 'testslive', - 'debugmemory', - 'exitwhenover', - 'noid', - 'noexpunge1', - 'authmd51', - 'logfile', - 'proxyauth2', - 'domain1', - 'domain2', 'oauthaccesstoken1', 'oauthaccesstoken2', 'oauthdirect1', 'oauthdirect2', - 'folder', - 'folderrec', - 'folderfirst', - 'folderlast', - 'nomixfolders', - 'authmd52', - 'debugfolders', - 'nossl2', + 'office1', + 'office2', + 'pidfile', + 'pidfilelocking', + 'prefix1', + 'prefix2', + 'proxyauth1', + 'proxyauth2', + 'resyncflags', + 'resynclabels', + 'search', + 'search1', + 'search2', + 'sep1', + 'sep2', + 'showpasswords', + 'skipemptyfolders', 'ssl2', + 'sslargs1', + 'sslargs2', + 'subfolder1', + 'subscribe', + 'subscribed', + 'syncacls', + 'syncduplicates', + 'syncinternaldates', + 'synclabels', + 'tests', + 'testslive', + 'testslive6', 'tls2', - 'notls2', - 'debugssl', - 'notls1', - 'inet4', - 'inet6', - 'log', - 'showpasswords' + 'truncmess', + 'usecache', + 'useheader', + 'useuid' ), 'blacklist' => array( 'skipmess', From b5c3d01834052e2a5efc431ff80e3a625c520913 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Thu, 16 Nov 2023 17:07:33 +0100 Subject: [PATCH 147/174] Translations update from Weblate (#5538) * [Web] Updated lang.cs-cz.json Co-authored-by: Peter Co-authored-by: milkmaker * [Web] Updated lang.fr-fr.json Co-authored-by: Quiwy Co-authored-by: milkmaker --------- Co-authored-by: Peter Co-authored-by: Quiwy --- data/web/lang/lang.cs-cz.json | 6 ++---- data/web/lang/lang.fr-fr.json | 6 +++++- 2 files changed, 7 insertions(+), 5 deletions(-) diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index d14bab1d5..1a5213b9e 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -209,7 +209,7 @@ "include_exclude_info": "Ve výchozím nastavení (bez výběru), jsou adresovány všechny mailové schránky", "includes": "Zahrnout tyto přijemce", "ip_check": "Kontrola IP", - "ip_check_disabled": "Kontrola IP je zakázána. Můžete ji povolit v nabídce
    Systém > Nastavení > Možnosti > Přizpůsobení.", + "ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v
    System > Nastavení > Options > Přizpůsobení", "ip_check_opt_in": "Přihlásit se k používání služby třetí strany ipv4.mailcow.email a ipv6.mailcow.email pro zjištění externích IP adres.", "is_mx_based": "Na základě MX", "last_applied": "Naposledy použité", @@ -343,9 +343,7 @@ "verify": "Ověřit", "yes": "✓", "f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem", - "f2b_max_ban_time": "Maximální délka banu (s)", - "ip_check": "Kontrola IP", - "ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v
    System > Nastavení > Options > Přizpůsobení" + "f2b_max_ban_time": "Maximální délka banu (s)" }, "danger": { "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři", diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 6c93f4ddb..96e1aef7d 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -326,7 +326,11 @@ "password_policy_lowerupper": "Doit contenir des caractères minuscules et majuscules", "password_policy_numbers": "Doit contenir au moins un chiffre", "ip_check": "Vérification IP", - "ip_check_disabled": "La vérification IP est désactivée. Vous pouvez l'activer sous
    Système > Configuration > Options > Personnaliser" + "ip_check_disabled": "La vérification IP est désactivée. Vous pouvez l'activer sous
    Système > Configuration > Options > Personnaliser", + "logo_normal_label": "Normal", + "logo_dark_label": "Inversé pour le mode sombre", + "allowed_methods": "Access-Control-Allow-Methods", + "allowed_origins": "Access-Control-Allow-Origin" }, "danger": { "access_denied": "Accès refusé ou données de formulaire non valides", From 03311b06c92a590859b93f37e444467cfc3151c9 Mon Sep 17 00:00:00 2001 From: Peter Date: Sat, 18 Nov 2023 11:40:57 +0100 Subject: [PATCH 148/174] Ignore everything in vendor subdirs --- .github/renovate.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/renovate.json b/.github/renovate.json index e2de9e5cf..62cbf93fd 100644 --- a/.github/renovate.json +++ b/.github/renovate.json @@ -12,7 +12,7 @@ "baseBranches": ["staging"], "enabledManagers": ["github-actions", "regex", "docker-compose"], "ignorePaths": [ - "data\/web\/inc\/lib\/vendor\/matthiasmullie\/minify\/**" + "data\/web\/inc\/lib\/vendor\/**" ], "regexManagers": [ { From 8ba1e1ba9e4bd18fd7044714799b645569eb429c Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Mon, 20 Nov 2023 12:38:37 +0100 Subject: [PATCH 149/174] [Rspamd] workaround - remove "--\x0D\x0A" prefix from rewritten cts --- data/conf/rspamd/lua/rspamd.local.lua | 22 +++++++++++++--------- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index acc40559e..c255ea8a0 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -631,15 +631,19 @@ rspamd_config:register_symbol({ end local out_parts = {} for _,o in ipairs(out) do - if type(o) ~= 'table' then - out_parts[#out_parts + 1] = o - out_parts[#out_parts + 1] = newline_s - else - out_parts[#out_parts + 1] = o[1] - if o[2] then - out_parts[#out_parts + 1] = newline_s - end - end + if type(o) ~= 'table' then + out_parts[#out_parts + 1] = o + out_parts[#out_parts + 1] = newline_s + else + local removePrefix = "--\x0D\x0AContent-Type" + if string.lower(string.sub(tostring(o[1]), 1, string.len(removePrefix))) == string.lower(removePrefix) then + o[1] = string.sub(tostring(o[1]), string.len("--\x0D\x0A") + 1) + end + out_parts[#out_parts + 1] = o[1] + if o[2] then + out_parts[#out_parts + 1] = newline_s + end + end end task:set_message(out_parts) else From f423ad77f3c33f60eaf0bd58b6634b062460696f Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 21 Nov 2023 08:49:18 +0100 Subject: [PATCH 150/174] [Web] escape quarantine html --- data/web/js/site/quarantine.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/data/web/js/site/quarantine.js b/data/web/js/site/quarantine.js index 8d7f22255..fbf4fe862 100644 --- a/data/web/js/site/quarantine.js +++ b/data/web/js/site/quarantine.js @@ -220,7 +220,7 @@ jQuery(function($){ if (value.score > 0) highlightClass = 'negative'; else if (value.score < 0) highlightClass = 'positive'; else highlightClass = 'neutral'; - $('#qid_detail_symbols').append('' + value.name + ' (' + value.score + ')'); + $('#qid_detail_symbols').append('' + value.name + ' (' + value.score + ')'); }); $('[data-bs-toggle="tooltip"]').tooltip(); } @@ -295,3 +295,7 @@ jQuery(function($){ $(".table_collapse_option").hide(); } }); + + + + From 392967d6647da44db6fd7f8111d3c98f7032e6bc Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Tue, 21 Nov 2023 10:19:00 +0100 Subject: [PATCH 151/174] [Rspamd] domain wide footer check for empty strings --- data/conf/rspamd/lua/rspamd.local.lua | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index c255ea8a0..459b23398 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -564,7 +564,7 @@ rspamd_config:register_symbol({ else local footer = parser:get_object() - if footer and type(footer) == "table" and (footer.html or footer.plain) then + if footer and type(footer) == "table" and (footer.html and footer.html ~= "" or footer.plain and footer.plain ~= "") then rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain) local envfrom_mime = task:get_from(2) From 5a10f2dd7c14f1f08b12a220d8fb2f8430541889 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 21 Nov 2023 15:37:53 +0100 Subject: [PATCH 152/174] Fix repo change when running in forced mode --- update.sh | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/update.sh b/update.sh index 8ecd3f144..419f85f4e 100755 --- a/update.sh +++ b/update.sh @@ -891,9 +891,14 @@ if [ "$CURRENT_REPO" != "$DEFAULT_REPO" ]; then echo "The Repository currently used is not the default Mailcow Repository." echo "Currently Repository: $CURRENT_REPO" echo "Default Repository: $DEFAULT_REPO" - read -r -p "Should it be changed back to default? [y/N] " repo_response - if [[ "$repo_response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then - git remote set-url origin $DEFAULT_REPO + if [ ! $FORCE ]; then + read -r -p "Should it be changed back to default? [y/N] " repo_response + if [[ "$repo_response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + git remote set-url origin $DEFAULT_REPO + fi + else + echo "Running in forced mode... setting Repo to default!" + git remote set-url origin $DEFAULT_REPO fi fi From d2e38678936158637fae1f9518248cc10099bf7f Mon Sep 17 00:00:00 2001 From: FreddleSpl0it Date: Thu, 23 Nov 2023 16:12:43 +0100 Subject: [PATCH 153/174] [Web][Rspamd] implement custom mailbox attributes and improve domain wide footer --- data/Dockerfiles/rspamd/docker-entrypoint.sh | 3 + data/conf/rspamd/dynmaps/footer.php | 89 ++++++++++ data/conf/rspamd/lua/rspamd.local.lua | 53 +++--- data/web/api/openapi.yaml | 161 +++++++++++++++++ data/web/edit.php | 3 + data/web/inc/functions.mailbox.inc.php | 178 +++++++++++++++---- data/web/inc/init_db.inc.php | 17 +- data/web/js/site/edit.js | 17 ++ data/web/json_api.php | 8 +- data/web/lang/lang.de-de.json | 4 + data/web/lang/lang.en-gb.json | 7 +- data/web/templates/edit.twig | 1 + data/web/templates/edit/domain.twig | 26 ++- data/web/templates/edit/mailbox.twig | 32 ++++ 14 files changed, 530 insertions(+), 69 deletions(-) create mode 100644 data/conf/rspamd/dynmaps/footer.php diff --git a/data/Dockerfiles/rspamd/docker-entrypoint.sh b/data/Dockerfiles/rspamd/docker-entrypoint.sh index e6d329b5c..8af7619c2 100755 --- a/data/Dockerfiles/rspamd/docker-entrypoint.sh +++ b/data/Dockerfiles/rspamd/docker-entrypoint.sh @@ -79,6 +79,9 @@ EOF redis-cli -h redis-mailcow SLAVEOF NO ONE fi +# Provide additional lua modules +ln -s /usr/lib/$(uname -m)-linux-gnu/liblua5.1-cjson.so.0.0.0 /usr/lib/rspamd/cjson.so + chown -R _rspamd:_rspamd /var/lib/rspamd \ /etc/rspamd/local.d \ /etc/rspamd/override.d \ diff --git a/data/conf/rspamd/dynmaps/footer.php b/data/conf/rspamd/dynmaps/footer.php new file mode 100644 index 000000000..ca18697ac --- /dev/null +++ b/data/conf/rspamd/dynmaps/footer.php @@ -0,0 +1,89 @@ + PDO::ERRMODE_EXCEPTION, + PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, + PDO::ATTR_EMULATE_PREPARES => false, +]; +try { + $pdo = new PDO($dsn, $database_user, $database_pass, $opt); +} +catch (PDOException $e) { + error_log("FOOTER: " . $e . PHP_EOL); + http_response_code(501); + exit; +} + +if (!function_exists('getallheaders')) { + function getallheaders() { + if (!is_array($_SERVER)) { + return array(); + } + $headers = array(); + foreach ($_SERVER as $name => $value) { + if (substr($name, 0, 5) == 'HTTP_') { + $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; + } + } + return $headers; + } +} + +// Read headers +$headers = getallheaders(); +// Get Domain +$domain = $headers['Domain']; +// Get Username +$username = $headers['Username']; +// define empty footer +$empty_footer = json_encode(array( + 'html' => '', + 'plain' => '', + 'vars' => array() +)); + +error_log("FOOTER: checking for domain " . $domain . " and user " . $username . PHP_EOL); + +try { + $stmt = $pdo->prepare("SELECT `plain`, `html`, `mbox_exclude` FROM `domain_wide_footer` + WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain + )); + $footer = $stmt->fetch(PDO::FETCH_ASSOC); + if (in_array($username, json_decode($footer['mbox_exclude']))){ + $footer = false; + } + if (empty($footer)){ + echo $empty_footer; + exit; + } + error_log("FOOTER: " . json_encode($footer) . PHP_EOL); + + $stmt = $pdo->prepare("SELECT `custom_attributes` FROM `mailbox` WHERE `username` = :username"); + $stmt->execute(array( + ':username' => $username + )); + $custom_attributes = $stmt->fetch(PDO::FETCH_ASSOC)['custom_attributes']; + if (empty($custom_attributes)){ + $custom_attributes = (object)array(); + } +} +catch (Exception $e) { + error_log("FOOTER: " . $e->getMessage() . PHP_EOL); + http_response_code(502); + exit; +} + + +// return footer +$footer["vars"] = $custom_attributes; +echo json_encode($footer); diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 459b23398..44be2e340 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -527,12 +527,11 @@ rspamd_config:register_symbol({ name = 'MOO_FOOTER', type = 'prefilter', callback = function(task) + local cjson = require "cjson" local lua_mime = require "lua_mime" local lua_util = require "lua_util" local rspamd_logger = require "rspamd_logger" - local rspamd_redis = require "rspamd_redis" - local ucl = require "ucl" - local redis_params = rspamd_parse_redis_server('footer') + local rspamd_http = require "rspamd_http" local envfrom = task:get_from(1) local uname = task:get_user() if not envfrom or not uname then @@ -541,6 +540,7 @@ rspamd_config:register_symbol({ local uname = uname:lower() local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case + -- determine newline type local function newline(task) local t = task:get_newlines_type() @@ -552,20 +552,19 @@ rspamd_config:register_symbol({ return '\r\n' end - local function redis_cb_footer(err, data) + -- retrieve footer + local function footer_cb(err_message, code, data, headers) if err or type(data) ~= 'string' then rspamd_logger.infox(rspamd_config, "domain wide footer request for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err) else + -- parse json string - local parser = ucl.parser() - local res,err = parser:parse_string(data) - if not res then + local footer = cjson.decode(data) + if not footer then rspamd_logger.infox(rspamd_config, "parsing domain wide footer for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err) else - local footer = parser:get_object() - if footer and type(footer) == "table" and (footer.html and footer.html ~= "" or footer.plain and footer.plain ~= "") then - rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s", uname, footer.html, footer.plain) + rspamd_logger.infox(rspamd_config, "found domain wide footer for user %s: html=%s, plain=%s, vars=%s", uname, footer.html, footer.plain, footer.vars) local envfrom_mime = task:get_from(2) local from_name = "" @@ -575,6 +574,7 @@ rspamd_config:register_symbol({ from_name = envfrom[1].name end + -- default replacements local replacements = { auth_user = uname, from_user = envfrom[1].user, @@ -582,10 +582,20 @@ rspamd_config:register_symbol({ from_addr = envfrom[1].addr, from_domain = envfrom[1].domain:lower() } - if footer.html then + -- add custom mailbox attributes + if footer.vars and type(footer.vars) == "string" then + local footer_vars = cjson.decode(footer.vars) + + if type(footer_vars) == "table" then + for key, value in pairs(footer_vars) do + replacements[key] = value + end + end + end + if footer.html and footer.html ~= "" then footer.html = lua_util.jinja_template(footer.html, replacements, true) end - if footer.plain then + if footer.plain and footer.plain ~= "" then footer.plain = lua_util.jinja_template(footer.plain, replacements, true) end @@ -653,17 +663,14 @@ rspamd_config:register_symbol({ end end - local redis_ret_footer = rspamd_redis_make_request(task, - redis_params, -- connect params - env_from_domain, -- hash key - false, -- is write - redis_cb_footer, --callback - 'HGET', -- command - {"DOMAIN_WIDE_FOOTER", env_from_domain} -- arguments - ) - if not redis_ret_footer then - rspamd_logger.infox(rspamd_config, "cannot make request to load footer for domain") - end + -- fetch footer + rspamd_http.request({ + task=task, + url='http://nginx:8081/footer.php', + body='', + callback=footer_cb, + headers={Domain=env_from_domain,Username=uname}, + }) return true end, diff --git a/data/web/api/openapi.yaml b/data/web/api/openapi.yaml index 1d2621689..a363dcbba 100644 --- a/data/web/api/openapi.yaml +++ b/data/web/api/openapi.yaml @@ -3137,6 +3137,86 @@ paths: type: string type: object summary: Update domain + /api/v1/edit/domain/footer: + post: + responses: + "401": + $ref: "#/components/responses/Unauthorized" + "200": + content: + application/json: + examples: + response: + value: + - log: + - mailbox + - edit + - domain_wide_footer + - domains: + - mailcow.tld + html: "
    foo {= foo =}" + plain: "- + You can update the footer of one or more domains per request. + operationId: Update domain wide footer + requestBody: + content: + application/json: + schema: + example: + attr: + html: "
    foo {= foo =}" + plain: "foo {= foo =}" + mbox_exclude: + - moo@mailcow.tld + items: mailcow.tld + properties: + attr: + properties: + html: + description: Footer text in HTML format + type: string + plain: + description: Footer text in PLAIN text format + type: string + mbox_exclude: + description: Array of mailboxes to exclude from domain wide footer + type: object + type: object + items: + description: contains a list of domain names where you want to update the footer + type: array + items: + type: string + type: object + summary: Update domain wide footer /api/v1/edit/fail2ban: post: responses: @@ -3336,6 +3416,86 @@ paths: type: object type: object summary: Update mailbox + /api/v1/edit/mailbox/custom-attribute: + post: + responses: + "401": + $ref: "#/components/responses/Unauthorized" + "200": + content: + application/json: + examples: + response: + value: + - log: + - mailbox + - edit + - mailbox_custom_attribute + - mailboxes: + - moo@mailcow.tld + attribute: + - role + - foo + value: + - cow + - bar + - null + msg: + - mailbox_modified + - moo@mailcow.tld + type: success + schema: + properties: + log: + description: contains request object + items: {} + type: array + msg: + items: {} + type: array + type: + enum: + - success + - danger + - error + type: string + type: object + description: OK + headers: {} + tags: + - Mailboxes + description: >- + You can update custom attributes of one or more mailboxes per request. + operationId: Update mailbox custom attributes + requestBody: + content: + application/json: + schema: + example: + attr: + attribute: + - role + - foo + value: + - cow + - bar + items: + - moo@mailcow.tld + properties: + attr: + properties: + attribute: + description: Array of attribute keys + type: object + value: + description: Array of attribute values + type: object + type: object + items: + description: contains list of mailboxes you want update + type: object + type: object + summary: Update mailbox custom attributes /api/v1/edit/mailq: post: responses: @@ -5581,6 +5741,7 @@ paths: sogo_access: "1" tls_enforce_in: "0" tls_enforce_out: "0" + custom_attributes: {} domain: domain3.tld is_relayed: 0 local_part: info diff --git a/data/web/edit.php b/data/web/edit.php index 8061441b8..83ae1467e 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -58,6 +58,8 @@ if (isset($_SESSION['mailcow_cc_role'])) { 'dkim' => dkim('details', $domain), 'domain_details' => $result, 'domain_footer' => $domain_footer, + 'mailboxes' => mailbox('get', 'mailboxes', $_GET["domain"]), + 'aliases' => mailbox('get', 'aliases', $_GET["domain"], 'address') ]; } } @@ -218,6 +220,7 @@ $js_minifier->add('/web/js/site/pwgen.js'); $template_data['result'] = $result; $template_data['return_to'] = $_SESSION['return_to']; $template_data['lang_user'] = json_encode($lang['user']); +$template_data['lang_admin'] = json_encode($lang['admin']); $template_data['lang_datatables'] = json_encode($lang['datatables']); require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php'; diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 298f607dc..7c2955f6d 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -3264,6 +3264,62 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); return true; break; + case 'mailbox_custom_attribute': + $_data['attribute'] = isset($_data['attribute']) ? $_data['attribute'] : array(); + $_data['attribute'] = is_array($_data['attribute']) ? $_data['attribute'] : array($_data['attribute']); + $_data['attribute'] = array_map(function($value) { return str_replace(' ', '', $value); }, $_data['attribute']); + $_data['value'] = isset($_data['value']) ? $_data['value'] : array(); + $_data['value'] = is_array($_data['value']) ? $_data['value'] : array($_data['value']); + $attributes = (object)array_combine($_data['attribute'], $_data['value']); + $mailboxes = is_array($_data['mailboxes']) ? $_data['mailboxes'] : array($_data['mailboxes']); + + foreach ($mailboxes as $mailbox) { + if (!filter_var($mailbox, FILTER_VALIDATE_EMAIL)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('username_invalid', $mailbox) + ); + continue; + } + $is_now = mailbox('get', 'mailbox_details', $mailbox); + if(!empty($is_now)){ + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $is_now['domain'])) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + continue; + } + } + else { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + continue; + } + + + $stmt = $pdo->prepare("UPDATE `mailbox` + SET `custom_attributes` = :custom_attributes + WHERE username = :username"); + $stmt->execute(array( + ":username" => $mailbox, + ":custom_attributes" => json_encode($attributes) + )); + + $_SESSION['return'][] = array( + 'type' => 'success', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('mailbox_modified', $mailbox) + ); + } + + return true; + break; case 'resource': if (!is_array($_data['name'])) { $names = array(); @@ -3343,44 +3399,79 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); } break; - case 'domain_wide_footer': - $domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46); - if (!is_valid_domain_name($domain)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'domain_invalid' - ); - return false; + case 'domain_wide_footer': + if (!is_array($_data['domains'])) { + $domains = array(); + $domains[] = $_data['domains']; } - if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { - $_SESSION['return'][] = array( - 'type' => 'danger', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => 'access_denied' - ); - return false; + else { + $domains = $_data['domains']; } - $footers = array(); - $footers['html'] = isset($_data['footer_html']) ? $_data['footer_html'] : ''; - $footers['plain'] = isset($_data['footer_plain']) ? $_data['footer_plain'] : ''; - try { - $redis->hSet('DOMAIN_WIDE_FOOTER', $domain, json_encode($footers)); - } - catch (RedisException $e) { + foreach ($domains as $domain) { + $domain = idn_to_ascii(strtolower(trim($domain)), 0, INTL_IDNA_VARIANT_UTS46); + if (!is_valid_domain_name($domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'domain_invalid' + ); + return false; + } + if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => 'access_denied' + ); + return false; + } + + $footers = array(); + $footers['html'] = isset($_data['html']) ? $_data['html'] : ''; + $footers['plain'] = isset($_data['plain']) ? $_data['plain'] : ''; + $footers['mbox_exclude'] = array(); + if (isset($_data["mbox_exclude"])){ + if (!is_array($_data["mbox_exclude"])) { + $_data["mbox_exclude"] = array($_data["mbox_exclude"]); + } + foreach ($_data["mbox_exclude"] as $mailbox) { + if (!filter_var($mailbox, FILTER_VALIDATE_EMAIL)) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => array('username_invalid', $mailbox) + ); + } else { + array_push($footers['mbox_exclude'], $mailbox); + } + } + } + try { + $stmt = $pdo->prepare("DELETE FROM `domain_wide_footer` WHERE `domain`= :domain"); + $stmt->execute(array(':domain' => $domain)); + $stmt = $pdo->prepare("INSERT INTO `domain_wide_footer` (`domain`, `html`, `plain`, `mbox_exclude`) VALUES (:domain, :html, :plain, :mbox_exclude)"); + $stmt->execute(array( + ':domain' => $domain, + ':html' => $footers['html'], + ':plain' => $footers['plain'], + ':mbox_exclude' => json_encode($footers['mbox_exclude']), + )); + } + catch (PDOException $e) { + $_SESSION['return'][] = array( + 'type' => 'danger', + 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), + 'msg' => $e->getMessage() + ); + return false; + } $_SESSION['return'][] = array( - 'type' => 'danger', + 'type' => 'success', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) + 'msg' => array('domain_footer_modified', htmlspecialchars($domain)) ); - return false; } - $_SESSION['return'][] = array( - 'type' => 'success', - 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('domain_footer_modified', htmlspecialchars($domain)) - ); break; } break; @@ -3934,13 +4025,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) { return false; } - $stmt = $pdo->prepare("SELECT `id` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain"); + $stmt = $pdo->prepare("SELECT `id`, `address` FROM `alias` WHERE `address` != `goto` AND `domain` = :domain"); $stmt->execute(array( ':domain' => $_data, )); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC); while($row = array_shift($rows)) { - $aliases[] = $row['id']; + if ($_extra == "address"){ + $aliases[] = $row['address']; + } else { + $aliases[] = $row['id']; + } } return $aliases; break; @@ -4292,6 +4387,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { `mailbox`.`modified`, `quota2`.`bytes`, `attributes`, + `custom_attributes`, `quota2`.`messages` FROM `mailbox`, `quota2`, `domain` WHERE (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL) @@ -4312,6 +4408,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { `mailbox`.`modified`, `quota2replica`.`bytes`, `attributes`, + `custom_attributes`, `quota2replica`.`messages` FROM `mailbox`, `quota2replica`, `domain` WHERE (`mailbox`.`kind` = '' OR `mailbox`.`kind` = NULL) @@ -4334,6 +4431,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $mailboxdata['quota'] = $row['quota']; $mailboxdata['messages'] = $row['messages']; $mailboxdata['attributes'] = json_decode($row['attributes'], true); + $mailboxdata['custom_attributes'] = json_decode($row['custom_attributes'], true); $mailboxdata['quota_used'] = intval($row['bytes']); $mailboxdata['percent_in_use'] = ($row['quota'] == 0) ? '- ' : round((intval($row['bytes']) / intval($row['quota'])) * 100); $mailboxdata['created'] = $row['created']; @@ -4514,19 +4612,23 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { } try { - $footers = $redis->hGet('DOMAIN_WIDE_FOOTER', $domain); - $footers = json_decode($footers, true); + $stmt = $pdo->prepare("SELECT `html`, `plain`, `mbox_exclude` FROM `domain_wide_footer` + WHERE `domain` = :domain"); + $stmt->execute(array( + ':domain' => $domain + )); + $footer = $stmt->fetch(PDO::FETCH_ASSOC); } - catch (RedisException $e) { + catch (PDOException $e) { $_SESSION['return'][] = array( 'type' => 'danger', 'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr), - 'msg' => array('redis_error', $e) + 'msg' => $e->getMessage() ); return false; } - return $footers; + return $footer; break; } break; diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 2ce6a28c1..4ea79d9bb 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -3,7 +3,7 @@ function init_db_schema() { try { global $pdo; - $db_version = "15112023_1536"; + $db_version = "21112023_1644"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -267,6 +267,20 @@ function init_db_schema() { ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" ), + "domain_wide_footer" => array( + "cols" => array( + "domain" => "VARCHAR(255) NOT NULL", + "html" => "LONGTEXT", + "plain" => "LONGTEXT", + "mbox_exclude" => "JSON NOT NULL DEFAULT ('[]')", + ), + "keys" => array( + "primary" => array( + "" => array("domain") + ) + ), + "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" + ), "tags_domain" => array( "cols" => array( "tag_name" => "VARCHAR(255) NOT NULL", @@ -344,6 +358,7 @@ function init_db_schema() { "local_part" => "VARCHAR(255) NOT NULL", "domain" => "VARCHAR(255) NOT NULL", "attributes" => "JSON", + "custom_attributes" => "JSON NOT NULL DEFAULT ('{}')", "kind" => "VARCHAR(100) NOT NULL DEFAULT ''", "multiple_bookings" => "INT NOT NULL DEFAULT -1", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", diff --git a/data/web/js/site/edit.js b/data/web/js/site/edit.js index cd938cd84..d68954989 100644 --- a/data/web/js/site/edit.js +++ b/data/web/js/site/edit.js @@ -199,6 +199,23 @@ jQuery(function($){ }); } + function add_table_row(table_id, type) { + var row = $('
    '); + if (type == "mbox_attr") { + cols = ''; + cols += ''; + cols += ''; + } + row.append(cols); + table_id.append(row); + } + $('#mbox_attr_table').on('click', 'tr a', function (e) { + e.preventDefault(); + $(this).parents('tr').remove(); + }); + $('#add_mbox_attr_row').click(function() { + add_table_row($('#mbox_attr_table'), "mbox_attr"); + }); // detect element visibility changes function onVisible(element, callback) { diff --git a/data/web/json_api.php b/data/web/json_api.php index b375bc8e4..668be0d10 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -1867,8 +1867,6 @@ if (isset($_GET['query'])) { case "quota_notification_bcc": process_edit_return(quota_notification_bcc('edit', $attr)); break; - case "domain-wide-footer": - process_edit_return(mailbox('edit', 'domain_wide_footer', $attr)); break; case "mailq": process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr))); @@ -1881,6 +1879,9 @@ if (isset($_GET['query'])) { case "template": process_edit_return(mailbox('edit', 'mailbox_templates', array_merge(array('ids' => $items), $attr))); break; + case "custom-attribute": + process_edit_return(mailbox('edit', 'mailbox_custom_attribute', array_merge(array('mailboxes' => $items), $attr))); + break; default: process_edit_return(mailbox('edit', 'mailbox', array_merge(array('username' => $items), $attr))); break; @@ -1900,6 +1901,9 @@ if (isset($_GET['query'])) { case "template": process_edit_return(mailbox('edit', 'domain_templates', array_merge(array('ids' => $items), $attr))); break; + case "footer": + process_edit_return(mailbox('edit', 'domain_wide_footer', array_merge(array('domains' => $items), $attr))); + break; default: process_edit_return(mailbox('edit', 'domain', array_merge(array('domain' => $items), $attr))); break; diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index 75c66af61..5737a664c 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -574,6 +574,7 @@ "client_secret": "Client-Secret", "comment_info": "Ein privater Kommentar ist für den Benutzer nicht einsehbar. Ein öffentlicher Kommentar wird als Tooltip im Interface des Benutzers angezeigt.", "created_on": "Erstellt am", + "custom_attributes": "benutzerdefinierte Attribute", "delete1": "Lösche Nachricht nach Übertragung vom Quell-Server", "delete2": "Lösche Nachrichten von Ziel-Server, die nicht auf Quell-Server vorhanden sind", "delete2duplicates": "Lösche Duplikate im Ziel", @@ -614,6 +615,7 @@ "max_quota": "Max. Größe per Mailbox (MiB)", "maxage": "Maximales Alter in Tagen einer Nachricht, die kopiert werden soll
    (0 = alle Nachrichten kopieren)", "maxbytespersecond": "Max. Übertragungsrate in Bytes/s (0 für unlimitiert)", + "mbox_exclude": "Mailboxen ausschließen", "mbox_rl_info": "Dieses Limit wird auf den SASL Loginnamen angewendet und betrifft daher alle Absenderadressen, die der eingeloggte Benutzer verwendet. Bei Mailbox Ratelimit überwiegt ein Domain-weites Ratelimit.", "mins_interval": "Intervall (min)", "multiple_bookings": "Mehrfaches Buchen", @@ -1125,6 +1127,7 @@ "apple_connection_profile_complete": "Dieses Verbindungsprofil beinhaltet neben IMAP- und SMTP-Konfigurationen auch Pfade für die Konfiguration von CalDAV (Kalender) und CardDAV (Adressbücher) für ein Apple-Gerät.", "apple_connection_profile_mailonly": "Dieses Verbindungsprofil beinhaltet IMAP- und SMTP-Konfigurationen für ein Apple-Gerät.", "apple_connection_profile_with_app_password": "Es wird ein neues App-Passwort erzeugt und in das Profil eingefügt, damit bei der Einrichtung kein Passwort eingegeben werden muss. Geben Sie das Profil nicht weiter, da es einen vollständigen Zugriff auf Ihr Postfach ermöglicht.", + "attribute": "Attribut", "change_password": "Passwort ändern", "change_password_hint_app_passwords": "Ihre Mailbox hat %d App-Passwörter, die nicht geändert werden. Um diese zu verwalten, gehen Sie bitte zum App-Passwörter-Tab.", "clear_recent_successful_connections": "Alle erfolgreichen Verbindungen bereinigen", @@ -1244,6 +1247,7 @@ "tls_policy_warning": "Vorsicht: Entscheiden Sie sich unverschlüsselte Verbindungen abzulehnen, kann dies dazu führen, dass Kontakte Sie nicht mehr erreichen.
    Nachrichten, die die Richtlinie nicht erfüllen, werden durch einen Hard-Fail im Mailsystem abgewiesen.
    Diese Einstellung ist aktiv für die primäre Mailbox, für alle Alias-Adressen, die dieser Mailbox direkt zugeordnet sind (lediglich eine einzige Ziel-Adresse) und der Adressen, die sich aus Alias-Domains ergeben. Ausgeschlossen sind temporäre Aliasse (\"Spam-Alias-Adressen\"), Catch-All Alias-Adressen sowie Alias-Adressen mit mehreren Zielen.", "user_settings": "Benutzereinstellungen", "username": "Benutzername", + "value": "Wert", "verify": "Verifizieren", "waiting": "Warte auf Ausführung", "week": "Woche", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index da97bebde..723ed62e0 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -576,6 +576,7 @@ "client_secret": "Client secret", "comment_info": "A private comment is not visible to the user, while a public comment is shown as tooltip when hovering it in a user's overview", "created_on": "Created on", + "custom_attributes": "Custom attributes", "delete1": "Delete from source when completed", "delete2": "Delete messages on destination that are not on source", "delete2duplicates": "Delete duplicates on destination", @@ -592,7 +593,8 @@ "from_user": "{= from_user =} - From user part of envelope, e.g for \"moo@mailcow.tld\" it returns \"moo\"", "from_name": "{= from_name =} - From name of envelope, e.g for \"Mailcow <moo@mailcow.tld>\" it returns \"Mailcow\"", "from_addr": "{= from_addr =} - From address part of envelope", - "from_domain": "{= from_domain =} - From domain part of envelope" + "from_domain": "{= from_domain =} - From domain part of envelope", + "custom": "{= foo =} - If mailbox has the custom attribute \"foo\" with value \"bar\" it returns \"bar\"" }, "domain_footer_plain": "PLAIN footer", "domain_quota": "Domain quota", @@ -623,6 +625,7 @@ "max_quota": "Max. quota per mailbox (MiB)", "maxage": "Maximum age of messages in days that will be polled from remote
    (0 = ignore age)", "maxbytespersecond": "Max. bytes per second
    (0 = unlimited)", + "mbox_exclude": "Exclude mailboxes", "mbox_rl_info": "This rate limit is applied on the SASL login name, it matches any \"from\" address used by the logged-in user. A mailbox rate limit overrides a domain-wide rate limit.", "mins_interval": "Interval (min)", "multiple_bookings": "Multiple bookings", @@ -1141,6 +1144,7 @@ "apple_connection_profile_complete": "This connection profile includes IMAP and SMTP parameters as well as CalDAV (calendars) and CardDAV (contacts) paths for an Apple device.", "apple_connection_profile_mailonly": "This connection profile includes IMAP and SMTP configuration parameters for an Apple device.", "apple_connection_profile_with_app_password": "A new app password is generated and added to the profile so that no password needs to be entered when setting up your device. Please do not share the file as it grants full access to your mailbox.", + "attribute": "Attribute", "change_password": "Change password", "change_password_hint_app_passwords": "Your account has %d app passwords that will not be changed. To manage these, go to the App passwords tab.", "clear_recent_successful_connections": "Clear seen successful connections", @@ -1271,6 +1275,7 @@ "tls_policy_warning": "Warning: If you decide to enforce encrypted mail transfer, you may lose emails.
    Messages to not satisfy the policy will be bounced with a hard fail by the mail system.
    This option applies to your primary email address (login name), all addresses derived from alias domains as well as alias addresses with only this single mailbox as target.", "user_settings": "User settings", "username": "Username", + "value": "Value", "verify": "Verify", "waiting": "Waiting", "week": "week", diff --git a/data/web/templates/edit.twig b/data/web/templates/edit.twig index af83a31d4..375018c66 100644 --- a/data/web/templates/edit.twig +++ b/data/web/templates/edit.twig @@ -24,6 +24,7 @@
    ' + lang_admin.remove_row + '