diff --git a/.github/workflows/pr_to_nightly.yml b/.github/workflows/pr_to_nightly.yml index 0cf59eeac..51df14f6e 100644 --- a/.github/workflows/pr_to_nightly.yml +++ b/.github/workflows/pr_to_nightly.yml @@ -12,7 +12,7 @@ jobs: with: fetch-depth: 0 - name: Run the Action - uses: devops-infra/action-pull-request@v0.6.0 + uses: devops-infra/action-pull-request@v0.6.1 with: github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }} title: Automatic PR to nightly from ${{ github.event.repository.updated_at}} diff --git a/_modules/scripts/core.sh b/_modules/scripts/core.sh index fe51e33ff..ab67f25c6 100644 --- a/_modules/scripts/core.sh +++ b/_modules/scripts/core.sh @@ -124,7 +124,7 @@ prefetch_images() { } docker_garbage() { - SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" + SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )/../.." && pwd )" IMGS_TO_DELETE=() declare -A IMAGES_INFO @@ -185,6 +185,7 @@ detect_major_update() { MAJOR_VERSIONS=( "2025-02" "2025-03" + "2025-08" ) current_version="" diff --git a/_modules/scripts/ipv6_controller.sh b/_modules/scripts/ipv6_controller.sh index 308f953f3..de5272048 100644 --- a/_modules/scripts/ipv6_controller.sh +++ b/_modules/scripts/ipv6_controller.sh @@ -41,7 +41,7 @@ docker_daemon_edit(){ ! _has_kv ipv6 true && MISSING+=("ipv6: true") ! grep -Eq '"fixed-cidr-v6"\s*:\s*".+"' "$DOCKER_DAEMON_CONFIG" \ && MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"') - if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -ge 27 ]]; then + if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -le 27 ]]; then _has_kv ipv6 true && ! _has_kv ip6tables true && MISSING+=("ip6tables: true") ! _has_kv experimental true && MISSING+=("experimental: true") fi @@ -105,7 +105,7 @@ EOF } EOF fi - echo "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}" + echo -e "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}" echo "Restarting Docker..." (command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart echo "Docker restarted." diff --git a/_modules/scripts/new_options.sh b/_modules/scripts/new_options.sh index c4a01affb..941527092 100644 --- a/_modules/scripts/new_options.sh +++ b/_modules/scripts/new_options.sh @@ -49,7 +49,6 @@ adapt_new_options() { "DOVECOT_MASTER_PASS" "MAILCOW_PASS_SCHEME" "ADDITIONAL_SERVER_NAMES" - "ACME_CONTACT" "WATCHDOG_VERBOSE" "WEBAUTHN_ONLY_TRUSTED_VENDORS" "SPAMHAUS_DQS_KEY" @@ -95,7 +94,7 @@ adapt_new_options() { echo '# Max log lines per service to keep in Redis logs' >> mailcow.conf echo "LOG_LINES=9999" >> mailcow.conf ;; - + IPV4_NETWORK) echo '# Internal IPv4 /24 subnet, format n.n.n. (expands to n.n.n.0/24)' >> mailcow.conf echo "IPV4_NETWORK=172.22.1" >> mailcow.conf @@ -238,14 +237,6 @@ adapt_new_options() { echo '# Comma separated list without spaces! Example: ADDITIONAL_SERVER_NAMES=a.b.c,d.e.f' >> mailcow.conf echo 'ADDITIONAL_SERVER_NAMES=' >> mailcow.conf ;; - ACME_CONTACT) - 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 - 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 - ;; WEBAUTHN_ONLY_TRUSTED_VENDORS) echo "# WebAuthn device manufacturer verification" >> mailcow.conf echo '# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed' >> mailcow.conf @@ -285,7 +276,7 @@ adapt_new_options() { echo '# A COMPLETE DOCKER STACK REBUILD (compose down && compose up -d) IS NEEDED TO APPLY THIS.' >> mailcow.conf echo ENABLE_IPV6=${IPV6_BOOL} >> mailcow.conf ;; - + SKIP_CLAMD) echo '# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n' >> mailcow.conf echo 'SKIP_CLAMD=n' >> mailcow.conf @@ -295,11 +286,11 @@ adapt_new_options() { echo '# Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n' >> mailcow.conf echo 'SKIP_OLEFY=n' >> mailcow.conf ;; - + REDISPASS) echo "REDISPASS=$(LC_ALL=C /dev/null | head -c 28)" >> mailcow.conf ;; - + *) echo "${option}=" >> mailcow.conf ;; diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index 9e49d88cc..10e141ab8 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -3,7 +3,7 @@ FROM alpine:3.21 LABEL maintainer="The Infrastructure Company GmbH " # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?.*)$ -ARG GOSU_VERSION=1.16 +ARG GOSU_VERSION=1.17 ENV LANG=C.UTF-8 ENV LC_ALL=C.UTF-8 diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 824d4092f..a681c1fda 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -76,7 +76,7 @@ try: def notify_rcpt(rcpt, msg_count, quarantine_acl, category): if category == "add_header": category = "add header" - meta_query = query_mysql('SELECT SHA2(CONCAT(id, qid), 256) AS qhash, id, subject, score, sender, created, action FROM quarantine WHERE notified = 0 AND rcpt = "%s" AND score < %f AND (action = "%s" OR "all" = "%s")' % (rcpt, max_score, category, category)) + meta_query = query_mysql('SELECT `qhash`, id, subject, score, sender, created, action FROM quarantine WHERE notified = 0 AND rcpt = "%s" AND score < %f AND (action = "%s" OR "all" = "%s")' % (rcpt, max_score, category, category)) print("%s: %d of %d messages qualify for notification" % (rcpt, len(meta_query), msg_count)) if len(meta_query) == 0: return diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index ff333f5b3..e7b43790b 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -3,15 +3,15 @@ FROM php:8.2-fpm-alpine3.21 LABEL maintainer = "The Infrastructure Company GmbH " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$ -ARG APCU_PECL_VERSION=5.1.24 +ARG APCU_PECL_VERSION=5.1.26 # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?.*)$ ARG IMAGICK_PECL_VERSION=3.8.0 # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ ARG MAILPARSE_PECL_VERSION=3.1.8 # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?.*)$ -ARG MEMCACHED_PECL_VERSION=3.2.0 +ARG MEMCACHED_PECL_VERSION=3.3.0 # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?.*)$ -ARG REDIS_PECL_VERSION=6.1.0 +ARG REDIS_PECL_VERSION=6.2.0 # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?.*)$ ARG COMPOSER_VERSION=2.8.6 diff --git a/data/Dockerfiles/rspamd/Dockerfile b/data/Dockerfiles/rspamd/Dockerfile index 68b38d3a7..e46981aa4 100644 --- a/data/Dockerfiles/rspamd/Dockerfile +++ b/data/Dockerfiles/rspamd/Dockerfile @@ -2,7 +2,7 @@ FROM debian:bookworm-slim LABEL maintainer="The Infrastructure Company GmbH " ARG DEBIAN_FRONTEND=noninteractive -ARG RSPAMD_VER=rspamd_3.11.1-1~ab0b44951 +ARG RSPAMD_VER=rspamd_3.12.1-1~6dbfca2fa ARG CODENAME=bookworm ENV LC_ALL=C diff --git a/data/conf/rspamd/lua/rspamd.local.lua b/data/conf/rspamd/lua/rspamd.local.lua index 5f23ef6b8..5fe66f75f 100644 --- a/data/conf/rspamd/lua/rspamd.local.lua +++ b/data/conf/rspamd/lua/rspamd.local.lua @@ -102,7 +102,7 @@ rspamd_config:register_symbol({ local rcpt_split = rspamd_str_split(rcpt['addr'], '@') if #rcpt_split == 2 then if rcpt_split[1] == 'postmaster' then - task:set_pre_result('accept', 'whitelisting postmaster smtp rcpt') + task:set_pre_result('accept', 'whitelisting postmaster smtp rcpt', 'postmaster') return end end @@ -167,7 +167,7 @@ rspamd_config:register_symbol({ for k,v in pairs(data) do if (v and v ~= userdata and v == '1') then rspamd_logger.infox(rspamd_config, "found ip in keep_spam map, setting pre-result") - task:set_pre_result('accept', 'ip matched with forward hosts') + task:set_pre_result('accept', 'ip matched with forward hosts', 'keep_spam') end end end diff --git a/data/conf/rspamd/meta_exporter/pipe.php b/data/conf/rspamd/meta_exporter/pipe.php index 4d8e2a132..bd5d875bd 100644 --- a/data/conf/rspamd/meta_exporter/pipe.php +++ b/data/conf/rspamd/meta_exporter/pipe.php @@ -236,6 +236,9 @@ foreach ($rcpt_final_mailboxes as $rcpt_final) { ':action' => $action, ':fuzzy_hashes' => $fuzzy )); + $lastId = $pdo->lastInsertId(); + $stmt_update = $pdo->prepare("UPDATE `quarantine` SET `qhash` = SHA2(CONCAT(`id`, `qid`), 256) WHERE `id` = :id"); + $stmt_update->execute(array(':id' => $lastId)); $stmt = $pdo->prepare('DELETE FROM `quarantine` WHERE `rcpt` = :rcpt AND `id` NOT IN ( SELECT `id` FROM ( diff --git a/data/web/edit.php b/data/web/edit.php index 9a1e5a5c1..7ce4d0c6a 100644 --- a/data/web/edit.php +++ b/data/web/edit.php @@ -125,6 +125,7 @@ if (isset($_SESSION['mailcow_cc_role'])) { 'mailbox' => $mailbox, 'rl' => $rl, 'pushover_data' => $pushover_data, + 'get_tagging_options' => mailbox('get', 'delimiter_action', $mailbox), 'quarantine_notification' => $quarantine_notification, 'quarantine_category' => $quarantine_category, 'get_tls_policy' => $get_tls_policy, diff --git a/data/web/favicon.png b/data/web/favicon.png index 69eb2fcd1..541361359 100644 Binary files a/data/web/favicon.png and b/data/web/favicon.png differ diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index d5daeddcd..6ea4f5717 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -1223,6 +1223,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $stmt->execute(array( ':username' => $username )); + // save delimiter_action + if (isset($_data['tagged_mail_handler'])) { + mailbox('edit', 'delimiter_action', array( + 'username' => $username, + 'tagged_mail_handler' => $_data['tagged_mail_handler'] + )); + } + // save tags foreach($tags as $index => $tag){ if (empty($tag)) continue; @@ -1613,6 +1621,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $attr = array(); $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array(); + $attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler']); $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']); $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']); $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; @@ -3259,6 +3268,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); return false; } + // save delimiter_action + if (isset($_data['tagged_mail_handler'])) { + mailbox('edit', 'delimiter_action', array( + 'username' => $username, + 'tagged_mail_handler' => $_data['tagged_mail_handler'] + )); + } // save tags foreach($tags as $index => $tag){ if (empty($tag)) continue; @@ -3604,6 +3620,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $attr = array(); $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags']; + $attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : $is_now['tagged_mail_handler']; $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification']; $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category']; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame']; diff --git a/data/web/inc/functions.quarantine.inc.php b/data/web/inc/functions.quarantine.inc.php index 39606f271..5df86ef33 100644 --- a/data/web/inc/functions.quarantine.inc.php +++ b/data/web/inc/functions.quarantine.inc.php @@ -22,7 +22,7 @@ function quarantine($_action, $_data = null) { return false; } $stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt` - WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash + WHERE `qhash` = :hash AND user_acl.quarantine = 1 AND rcpt IN (SELECT username FROM mailbox)'); $stmt->execute(array(':hash' => $hash)); @@ -65,7 +65,7 @@ function quarantine($_action, $_data = null) { return false; } $stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt` - WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash + WHERE `qhash` = :hash AND `user_acl`.`quarantine` = 1 AND `username` IN (SELECT `username` FROM `mailbox`)'); $stmt->execute(array(':hash' => $hash)); @@ -833,7 +833,7 @@ function quarantine($_action, $_data = null) { ))); return false; } - $stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE SHA2(CONCAT(`id`, `qid`), 256) = :hash'); + $stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE `qhash` = :hash'); $stmt->execute(array(':hash' => $hash)); return $stmt->fetch(PDO::FETCH_ASSOC); break; diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index 767a0024e..6a9d042a9 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -4,7 +4,7 @@ function init_db_schema() try { global $pdo; - $db_version = "27012025_1555"; + $db_version = "06082025_1611"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -345,10 +345,14 @@ function init_db_schema() "notified" => "TINYINT(1) NOT NULL DEFAULT '0'", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "user" => "VARCHAR(255) NOT NULL DEFAULT 'unknown'", + "qhash" => "VARCHAR(64)", ), "keys" => array( "primary" => array( "" => array("id") + ), + "key" => array( + "qhash" => array("qhash") ) ), "attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC" @@ -1482,6 +1486,10 @@ function init_db_schema() 'msg' => 'db_init_complete' ); } + + // fill quarantine.qhash + $pdo->query("UPDATE `quarantine` SET `qhash` = SHA2(CONCAT(`id`, `qid`), 256) WHERE ISNULL(`qhash`)"); + } catch (PDOException $e) { if (php_sapi_name() == "cli") { echo "DB initialization failed: " . print_r($e, true) . PHP_EOL; diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index 671e20334..568105308 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -186,6 +186,12 @@ $MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false; // Enable SOGo access - Users will be redirected to SOGo after login (set to false to disable redirect by default) $MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true; +// How to handle tagged emails +// none - No special handling +// subfolder - Create subfolder under INBOX (e.g. "INBOX/Facebook") +// subject - Add tag to subject (e.g. "[Facebook] Subject") +$MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler'] = "none"; + // Send notification when quarantine is not empty (never, hourly, daily, weekly) $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'hourly'; @@ -257,57 +263,57 @@ $RSPAMD_MAPS = array( $IMAPSYNC_OPTIONS = array( 'whitelist' => array( - 'abort', - 'authmd51', - 'authmd52', + 'abort', + 'authmd51', + 'authmd52', 'authmech1', 'authmech2', - 'authuser1', - 'authuser2', - 'debug', - 'debugcontent', - 'debugcrossduplicates', - 'debugflags', - 'debugfolders', - 'debugimap', - 'debugimap1', - 'debugimap2', - 'debugmemory', - 'debugssl', + 'authuser1', + 'authuser2', + 'debug', + 'debugcontent', + 'debugcrossduplicates', + 'debugflags', + 'debugfolders', + 'debugimap', + 'debugimap1', + 'debugimap2', + 'debugmemory', + 'debugssl', 'delete1emptyfolders', - 'delete2folders', - 'disarmreadreceipts', + 'delete2folders', + 'disarmreadreceipts', 'domain1', 'domain2', - 'domino1', - 'domino2', + 'domino1', + 'domino2', 'dry', 'errorsmax', - 'exchange1', - 'exchange2', + 'exchange1', + 'exchange2', 'exitwhenover', 'expunge1', - 'f1f2', - 'filterbuggyflags', + 'f1f2', + 'filterbuggyflags', 'folder', 'folderfirst', 'folderlast', 'folderrec', - 'gmail1', - 'gmail2', - 'idatefromheader', + 'gmail1', + 'gmail2', + 'idatefromheader', 'include', 'inet4', 'inet6', - 'justconnect', - 'justfolders', - 'justfoldersizes', - 'justlogin', - 'keepalive1', - 'keepalive2', + 'justconnect', + 'justfolders', + 'justfoldersizes', + 'justlogin', + 'keepalive1', + 'keepalive2', 'log', 'logdir', - 'logfile', + 'logfile', 'maxbytesafter', 'maxlinelength', 'maxmessagespersecond', @@ -315,62 +321,62 @@ $IMAPSYNC_OPTIONS = array( 'maxsleep', 'minage', 'minsize', - 'noabletosearch', - 'noabletosearch1', - 'noabletosearch2', - 'noexpunge1', - 'noexpunge2', + 'noabletosearch', + 'noabletosearch1', + 'noabletosearch2', + 'noexpunge1', + 'noexpunge2', 'nofoldersizesatend', - 'noid', - 'nolog', - 'nomixfolders', - 'noresyncflags', - 'nossl1', - 'nossl2', - 'nosyncacls', - 'notls1', - 'notls2', - 'nouidexpunge2', - 'nousecache', + 'noid', + 'nolog', + 'nomixfolders', + 'noresyncflags', + 'nossl1', + 'nossl2', + 'nosyncacls', + 'notls1', + 'notls2', + 'nouidexpunge2', + 'nousecache', 'oauthaccesstoken1', 'oauthaccesstoken2', 'oauthdirect1', 'oauthdirect2', - 'office1', - 'office2', - 'pidfile', - 'pidfilelocking', + 'office1', + 'office2', + 'pidfile', + 'pidfilelocking', 'prefix1', 'prefix2', - 'proxyauth1', - 'proxyauth2', - 'resyncflags', - 'resynclabels', - 'search', + 'proxyauth1', + 'proxyauth2', + 'resyncflags', + 'resynclabels', + 'search', 'search1', - 'search2', + 'search2', 'sep1', 'sep2', 'showpasswords', 'skipemptyfolders', - 'ssl2', + 'ssl2', 'sslargs1', - 'sslargs2', + 'sslargs2', 'subfolder1', - 'subscribe', + 'subscribe', 'subscribed', 'syncacls', 'syncduplicates', 'syncinternaldates', - 'synclabels', - 'tests', - 'testslive', - 'testslive6', - 'tls2', - 'truncmess', - 'usecache', - 'useheader', - 'useuid' + 'synclabels', + 'tests', + 'testslive', + 'testslive6', + 'tls2', + 'truncmess', + 'usecache', + 'useheader', + 'useuid' ), 'blacklist' => array( 'skipmess', diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 28e6fd284..135ec764a 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -269,6 +269,24 @@ $(document).ready(function() { function setMailboxTemplateData(template){ $("#addInputQuota").val(template.quota / 1048576); + if (template.tagged_mail_handler === "subfolder"){ + $('#tagged_mail_handler_subfolder').prop('checked', true); + $('#tagged_mail_handler_subject').prop('checked', false); + $('#tagged_mail_handler_none').prop('checked', false); + } else if(template.tagged_mail_handler === "subject"){ + $('#tagged_mail_handler_subfolder').prop('checked', false); + $('#tagged_mail_handler_subject').prop('checked', true); + $('#tagged_mail_handler_none').prop('checked', false); + } else if(template.tagged_mail_handler === "none"){ + $('#tagged_mail_handler_subfolder').prop('checked', false); + $('#tagged_mail_handler_subject').prop('checked', false); + $('#tagged_mail_handler_none').prop('checked', true); + } else { + $('#tagged_mail_handler_subfolder').prop('checked', false); + $('#tagged_mail_handler_subject').prop('checked', false); + $('#tagged_mail_handler_none').prop('checked', true); + } + if (template.quarantine_notification === "never"){ $('#quarantine_notification_never').prop('checked', true); $('#quarantine_notification_hourly').prop('checked', false); diff --git a/data/web/templates/edit/mailbox-templates.twig b/data/web/templates/edit/mailbox-templates.twig index 6d150b263..65a83cd2a 100644 --- a/data/web/templates/edit/mailbox-templates.twig +++ b/data/web/templates/edit/mailbox-templates.twig @@ -36,6 +36,23 @@ 0 = ∞ +
+ +
+
+ + + + + + + + +
+

{{ lang.user.tag_help_explain|raw }}

+

{{ lang.user.tag_help_example|raw }}

+
+
diff --git a/data/web/templates/edit/mailbox.twig b/data/web/templates/edit/mailbox.twig index 32a3706c1..12c1f3b93 100644 --- a/data/web/templates/edit/mailbox.twig +++ b/data/web/templates/edit/mailbox.twig @@ -117,7 +117,7 @@
- {% for rlyhost in rlyhosts %}
+
+
+ +
+
+ + + +
+

{{ lang.user.tag_help_explain|raw }}

+

{{ lang.user.tag_help_example|raw }}

diff --git a/data/web/templates/modals/mailbox.twig b/data/web/templates/modals/mailbox.twig index 85091da41..0c164332b 100644 --- a/data/web/templates/modals/mailbox.twig +++ b/data/web/templates/modals/mailbox.twig @@ -76,6 +76,23 @@
+
+ +
+
+ + + + + + + + +
+

{{ lang.user.tag_help_explain|raw }}

+

{{ lang.user.tag_help_example|raw }}

+
+
@@ -246,6 +263,23 @@ 0 = ∞
+
+ +
+
+ + + + + + + + +
+

{{ lang.user.tag_help_explain|raw }}

+

{{ lang.user.tag_help_example|raw }}

+
+
diff --git a/docker-compose.yml b/docker-compose.yml index 550ad5997..909f9f2b7 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -84,7 +84,7 @@ services: - clamd rspamd-mailcow: - image: ghcr.io/mailcow/rspamd:2.2 + image: ghcr.io/mailcow/rspamd:2.3 stop_grace_period: 30s depends_on: - dovecot-mailcow diff --git a/update.sh b/update.sh index a300e99a9..89dec3e66 100755 --- a/update.sh +++ b/update.sh @@ -383,7 +383,6 @@ configure_ipv6 [[ -f data/conf/nginx/ZZZ-ejabberd.conf ]] && rm data/conf/nginx/ZZZ-ejabberd.conf migrate_config_options adapt_new_options -remove_obsolete_options if [ ! "$DEV" ]; then DEFAULT_REPO="https://github.com/mailcow/mailcow-dockerized" @@ -434,7 +433,7 @@ if [ ! "$DEV" ]; then 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 +else echo -e "\e[33mDEVELOPER MODE: Not creating a git diff and commiting it to prevent development stuff within a backup diff...\e[0m" fi