Browse Source

Merge pull request #6810 from mailcow/staging

Update 2025-09c
FreddleSpl0it 6 days ago
parent
commit
24c62b2f09
38 changed files with 441 additions and 397 deletions
  1. 34 29
      .github/ISSUE_TEMPLATE/Bug_report.yml
  2. 1 1
      .github/workflows/close_old_issues_and_prs.yml
  3. 8 2
      _modules/scripts/core.sh
  4. 1 0
      _modules/scripts/ipv6_controller.sh
  5. 6 5
      _modules/scripts/new_options.sh
  6. 1 1
      data/Dockerfiles/nginx/bootstrap.py
  7. 4 0
      data/Dockerfiles/sogo/bootstrap-sogo.sh
  8. 19 23
      data/conf/postfix/postscreen_access.cidr
  9. 1 1
      data/conf/rspamd/dynmaps/aliasexp.php
  10. 1 1
      data/conf/rspamd/meta_exporter/pipe.php
  11. 1 1
      data/conf/rspamd/meta_exporter/pushover.php
  12. 12 40
      data/web/inc/functions.app_passwd.inc.php
  13. 4 2
      data/web/inc/functions.customize.inc.php
  14. 11 1
      data/web/inc/functions.inc.php
  15. 2 2
      data/web/inc/functions.mailbox.inc.php
  16. 5 1
      data/web/inc/header.inc.php
  17. 2 0
      data/web/inc/sessions.inc.php
  18. 2 2
      data/web/inc/triggers.user.inc.php
  19. 7 0
      data/web/inc/vars.inc.php
  20. 9 5
      data/web/js/build/013-mailcow.js
  21. 0 1
      data/web/js/site/admin.js
  22. 2 9
      data/web/js/site/dashboard.js
  23. 0 1
      data/web/js/site/edit.js
  24. 0 5
      data/web/js/site/user.js
  25. 34 10
      data/web/lang/lang.cs-cz.json
  26. 1 1
      data/web/lang/lang.de-de.json
  27. 69 43
      data/web/lang/lang.lv-lv.json
  28. 153 148
      data/web/lang/lang.si-si.json
  29. 18 5
      data/web/lang/lang.zh-cn.json
  30. 2 1
      data/web/mta-sts.php
  31. 1 4
      data/web/sogo-auth.php
  32. 4 4
      data/web/templates/edit/app-passwd.twig
  33. 5 3
      data/web/templates/edit/domain.twig
  34. 3 1
      data/web/templates/edit/mailbox.twig
  35. 3 2
      docker-compose.yml
  36. 10 37
      generate_config.sh
  37. 3 3
      helper-scripts/_cold-standby.sh
  38. 2 2
      helper-scripts/docker-compose.override.yml.d/PROMETHEUS_EXPORTER/docker-compose.override.yml

+ 34 - 29
.github/ISSUE_TEMPLATE/Bug_report.yml

@@ -11,70 +11,74 @@ body:
         required: true
   - type: checkboxes
     attributes:
-      label: I've found a bug and checked that ...
-      description: Prior to placing the issue, please check following:** *(fill out each checkbox with an `X` once done)*
+      label: Checklist prior issue creation
+      description: Prior to creating the issue...
       options:
-      - label: ... I understand that not following the below instructions will result in immediate closure and/or deletion of my issue.
+      - label: I understand that failure to follow below instructions may cause this issue to be closed.
         required: true
-      - label: ... I have understood that this bug report is dedicated for bugs, and not for support-related inquiries.
+      - label: I understand that vague, incomplete or inaccurate information may cause this issue to be closed.
         required: true
-      - label: ... I have understood that answers are voluntary and community-driven, and not commercial support.
+      - label: I understand that this form is intended solely for reporting software bugs and not for support-related inquiries.
         required: true
-      - label: ... I have verified that my issue has not been already answered in the past. I also checked previous [issues](https://github.com/mailcow/mailcow-dockerized/issues).
+      - label: I understand that all responses are voluntary and community-driven, and do not constitute commercial support.
+        required: true
+      - label: I confirm that I have reviewed previous [issues](https://github.com/mailcow/mailcow-dockerized/issues) to ensure this matter has not already been addressed.
+        required: true
+      - label: I confirm that my environment meets all [prerequisite requirements](https://docs.mailcow.email/getstarted/prerequisite-system/) as specified in the official documentation.
         required: true
   - type: textarea
     attributes:
       label: Description
-      description: Please provide a brief description of the bug in 1-2 sentences. If applicable, add screenshots to help explain your problem. Very useful for bugs in mailcow UI.
-      render: plain text
-    validations:
-      required: true
-  - type: textarea
-    attributes:
-      label: "Logs:"
-      description: "Please take a look at the [official documentation](https://docs.mailcow.email/troubleshooting/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks."
-      render: plain text
+      description: Please provide a brief description of the bug. If applicable, add screenshots to help explain your problem. (Very useful for bugs in mailcow UI.)
     validations:
       required: true
   - type: textarea
     attributes:
       label: "Steps to reproduce:"
       description: "Please describe the steps to reproduce the bug. Screenshots can be added, if helpful."
-      render: plain text
       placeholder: |-
         1. ...
         2. ...
         3. ...
     validations:
       required: true
+  - type: textarea
+    attributes:
+      label: "Logs:"
+      description: "Please take a look at the [official documentation](https://docs.mailcow.email/troubleshooting/debug-logs/) and post the last few lines of logs, when the error occurs. For example, docker container logs of affected containers. This will be automatically formatted into code, so no need for backticks."
+      render: plain text
+    validations:
+      required: true
   - type: markdown
     attributes:
       value: |
         ## System information
-        ### In this stage we would kindly ask you to attach general system information about your setup.
+        In this stage we would kindly ask you to attach general system information about your setup.
   - type: dropdown
     attributes:
       label: "Which branch are you using?"
-      description: "#### `git rev-parse --abbrev-ref HEAD`"
+      description: "#### Run: `git rev-parse --abbrev-ref HEAD`"
       multiple: false
       options:
-        - master
+        - master (stable)
+        - staging
         - nightly
     validations:
       required: true
   - type: dropdown
     attributes:
       label: "Which architecture are you using?"
-      description: "#### `uname -m`"
+      description: "#### Run: `uname -m`"
       multiple: false
       options:
-        - x86
+        - x86_64
         - ARM64 (aarch64)
     validations:
       required: true
   - type: input
     attributes:
       label: "Operating System:"
+      description: "#### Run: `lsb_release -ds`"
       placeholder: "e.g. Ubuntu 22.04 LTS"
     validations:
       required: true
@@ -93,43 +97,44 @@ body:
   - type: input
     attributes:
       label: "Virtualization technology:"
-      placeholder: "KVM, VMware, Xen, etc - **LXC and OpenVZ are not supported**"
+      description: "LXC and OpenVZ are not supported!"
+      placeholder: "KVM, VMware ESXi, Xen, etc"
     validations:
       required: true
   - type: input
     attributes:
       label: "Docker version:"
-      description: "#### `docker version`"
+      description: "#### Run: `docker version`"
       placeholder: "20.10.21"
     validations:
       required: true
   - type: input
     attributes:
       label: "docker-compose version or docker compose version:"
-      description: "#### `docker-compose version` or `docker compose version`"
+      description: "#### Run: `docker-compose version` or `docker compose version`"
       placeholder: "v2.12.2"
     validations:
       required: true
   - type: input
     attributes:
       label: "mailcow version:"
-      description: "#### ```git describe --tags `git rev-list --tags --max-count=1` ```"
-      placeholder: "2022-08"
+      description: "#### Run: ```git describe --tags `git rev-list --tags --max-count=1` ```"
+      placeholder: "2022-08x"
     validations:
       required: true
   - type: input
     attributes:
       label: "Reverse proxy:"
-      placeholder: "e.g. Nginx/Traefik"
+      placeholder: "e.g. nginx/Traefik, or none"
     validations:
       required: true
   - type: textarea
     attributes:
       label: "Logs of git diff:"
-      description: "#### Output of `git diff origin/master`, any other changes to the code? If so, **please post them**:"
+      description: "#### Output of `git diff origin/master`, any other changes to the code? Sanitize if needed. If so, **please post them**:"
       render: plain text
     validations:
-      required: true
+      required: false
   - type: textarea
     attributes:
       label: "Logs of iptables -L -vn:"

+ 1 - 1
.github/workflows/close_old_issues_and_prs.yml

@@ -14,7 +14,7 @@ jobs:
       pull-requests: write
     steps:
       - name: Mark/Close Stale Issues and Pull Requests 🗑️
-        uses: actions/stale@v10.0.0
+        uses: actions/stale@v10.1.0
         with:
           repo-token: ${{ secrets.STALE_ACTION_PAT }}
           days-before-stale: 60

+ 8 - 2
_modules/scripts/core.sh

@@ -17,7 +17,13 @@ caller="${BASH_SOURCE[1]##*/}"
 
 get_installed_tools(){
     for bin in openssl curl docker git awk sha1sum grep cut jq; do
-        if [[ -z $(command -v ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
+        if [[ -z $(command -v ${bin}) ]]; then
+          echo "Error: Cannot find command '${bin}'. Cannot proceed."
+          echo "Solution: Please review system requirements and install requirements. Then, re-run the script."
+          echo "See System Requirements: https://docs.mailcow.email/getstarted/install/"
+          echo "Exiting..."
+          exit 1
+        fi
     done
 
     if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo -e "${LIGHT_RED}BusyBox grep detected, please install gnu grep, \"apk add --no-cache --upgrade grep\"${NC}"; exit 1; fi
@@ -221,4 +227,4 @@ detect_major_update() {
       fi
     fi
   fi
-}
+}

+ 1 - 0
_modules/scripts/ipv6_controller.sh

@@ -155,6 +155,7 @@ docker_daemon_edit(){
     fi
 
     if [[ $ans =~ ^[Yy]$ ]]; then
+      mkdir -p "$(dirname "$DOCKER_DAEMON_CONFIG")"
       if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
         cat > "$DOCKER_DAEMON_CONFIG" <<EOF
 {

+ 6 - 5
_modules/scripts/new_options.sh

@@ -43,6 +43,7 @@ adapt_new_options() {
   "ALLOW_ADMIN_EMAIL_LOGIN"
   "SKIP_HTTP_VERIFICATION"
   "SOGO_EXPIRE_SESSION"
+  "SOGO_URL_ENCRYPTION_KEY"
   "REDIS_PORT"
   "REDISPASS"
   "DOVECOT_MASTER_USER"
@@ -94,7 +95,6 @@ adapt_new_options() {
             echo '# Max log lines per service to keep in Redis logs' >> mailcow.conf
             echo "LOG_LINES=9999" >> mailcow.conf
             ;;
-        
         IPV4_NETWORK)
             echo '# Internal IPv4 /24 subnet, format n.n.n. (expands to n.n.n.0/24)' >> mailcow.conf
             echo "IPV4_NETWORK=172.22.1" >> mailcow.conf
@@ -276,21 +276,22 @@ adapt_new_options() {
             echo '# A COMPLETE DOCKER STACK REBUILD (compose down && compose up -d) IS NEEDED TO APPLY THIS.' >> mailcow.conf
             echo ENABLE_IPV6=${IPV6_BOOL} >> mailcow.conf
             ;;
-    
         SKIP_CLAMD)
             echo '# Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n' >> mailcow.conf
             echo 'SKIP_CLAMD=n' >> mailcow.conf
             ;;
-
         SKIP_OLEFY)
             echo '# Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n' >> mailcow.conf
             echo 'SKIP_OLEFY=n' >> mailcow.conf
             ;;
-        
         REDISPASS)
             echo "REDISPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2>/dev/null | head -c 28)" >> mailcow.conf
             ;;
-                  
+        SOGO_URL_ENCRYPTION_KEY)
+            echo '# SOGo URL encryption key (exactly 16 characters, limited to A–Z, a–z, 0–9)' >> mailcow.conf
+            echo '# This key is used to encrypt email addresses within SOGo URLs' >> mailcow.conf
+            echo "SOGO_URL_ENCRYPTION_KEY=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2>/dev/null | head -c 16)" >> mailcow.conf
+            ;;
         *)
             echo "${option}=" >> mailcow.conf
             ;;

+ 1 - 1
data/Dockerfiles/nginx/bootstrap.py

@@ -10,7 +10,7 @@ def includes_conf(env, template_vars):
   server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {' '.join(template_vars['ADDITIONAL_SERVER_NAMES'])};"
   listen_plain_config = f"listen {template_vars['HTTP_PORT']};"
   listen_ssl_config = f"listen {template_vars['HTTPS_PORT']};"
-  if not template_vars['ENABLE_IPV6']:
+  if template_vars['ENABLE_IPV6']:
     listen_plain_config += f"\nlisten [::]:{template_vars['HTTP_PORT']};"
     listen_ssl_config += f"\nlisten [::]:{template_vars['HTTPS_PORT']} ssl;"
   listen_ssl_config += "\nhttp2 on;"

+ 4 - 0
data/Dockerfiles/sogo/bootstrap-sogo.sh

@@ -50,6 +50,10 @@ cat <<EOF > /var/lib/sogo/GNUstep/Defaults/sogod.plist
     <string>YES</string>
     <key>SOGoEncryptionKey</key>
     <string>${RAND_PASS}</string>
+    <key>SOGoURLEncryptionEnabled</key>
+    <string>YES</string>
+    <key>SOGoURLEncryptionPassphrase</key>
+    <string>${SOGO_URL_ENCRYPTION_KEY}</string>
     <key>OCSAdminURL</key>
     <string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_admin</string>
     <key>OCSCacheFolderURL</key>

+ 19 - 23
data/conf/postfix/postscreen_access.cidr

@@ -1,12 +1,13 @@
-# Whitelist generated by Postwhite v3.4 on Mon Sep  1 00:23:07 UTC 2025
+# Whitelist generated by Postwhite v3.4 on Wed Oct  1 00:21:33 UTC 2025
 # https://github.com/stevejenkins/postwhite/
-# 2165 total rules
+# 2216 total rules
 2a00:1450:4000::/36	permit
 2a01:111:f400::/48	permit
-2a01:111:f403::/49	permit
-2a01:111:f403:8000::/50	permit
+2a01:111:f403:2800::/53	permit
 2a01:111:f403:8000::/51	permit
+2a01:111:f403::/49	permit
 2a01:111:f403:c000::/51	permit
+2a01:111:f403:d000::/53	permit
 2a01:111:f403:f000::/52	permit
 2a01:238:20a:202:5370::1	permit
 2a01:238:20a:202:5372::1	permit
@@ -55,7 +56,8 @@
 8.40.222.0/23	permit
 8.40.222.250/31	permit
 12.130.86.238	permit
-13.107.246.40	permit
+13.107.213.41	permit
+13.107.246.41	permit
 13.110.208.0/21	permit
 13.110.209.0/24	permit
 13.110.216.0/22	permit
@@ -174,6 +176,7 @@
 35.161.32.253	permit
 35.162.73.231	permit
 35.167.93.243	permit
+35.174.145.124	permit
 35.176.132.251	permit
 35.205.92.9	permit
 35.228.216.85	permit
@@ -183,7 +186,6 @@
 37.218.249.47	permit
 37.218.251.62	permit
 39.156.163.64/29	permit
-40.90.65.81	permit
 40.92.0.0/15	permit
 40.92.0.0/16	permit
 40.107.0.0/16	permit
@@ -271,9 +273,6 @@
 50.56.130.221	permit
 50.56.130.222	permit
 50.112.246.219	permit
-51.77.79.158	permit
-51.83.17.38	permit
-51.89.119.103	permit
 52.1.14.157	permit
 52.5.230.59	permit
 52.6.74.205	permit
@@ -324,8 +323,6 @@
 52.234.172.96/28	permit
 52.235.253.128	permit
 52.236.28.240/28	permit
-54.36.149.183	permit
-54.38.221.122	permit
 54.90.148.255	permit
 54.165.19.38	permit
 54.174.52.0/24	permit
@@ -686,6 +683,8 @@
 82.165.159.45	permit
 82.165.159.130	permit
 82.165.159.131	permit
+85.9.206.169	permit
+85.9.210.45	permit
 85.158.136.0/21	permit
 85.215.255.39	permit
 85.215.255.40	permit
@@ -1234,16 +1233,14 @@
 99.83.190.102	permit
 103.9.96.0/22	permit
 103.28.42.0/24	permit
-103.122.78.238	permit
+103.84.217.238	permit
+103.89.75.238	permit
 103.151.192.0/23	permit
 103.168.172.128/27	permit
 103.237.104.0/22	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
 106.10.144.64/27	permit
@@ -1378,7 +1375,6 @@
 108.174.6.215	permit
 108.175.18.45	permit
 108.175.30.45	permit
-108.177.96.0/20	permit
 108.179.144.0/20	permit
 109.224.244.0/24	permit
 109.237.142.0/24	permit
@@ -1544,6 +1540,7 @@
 148.105.0.0/16	permit
 148.105.8.0/21	permit
 149.72.0.0/16	permit
+149.72.234.184	permit
 149.72.248.236	permit
 149.97.173.180	permit
 150.230.98.160	permit
@@ -1599,6 +1596,7 @@
 159.183.0.0/16	permit
 159.183.68.71	permit
 159.183.79.38	permit
+159.183.129.172	permit
 160.1.62.192	permit
 161.38.192.0/20	permit
 161.38.204.0/22	permit
@@ -1616,6 +1614,7 @@
 163.114.134.16	permit
 163.114.135.16	permit
 163.116.128.0/17	permit
+163.192.116.87	permit
 164.152.23.32	permit
 164.152.25.241	permit
 164.177.132.168/30	permit
@@ -1655,6 +1654,7 @@
 169.148.131.0/24	permit
 169.148.138.0/24	permit
 169.148.142.10	permit
+169.148.142.33	permit
 169.148.144.0/25	permit
 169.148.144.10	permit
 169.148.146.0/23	permit
@@ -1666,11 +1666,7 @@
 170.10.132.56/29	permit
 170.10.132.64/29	permit
 170.10.133.0/24	permit
-172.217.0.0/20	permit
 172.217.32.0/20	permit
-172.217.128.0/19	permit
-172.217.160.0/20	permit
-172.217.192.0/19	permit
 172.253.56.0/21	permit
 172.253.112.0/20	permit
 173.0.84.0/29	permit
@@ -2209,17 +2205,17 @@
 2607:13c0:0002:0000:0000:0000:0000:1000/116	permit
 2607:13c0:0004:0000:0000:0000:0000:0000/116	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:400::8:1	permit
 2620:10d:c091:400::8:1	permit
 2620:10d:c09b:400::8:1	permit
 2620:10d:c09c:400::8:1	permit
-2620:119:50c0:207::215	permit
 2620:119:50c0:207::/64	permit
+2620:119:50c0:207::215	permit
 2800:3f0:4000::/36	permit
 49.12.4.251 permit # checks.mailcow.email
 2a01:4f8:c17:7906::10 permit # checks.mailcow.email

+ 1 - 1
data/conf/rspamd/dynmaps/aliasexp.php

@@ -133,7 +133,7 @@ try {
             error_log("ALIAS EXPANDER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
             $goto_branch_array = explode(',', $goto_branch);
           } else {
-            $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+            $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'");
             $stmt->execute(array(':domain' => $parsed_goto['domain']));
             $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
             if ($goto_branch) {

+ 1 - 1
data/conf/rspamd/meta_exporter/pipe.php

@@ -182,7 +182,7 @@ foreach (json_decode($rcpts, true) as $rcpt) {
               error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
               $goto_branch_array = explode(',', $goto_branch);
             } else {
-              $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+              $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'");
               $stmt->execute(array(':domain' => $parsed_goto['domain']));
               $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
               if ($goto_branch) {

+ 1 - 1
data/conf/rspamd/meta_exporter/pushover.php

@@ -167,7 +167,7 @@ foreach (json_decode($rcpts, true) as $rcpt) {
               error_log("RCPT RESOVLER: http pipe: goto address " . $goto . " is an alias branch for " . $goto_branch . PHP_EOL);
               $goto_branch_array = explode(',', $goto_branch);
             } else {
-              $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` AND '1'");
+              $stmt = $pdo->prepare("SELECT `target_domain` FROM `alias_domain` WHERE `alias_domain` = :domain AND `active` = '1'");
               $stmt->execute(array(':domain' => $parsed_goto['domain']));
               $goto_branch = $stmt->fetch(PDO::FETCH_ASSOC)['target_domain'];
               if ($goto_branch) {

+ 12 - 40
data/web/inc/functions.app_passwd.inc.php

@@ -1,7 +1,7 @@
 <?php
 function app_passwd($_action, $_data = null) {
-	global $pdo;
-	global $lang;
+  global $pdo;
+  global $lang;
   $_data_log = $_data;
   !isset($_data_log['app_passwd']) ?: $_data_log['app_passwd'] = '*';
   !isset($_data_log['app_passwd2']) ?: $_data_log['app_passwd2'] = '*';
@@ -43,20 +43,7 @@ function app_passwd($_action, $_data = null) {
         );
         return false;
       }
-      if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
-        $_SESSION['return'][] = array(
-          'type' => 'danger',
-          'log' => array(__FUNCTION__, $_action, $_data_log),
-          'msg' => 'password_complexity'
-        );
-        return false;
-      }
-      if ($password != $password2) {
-        $_SESSION['return'][] = array(
-          'type' => 'danger',
-          'log' => array(__FUNCTION__, $_action, $_data_log),
-          'msg' => 'password_mismatch'
-        );
+      if (password_check($password, $password2) !== true) {
         return false;
       }
       $password_hashed = hash_password($password);
@@ -88,15 +75,15 @@ function app_passwd($_action, $_data = null) {
         'log' => array(__FUNCTION__, $_action, $_data_log),
         'msg' => 'app_passwd_added'
       );
-    break;
+      break;
     case 'edit':
       $ids = (array)$_data['id'];
       foreach ($ids as $id) {
         $is_now = app_passwd('details', $id);
         if (!empty($is_now)) {
           $app_name = (!empty($_data['app_name'])) ? $_data['app_name'] : $is_now['name'];
-          $password = (!empty($_data['password'])) ? $_data['password'] : null;
-          $password2 = (!empty($_data['password2'])) ? $_data['password2'] : null;
+          $password = (!empty($_data['app_passwd'])) ? $_data['app_passwd'] : null;
+          $password2 = (!empty($_data['app_passwd2'])) ? $_data['app_passwd2'] : null;
           if (isset($_data['protocols'])) {
             $protocols = (array)$_data['protocols'];
             $imap_access = (in_array('imap_access', $protocols)) ? 1 : 0;
@@ -126,20 +113,7 @@ function app_passwd($_action, $_data = null) {
         }
         $app_name = htmlspecialchars(trim($app_name));
         if (!empty($password) && !empty($password2)) {
-          if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
-            $_SESSION['return'][] = array(
-              'type' => 'danger',
-              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
-              'msg' => 'password_complexity'
-            );
-            continue;
-          }
-          if ($password != $password2) {
-            $_SESSION['return'][] = array(
-              'type' => 'danger',
-              'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
-              'msg' => 'password_mismatch'
-            );
+          if (password_check($password, $password2) !== true) {
             continue;
           }
           $password_hashed = hash_password($password);
@@ -182,7 +156,7 @@ function app_passwd($_action, $_data = null) {
           'msg' => array('object_modified', htmlspecialchars(implode(', ', $ids)))
         );
       }
-    break;
+      break;
     case 'delete':
       $ids = (array)$_data['id'];
       foreach ($ids as $id) {
@@ -213,19 +187,17 @@ function app_passwd($_action, $_data = null) {
           'msg' => array('app_passwd_removed', htmlspecialchars($id))
         );
       }
-    break;
+      break;
     case 'get':
       $app_passwds = array();
       $stmt = $pdo->prepare("SELECT `id`, `name` FROM `app_passwd` WHERE `mailbox` = :username");
       $stmt->execute(array(':username' => $username));
       $app_passwds = $stmt->fetchAll(PDO::FETCH_ASSOC);
       return $app_passwds;
-    break;
+      break;
     case 'details':
       $app_passwd_data = array();
-      $stmt = $pdo->prepare("SELECT *
-          FROM `app_passwd`
-            WHERE `id` = :id");
+      $stmt = $pdo->prepare("SELECT * FROM `app_passwd` WHERE `id` = :id");
       $stmt->execute(array(':id' => $_data));
       $app_passwd_data = $stmt->fetch(PDO::FETCH_ASSOC);
       if (empty($app_passwd_data)) {
@@ -237,6 +209,6 @@ function app_passwd($_action, $_data = null) {
       }
       $app_passwd_data['name'] = htmlspecialchars(trim($app_passwd_data['name']));
       return $app_passwd_data;
-    break;
+      break;
   }
 }

+ 4 - 2
data/web/inc/functions.customize.inc.php

@@ -325,8 +325,10 @@ function customize($_action, $_item, $_data = null) {
         break;
         case 'ui_texts':
           try {
-            $data['title_name'] = ($title_name = $redis->get('TITLE_NAME')) ? $title_name : 'mailcow UI';
-            $data['main_name'] = ($main_name = $redis->get('MAIN_NAME')) ? $main_name : 'mailcow UI';
+            $mailcow_hostname = strtolower(getenv("MAILCOW_HOSTNAME"));
+
+            $data['title_name'] = ($title_name = $redis->get('TITLE_NAME')) ? $title_name : "$mailcow_hostname - mail UI";
+            $data['main_name'] = ($main_name = $redis->get('MAIN_NAME')) ? $main_name : "$mailcow_hostname - mail UI";
             $data['apps_name'] = ($apps_name = $redis->get('APPS_NAME')) ? $apps_name : $lang['header']['apps'];
             $data['help_text'] = ($help_text = $redis->get('HELP_TEXT')) ? $help_text : false;
             if (!empty($redis->get('UI_IMPRESS'))) {

+ 11 - 1
data/web/inc/functions.inc.php

@@ -1107,11 +1107,21 @@ function user_get_alias_details($username) {
   }
   return $data;
 }
-function is_valid_domain_name($domain_name) {
+function is_valid_domain_name($domain_name, $options = array()) {
   if (empty($domain_name)) {
     return false;
   }
+
+  // Convert domain name to ASCII for validation
   $domain_name = idn_to_ascii($domain_name, 0, INTL_IDNA_VARIANT_UTS46);
+
+  if (isset($options['allow_wildcard']) && $options['allow_wildcard'] == true) {
+    // Remove '*.' if wildcard subdomains are allowed
+    if (strpos($domain_name, '*.') === 0) {
+      $domain_name = substr($domain_name, 2);
+    }
+  }
+
   return (preg_match("/^([a-z\d](-*[a-z\d])*)(\.([a-z\d](-*[a-z\d])*))*$/i", $domain_name)
        && preg_match("/^.{1,253}$/", $domain_name)
        && preg_match("/^[^\.]{1,63}(\.[^\.]{1,63})*$/", $domain_name));

+ 2 - 2
data/web/inc/functions.mailbox.inc.php

@@ -1446,7 +1446,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           }
           foreach ($mx as $index => $mx_domain) {
             $mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46);
-            if (!is_valid_domain_name($mx_domain)) {
+            if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) {
               $_SESSION['return'][] = array(
                 'type' => 'danger',
                 'log' => array(__FUNCTION__, $_action, $_type, $_data, $_attr),
@@ -3897,7 +3897,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
             foreach ($mx as $index => $mx_domain) {
               $mx_domain = idn_to_ascii(strtolower(trim($mx_domain)), 0, INTL_IDNA_VARIANT_UTS46);
               $invalid_mx = false;
-              if (!is_valid_domain_name($mx_domain)) {
+              if (!is_valid_domain_name($mx_domain, array('allow_wildcard' => true))) {
                 $invalid_mx = $mx_domain;
                 break;
               }

+ 5 - 1
data/web/inc/header.inc.php

@@ -62,7 +62,11 @@ if ($app_links_processed){
   }
 }
 
-
+// Workaround to get text with <br> straight to twig.
+// Using "nl2br" doesn't work with Twig as it would escape everything by default.
+if (isset($UI_TEXTS["ui_footer"])) {
+  $UI_TEXTS["ui_footer"] = nl2br($UI_TEXTS["ui_footer"]);
+}
 
 $globalVariables = [
   'mailcow_hostname' => getenv('MAILCOW_HOSTNAME'),

+ 2 - 0
data/web/inc/sessions.inc.php

@@ -1,7 +1,9 @@
 <?php
 // Start session
 if (session_status() !== PHP_SESSION_ACTIVE) {
+  session_name($SESSION_NAME);
   ini_set("session.cookie_httponly", 1);
+  ini_set("session.cookie_samesite", $SESSION_SAMESITE_POLICY);
   ini_set('session.gc_maxlifetime', $SESSION_LIFETIME);
 }
 

+ 2 - 2
data/web/inc/triggers.user.inc.php

@@ -80,7 +80,7 @@ if (isset($_POST["verify_tfa_login"])) {
             intval($user_details['attributes']['force_pw_update']) != 1 &&
             getenv('SKIP_SOGO') != "y" &&
             !$is_dual) {
-          header("Location: /SOGo/so/{$_SESSION['mailcow_cc_username']}");
+          header("Location: /SOGo/so/");
           die();
         } else {
           header("Location: /user");
@@ -146,7 +146,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
         intval($user_details['attributes']['force_pw_update']) != 1 &&
         getenv('SKIP_SOGO') != "y" &&
         !$is_dual) {
-      header("Location: /SOGo/so/{$login_user}");
+      header("Location: /SOGo/so/");
       die();
     } else {
       header("Location: /user");

+ 7 - 0
data/web/inc/vars.inc.php

@@ -153,6 +153,13 @@ $LOG_PAGINATION_SIZE = 50;
 // Session lifetime in seconds
 $SESSION_LIFETIME = 10800;
 
+// Session SameSite Policy
+// Use "None", "Lax" or "Strict"
+$SESSION_SAMESITE_POLICY = "Lax";
+
+// Name of the session cookie
+$SESSION_NAME = "MCSESSID";
+
 // Label for OTP devices
 $OTP_LABEL = "mailcow UI";
 

+ 9 - 5
data/web/js/build/013-mailcow.js

@@ -22,8 +22,8 @@ $(document).ready(function() {
     $.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
   }
 
-  $(".generate_password").click(async function( event ) {   
-    try { 
+  $(".generate_password").click(async function( event ) {
+    try {
       var password_policy = await window.fetch("/api/v1/get/passwordpolicy", { method:'GET', cache:'no-cache' });
       var password_policy = await password_policy.json();
       random_passwd_length = password_policy.length;
@@ -48,7 +48,11 @@ $(document).ready(function() {
     })
   }
   $(".rot-enc").html(function(){
-    return str_rot13($(this).html())
+    footer_html = $(this).html();
+    footer_html = footer_html.replace(/&lt;/g, '<').replace(/&gt;/g, '>')
+                             .replace(/&amp;/g, '&').replace(/&nzc;/g, '&')
+                             .replace(/&quot;/g, '"').replace(/&#x27;/g, "'");
+    return str_rot13(footer_html)
   });
   // https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate
   function shake(div,interval,distance,times) {
@@ -125,7 +129,7 @@ $(document).ready(function() {
         }
       });
   })();
-  
+
   // responsive tabs, scroll to opened tab
   $(document).on("shown.bs.collapse shown.bs.tab", function (e) {
 	  var target = $(e.target);
@@ -409,4 +413,4 @@ function copyToClipboard(id) {
   // only works with https connections
   navigator.clipboard.writeText(copyText.value);
   mailcow_alert_box(lang.copy_to_clipboard, "success");
-}
+}

+ 0 - 1
data/web/js/site/admin.js

@@ -715,7 +715,6 @@ jQuery(function($){
     $('.app_hide').off('change');
     $('.app_hide').on('change', function (e) {
       var value = $(this).is(':checked') ? '1' : '0';
-      console.log(value)
       $(this).parent().children(':first-child').val(value);
     })
   }

+ 2 - 9
data/web/js/site/dashboard.js

@@ -47,8 +47,6 @@ $(document).ready(function() {
     window.fetch("/api/v1/get/status/host/ip", { method:'GET', cache:'no-cache' }).then(function(response) {
       return response.json();
     }).then(function(data) {
-      console.log(data);
-
       // display host ips
       if (data.ipv4)
         $("#host_ipv4").text(data.ipv4);
@@ -1007,7 +1005,7 @@ jQuery(function($){
               "data-order": cellData.sortBy,
               "data-sort": cellData.sortBy
             });
-          },    
+          },
           render: function (data) {
             return data.value;
           }
@@ -1032,7 +1030,7 @@ jQuery(function($){
               "data-order": cellData.sortBy,
               "data-sort": cellData.sortBy
             });
-          },    
+          },
           render: function (data) {
             return data.value;
           }
@@ -1347,9 +1345,6 @@ function update_stats(timeout=5){
 
   window.fetch("/api/v1/get/status/host", {method:'GET',cache:'no-cache'}).then(function(response) {
     return response.json();
-  }).then(function(data) {
-    console.log(data);
-
     if (data){
       // display table data
       $("#host_date").text(data.system_time);
@@ -1399,8 +1394,6 @@ function update_container_stats(timeout=5){
         var diskIOCtx = Chart.getChart(container + "_DiskIOChart");
         var netIOCtx = Chart.getChart(container + "_NetIOChart");
 
-        console.log(container);
-        console.log(data);
         prev_stats = null;
         if (data.length >= 2){
           prev_stats = data[data.length -2];

+ 0 - 1
data/web/js/site/edit.js

@@ -66,7 +66,6 @@ $(document).ready(function() {
   // load tags
   if ($('#tags').length){
     var tagsEl = $('#tags').parent().find('.tag-values')[0];
-    console.log($(tagsEl).val())
     var tags = JSON.parse($(tagsEl).val());
     $(tagsEl).val("");
 

+ 0 - 5
data/web/js/site/user.js

@@ -169,7 +169,6 @@ jQuery(function($){
         type: "GET",
         url: "/api/v1/get/time_limited_aliases",
         dataSrc: function(data){
-          console.log(data);
           $.each(data, function (i, item) {
             if (acl_data.spam_alias === 1) {
               item.action = '<div class="btn-group">' +
@@ -262,7 +261,6 @@ jQuery(function($){
         type: "GET",
         url: '/api/v1/get/syncjobs/' + encodeURIComponent(mailcow_cc_username) + '/no_log',
         dataSrc: function(data){
-          console.log(data);
           $.each(data, function (i, item) {
             item.user1 = escapeHtml(item.user1);
             item.log = '<a href="#syncjobLogModal" data-bs-toggle="modal" data-syncjob-id="' + item.id + '">' + lang.open_logs + '</a>'
@@ -418,7 +416,6 @@ jQuery(function($){
         type: "GET",
         url: '/api/v1/get/app-passwd/all',
         dataSrc: function(data){
-          console.log(data);
           $.each(data, function (i, item) {
             item.name = escapeHtml(item.name)
             item.protocols = []
@@ -514,7 +511,6 @@ jQuery(function($){
         type: "GET",
         url: '/api/v1/get/policy_wl_mailbox',
         dataSrc: function(data){
-          console.log(data);
           $.each(data, function (i, item) {
             if (validateEmail(item.object)) {
               item.chkbox = '<input type="checkbox" class="form-check-input" data-id="policy_wl_mailbox" name="multi_select" value="' + item.prefid + '" />';
@@ -585,7 +581,6 @@ jQuery(function($){
         type: "GET",
         url: '/api/v1/get/policy_bl_mailbox',
         dataSrc: function(data){
-          console.log(data);
           $.each(data, function (i, item) {
             if (validateEmail(item.object)) {
               item.chkbox = '<input type="checkbox" class="form-check-input" data-id="policy_bl_mailbox" name="multi_select" value="' + item.prefid + '" />';

+ 34 - 10
data/web/lang/lang.cs-cz.json

@@ -24,7 +24,7 @@
         "sogo_access": "Správa přístupu do SOGo",
         "sogo_profile_reset": "Resetování profilu SOGo",
         "spam_alias": "Dočasné aliasy",
-        "spam_policy": "Blacklist/Whitelist",
+        "spam_policy": "Denylist/Allowlist",
         "spam_score": "Skóre spamu",
         "syncjobs": "Synchronizační úlohy",
         "tls_policy": "Pravidla TLS",
@@ -109,7 +109,9 @@
         "validate": "Ověřit",
         "validation_success": "Úspěšně ověřeno",
         "tags": "Štítky",
-        "dry": "Simulovat synchronizaci"
+        "dry": "Simulovat synchronizaci",
+        "internal": "Interní",
+        "internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů."
     },
     "admin": {
         "access": "Přístupy",
@@ -303,7 +305,7 @@
         "rspamd_global_filters": "Mapa globálních filtrů",
         "rspamd_global_filters_agree": "Budu opatrný!",
         "rspamd_global_filters_info": "Mapa globálních filtrů obsahuje jiné globální black- a whitelisty.",
-        "rspamd_global_filters_regex": "Názvy jsou dostatečným vysvětlením. Musí obsahovat jen platné regulární výrazy ve formátu \"/vyraz/parametry\" (e.g. <code>/.+@domena\\.tld/i</code>).<br>\r\n  Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.<br>\r\n  Rspamd se pokusí načíst mapu po každé změně. V případě potíží, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">restartujte Rspamd</a>, aby se konfigurace načetla explicitně.",
+        "rspamd_global_filters_regex": "Názvy stačí k vysvětlení. Položky musejí obsahovat jen platné regulární výrazy ve tvaru \"/vyraz/parametry\" (e.g. <code>/.+@domena\\.tld/i</code>).<br>\n  Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.<br>\n  Rspamd se pokusí po každé změně načíst mapu znovu. V případě potíží <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">restartujte Rspamd</a>, aby se konfigurace načetla explicitně.",
         "rspamd_settings_map": "Nastavení Rspamd",
         "sal_level": "Úroveň 'Moo'",
         "save": "Uložit změny",
@@ -407,7 +409,9 @@
         "iam_extra_permission": "Aby vše fungovalo, musí mít mailcow klient v Keycloaku nastavený <code>servisní účet</code> a povolení <code>view-users</code>.",
         "iam_host": "Hostitel",
         "iam_host_info": "Zadejte jeden či více hostitelů, oddělte čárkou.",
-        "iam_import_users": "Importovat uživatele"
+        "iam_import_users": "Importovat uživatele",
+        "iam_auth_flow": "Proces autentizace",
+        "needs_restart": "potřebuje restart"
     },
     "danger": {
         "access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
@@ -548,7 +552,11 @@
         "img_size_exceeded": "Obrázek má větší než povolenou velikost souboru",
         "invalid_reset_token": "Neplatný resetovací token",
         "required_data_missing": "Chybí potřebný údaj %s",
-        "reset_token_limit_exceeded": "Byl překročen limit na reset tokeny. Zkuste to později."
+        "reset_token_limit_exceeded": "Byl překročen limit na reset tokeny. Zkuste to později.",
+        "max_age_invalid": "Maximální životnost %s není platná",
+        "mode_invalid": "Mód %s není platný",
+        "mx_invalid": "Záznam MX %s není platný",
+        "version_invalid": "Verze %s není platná"
     },
     "datatables": {
         "emptyTable": "Tabulka neobsahuje žádná data",
@@ -759,7 +767,20 @@
         "mailbox_rename_warning": "DŮLEŽITÉ! Vytvořte si zálohu schránky, než ji přejmenujete.",
         "mailbox_rename_alias": "Automaticky vytvořit alias",
         "mailbox_rename_title": "Nový název zdejší schránky",
-        "pushover": "Pushover"
+        "pushover": "Pushover",
+        "internal": "Interní",
+        "internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů.",
+        "mta_sts": "MTA-STS",
+        "mta_sts_info": "<a href='https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security' target='_blank'>MTA-STS</a> je standard, jenž říká poštovním serverům, aby komunikovaly pomocí TLS s platnými certifikáty. <br>Používá se, pokud není k dispozici <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a>, např. chybí-li či není podporováno DNSSEC.<br><b>Pozn.</b>: Podporuje-li přijímající doména DANE a DNSSEC, bude <b>vždy</b> použito DANE; MTA-STS zůstane jako plán B.",
+        "mta_sts_version": "Verze",
+        "mta_sts_version_info": "Určuje verzi standardu MTA-STS – zatím je podporována jen <code>STSv1</code>.",
+        "mta_sts_mode": "Mód",
+        "mta_sts_mode_info": "K dispozici jsou tři módy:<ul><li><em>testing</em> – pravidlo se jen sleduje, porušení je bez následků.</li><li><em>enforce</em> – pravidlo je důsledně dodržováno, spojení bez platného TLS jsou odmítána.</li><li><em>none</em> – pravidlo je zveřejněno, ale neuplatňuje se.</li></ul>",
+        "mta_sts_max_age": "Maximální životnost",
+        "mta_sts_max_age_info": "Doba v sekundách, po niž poštovní servery mohou toho pravidlo držet v mezipaměti bez nutnosti obnovení.",
+        "mta_sts_mx": "Server MX",
+        "mta_sts_mx_info": "Dovoluje odesílání jen výslovně vypsaným poštovním serverům; odesílající server kontroluje, že server MX určený v DNS odpovídá pravidlu, a povolí doručení jen s platným certifikátem TLS (chrání přes útokem typu MITM).",
+        "mta_sts_mx_notice": "Lze zadat více serverů MX (oddělte čárkou)."
     },
     "fido2": {
         "confirm": "Potvrdit",
@@ -829,7 +850,8 @@
         "login_admintext": "Přihlášení správce",
         "login_user": "Přihlášení uživatele",
         "login_dadmin": "Přihlášení správce domény",
-        "login_admin": "Přihlášení správce"
+        "login_admin": "Přihlášení správce",
+        "email": "Mailová adresa"
     },
     "mailbox": {
         "action": "Akce",
@@ -861,7 +883,7 @@
         "bcc": "BCC",
         "bcc_destination": "Cíl kopie",
         "bcc_destinations": "Cíl kopií",
-        "bcc_info": "Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.\nMístní cíl se nedozví, selže-li doručení na cíl BCC.",
+        "bcc_info": "<br/>Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.<br/>\n  Místní cíl se nedozví, selže-li doručení na cíl BCC.",
         "bcc_local_dest": "Týká se",
         "bcc_map": "Skrytá kopie",
         "bcc_map_type": "Typ skryté kopie",
@@ -1005,7 +1027,8 @@
         "weekly": "Každý týden",
         "yes": "&#10003;",
         "relay_unknown": "Předávání neexistujících schránek",
-        "iam": "Poskytovatel identity"
+        "iam": "Poskytovatel identity",
+        "internal": "Interní"
     },
     "oauth2": {
         "access_denied": "K udělení přístupu se přihlašte jako vlastník mailové schránky.",
@@ -1082,7 +1105,8 @@
         "hold_mail_legend": "Podrží vybrané e-maily. (Zabrání dalším pokusům o doručení)",
         "show_message": "Zobrazit zprávu",
         "unhold_mail": "Uvolnit",
-        "unhold_mail_legend": "Uvolnit vybrané e-maily k doručení. (Pouze v případě předchozího podržení)"
+        "unhold_mail_legend": "Uvolnit vybrané e-maily k doručení. (Pouze v případě předchozího podržení)",
+        "unban": "odblokovat"
     },
     "ratelimit": {
         "disabled": "Vypnuto",

+ 1 - 1
data/web/lang/lang.de-de.json

@@ -1100,7 +1100,7 @@
         "legend": "Funktionen der Mailqueue Aktionen:",
         "ays": "Soll die derzeitige Queue wirklich komplett bereinigt werden?",
         "deliver_mail": "Ausliefern",
-        "deliver_mail_legend": "Versucht eine erneute Zustellung der ausgwählten Mails.",
+        "deliver_mail_legend": "Versucht eine erneute Zustellung der ausgewählten Mails.",
         "hold_mail": "Zurückhalten",
         "hold_mail_legend": "Hält die ausgewählten Mails zurück. (Verhindert weitere Zustellversuche)",
         "queue_manager": "Queue Manager",

+ 69 - 43
data/web/lang/lang.lv-lv.json

@@ -39,16 +39,16 @@
         "alias_domain_info": "<small>Tikai derīgi domēna vārdi (komatu atdalīti).</small>",
         "automap": "Mēģiniet automatizēt mapes (\"Nosūtītie vienumi\", \"Nosūtītie\" => \"Nosūtītie\" etc.)",
         "backup_mx_options": "Dublējuma MX iespējas",
-        "delete1": "Dzēst no avota, kad tas ir pabeigts",
+        "delete1": "Izdzēst no avota pēc pabeigšanas",
         "delete2": "Dzēsiet ziņojumus galamērķī, kas nav avotā",
-        "delete2duplicates": "Dzēst dublikātus galamērķī",
+        "delete2duplicates": "Izdzēst atkārtojošos vienumus galamērķī",
         "description": "Apraksts",
         "domain": "Domēns",
         "domain_quota_m": "Kopējā domēna kvota (MiB)",
         "enc_method": "Šifrēšanas metode",
         "exclude": "Izslēgt objektus (regex)",
         "full_name": "Pilns vārds",
-        "goto_null": "Klusām dzēst pastu",
+        "goto_null": "Klusām atmest pastu",
         "hostname": "Saimniekdators",
         "kind": "Veids",
         "mailbox_quota_m": "Maks. kvota pastkastei (MiB)",
@@ -77,12 +77,13 @@
         "target_domain": "Mērķa domēns",
         "username": "Lietotājvārds",
         "validate": "Apstiprināt",
-        "validation_success": "Apstiprināts veiksmīgi",
+        "validation_success": "Sekmīgi apstiprināts",
         "bcc_dest_format": "BCC galamērķim ir jābūt vienai derīgai e-pasta adresei.<br>Ja ir nepieciešams nosūtīt kopiju vairākām adresēm, jāizveido aizstājvārds un jāizmanto tas šeit.",
         "domain_matches_hostname": "Domēns %s atbilst saimniekdatora nosaukumam",
         "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)",
         "app_password": "Pievienot lietotnes paroli",
-        "app_passwd_protocols": "Atļautie lietotnes paroles protokoli"
+        "app_passwd_protocols": "Atļautie lietotnes paroles protokoli",
+        "goto_spam": "Apgūt kā <span class=\"text-danger\"><b>mēstuli</b></span>"
     },
     "admin": {
         "access": "Pieeja",
@@ -115,14 +116,14 @@
         "domain": "Domēns",
         "domain_admins": "Domēna administratori",
         "edit": "Labot",
-        "empty": "Nav rezultātu",
+        "empty": "Nav iznākuma",
         "f2b_ban_time": "Aizlieguma laiks (s)",
         "f2b_max_attempts": "Maks. piegājieni",
         "f2b_netban_ipv4": "IPv4 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-32)",
         "f2b_netban_ipv6": "IPv6 apakštīkla izmērs, lai piemērotu aizliegumu uz (8-128)",
         "f2b_parameters": "Fail2ban parametri",
         "f2b_retry_window": "Atkārtošanas logs (s) priekš maks. piegājiena",
-        "f2b_whitelist": "Baltā saraksta tīkls/hosts",
+        "f2b_whitelist": "Atļautie tīkli/resursdatori",
         "filter_table": "Filtru tabula",
         "forwarding_hosts": "Hostu pārsūtīšana",
         "forwarding_hosts_add_hint": "Var norādīt vai nu IPv4/IPv6 adreses, tīklu ar CIDR apzīmējumu, saimniekdatoru nosaukumus (kas tiks atrisināti IP adresēs) vai arī domēna vārdus (kas tiks atrisināti IP adresēs, vaicājot SPF ierakstus, vai, ja tādu nav, MX ierakstus).",
@@ -181,7 +182,10 @@
         "rspamd_com_settings": "Iestatījuma nosaukums tiks izveidots automātiski. Lūgums zemāk skatīt priekšiestatījumu piemērus. Vairāk informācijas ir <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Rspamd dokumentācijā</a>",
         "reset_password_vars": "<code>{{link}}</code> Izveidotā paroles atiestatīšanas saite<br><code>{{username}}</code> Lietotāja, kurš pieprasīja paroles atiestatīšanu, pastkastes nosaukums<br><code>{{username2}}</code> Atkopšanas pastkastes nosaukums<br><code>{{date}}</code> Paroles atiestatīšanas pieprasījuma veikšanas datums<br><code>{{token_lifetime}}</code> Pilnvaras derīgums minūtēs<br><code>{{hostname}}</code> mailcow saimniekdatora nosaukums",
         "ui_header_announcement_help": "Paziņojums ir redzams visiem lietotājiem, kuri ir pieteikušies, un pieteikšanās ekrānā saskarnē.",
-        "login_time": "Pieteikšanās laiks"
+        "login_time": "Pieteikšanās laiks",
+        "iam_version": "Versija",
+        "quarantine_max_age": "Lielākais pieļaujamais vecums dienās<br><small>Vērtībai jābūt vienādai ar vai lielākai par 1 dienu.</small>",
+        "quarantine_max_score": "Atmest paziņojumu, ja e-pasta ziņojuma mēstuļu novērtējums ir augstāks par šo vērtību:<br><small>Noklusējums ir 9999.0</small>"
     },
     "danger": {
         "access_denied": "Piekļuve liegta, vai nepareizi dati",
@@ -201,8 +205,8 @@
         "goto_empty": "Aizstājādresei jāsatur vismaz viena derīga mērķa adrese",
         "goto_invalid": "Goto adrese nepareiza",
         "imagick_exception": "Kļūda: Imagick izņēmums, lasot attēlu",
-        "img_invalid": "Nevar apstiprināt attēla failu",
-        "img_tmp_missing": "Nevar apstiprināt attēla failu: pagaidu failu nav atrasts",
+        "img_invalid": "Nevar apstiprināt attēla datni",
+        "img_tmp_missing": "Nevar apstiprināt attēla datni: pagaidu datne nav atrasta",
         "invalid_mime_type": "Nederīgs mime tips",
         "is_alias": "%s jau ir zināma kā aizstājadrese",
         "is_alias_or_mailbox": "%s jau ir zināms kā aizstājvārds, pastkaste vai aizstājadrese, kas ir izvērsta no aizstājdomēna.",
@@ -234,7 +238,10 @@
         "username_invalid": "Lietotājvārds nevar tikt izmantots",
         "validity_missing": "Lūdzu piešķiriet derīguma termiņu",
         "domain_cannot_match_hostname": "Domēns nevar atbilst saimniekdatora nosaukumam",
-        "app_passwd_id_invalid": "Lietotnes paroles Id %s ir nederīgs"
+        "app_passwd_id_invalid": "Lietotnes paroles Id %s ir nederīgs",
+        "img_dimensions_exceeded": "Attēls pārsniedz lielāko pieļaujamo attēla lielumu",
+        "img_size_exceeded": "Attēls pārsniedz lielāko pieļaujamo datnes lielumu",
+        "version_invalid": "Versija %s ir nederīga"
     },
     "diagnostics": {
         "cname_from_a": "Vērtība, kas iegūta no A/AAAA ieraksta. Tas tiek atbalstīts tik ilgi, kamēr ieraksts norāda uz pareizo resursu.",
@@ -251,9 +258,9 @@
         "alias": "Labot aizstājvārdu",
         "automap": "Mēģiniet automatizēt mapes (\"Nosūtītie vienumi\", \"Nosūtītie\" => \"Nosūtītie\" utt.)",
         "backup_mx_options": "Dublēt MX iespējas",
-        "delete1": "Dzēst no avota, kad pabeigts",
+        "delete1": "Izdzēst no avota pēc pabeigšanas",
         "delete2": "Dzēsiet ziņojumus galamērķī, kas nav avotā",
-        "delete2duplicates": "Dzēst dublikātus galamērķī",
+        "delete2duplicates": "Izdzēst atkārtojošos vienumus galamērķī",
         "description": "Apraksts",
         "domain": "Labot domēnu",
         "domain_admin": "Labot domēna administratoru",
@@ -273,7 +280,7 @@
         "max_aliases": "Lielākais aizstājvārdu skaits",
         "max_mailboxes": "Maks. iespējamās pastkastes",
         "max_quota": "Maks. kvota uz pastkasti (MiB)",
-        "maxage": "Lielākais ziņojumu, kuri tiks vaicāti attālajā serverī, vecums dienās<br><small>(0 = neņemt vērā vecumu)</small>",
+        "maxage": "Lielākais pieļaujamais ziņojumu, kuri tiks vaicāti attālajā serverī, vecums dienās<br><small>(0 = neņemt vērā vecumu)</small>",
         "maxbytespersecond": "Maks. baiti sekundē (0 ir vienāds ar neierobežotu skaitu)",
         "mins_interval": "Intervāls (min)",
         "multiple_bookings": "Vairāki rezervējumi",
@@ -292,8 +299,8 @@
         "sieve_type": "Filtra tips",
         "skipcrossduplicates": "Izlaist dublētus ziņojumus pa mapēm (pirmais nāk, pirmais kalpo)",
         "spam_alias": "Izveidot vai mainīt laika ierobežotas aizstājadreses",
-        "spam_policy": "Pievienot vai noņemt vienumus baltajā-/melnajā sarakstā",
-        "spam_score": "Iestatīt pielāgotu surogātpasta vērtējumu",
+        "spam_policy": "Pievienot vai noņemt vienumus atļautajā/liegumu sarakstā",
+        "spam_score": "Iestatīt pielāgotu mēstules vērtējumu",
         "subfolder2": "Sinhronizēt galamērķa apakšmapē<br><small>(tukšs = neizmantot apakšmapi)</small>",
         "syncjob": "Labot sinhronizācijas darbu",
         "target_address": "Mērķa adrese/s <small>(atdalītas ar komatu)</small>",
@@ -316,17 +323,21 @@
         "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)",
         "app_passwd_protocols": "Atļautie lietotnes paroles protokoli",
         "allowed_protocols": "Atļautie protokoli tiešai lietotāja piekļuvei (neietekmē lietotnes paroles protokolus)",
-        "app_passwd": "Lietotnes parole"
+        "app_passwd": "Lietotnes parole",
+        "mta_sts_version": "Versija",
+        "mta_sts_version_info": "Norāda MTA-STS standarta versiju – pašreiz ir derīga tikai <code>STSv1</code>.",
+        "sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sūtītāja pārbaude ir atspējota</span>"
     },
     "footer": {
         "cancel": "Atcelt",
-        "confirm_delete": "Apstiprināt dzēšanu",
-        "delete_now": "Dzēst tagad",
+        "confirm_delete": "Apstiprināt izdzēšanu",
+        "delete_now": "Izdzēst tagad",
         "delete_these_items": "Lūgums apstiprināt izmaiņas šim objekta Id",
         "loading": "Lūgums uzgaidīt...",
         "restart_container": "Restartēt konteineri",
         "restart_container_info": "<b>Svarīgi:</b> nesteidzīga pārsāknēšana var aizņemt ilgāku laiku. Lūgums uzgaidīt, līdz tā tiek pabeigta.",
-        "restart_now": "Pārsāknēt tagad"
+        "restart_now": "Pārsāknēt tagad",
+        "hibp_nok": "Sakrīt. Šī, iespējams, ir bīstama parole."
     },
     "header": {
         "administration": "Konfigurācija un informācija",
@@ -389,7 +400,7 @@
         "domain_quota_total": "Kopējais domēna ierobežojums",
         "domains": "Domēns",
         "edit": "Labot",
-        "empty": "Nav rezultātu",
+        "empty": "Nav iznākuma",
         "excludes": "Izslēdzot",
         "filter_table": "Filtra tabula",
         "filters": "Filtri",
@@ -448,13 +459,15 @@
         "add_alias_expand": "Izvērst aizstājvārdu pār aizstājdomēniem",
         "alias_domain_alias_hint": "Aizstājvārdi <b>netiek</b> automātiski piemēroti domēnu aizstājvārdiem. Aizstājadrese <code>my-alias@domain</code> <b>nenosedz</b> adresi <code>my-alias@alias-domain</code> (kur \"alias-domain\" ir iedomāts \"domain\" aizstājdomēns).<br>Lūgums izmantot sieta atlasi, lai pārvirzītu pastu uz ārēju pastkasti (skatīt cilti \"Atlasīšana\" vai izmantot SOGo -> Pārsūtītājs). \"Izvērst aizstājvārdu pār aizstājdomēniem\" ir izmantojams, lai automātiski pievienotu trūkstošos aiztājvārdus.",
         "alias_domain_backupmx": "Aizstājdomēns ir neaktīvs retranslācijas domēnam",
-        "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)"
+        "disable_login": "Neļaut pieteikšanos (ienākošais pasts joprojām tiks pieņemts)",
+        "sieve_preset_1": "Atmest e-pasta vēstules ar iespējami bīstamiem datņu veidiem",
+        "syncjob_last_run_result": "Pēdējās izpildes iznākums"
     },
     "quarantine": {
         "action": "Darbības",
         "atts": "Pielikumi",
-        "check_hash": "Meklēt faila hašu @ VT",
-        "empty": "Nav rezultātu",
+        "check_hash": "Meklēt datnes jaucējvērtību @ VT",
+        "empty": "Nav iznākuma",
         "qid": "Rspamd QID",
         "qitem": "Karantīnas vienumi",
         "quarantine": "Karantīna",
@@ -463,7 +476,7 @@
         "received": "Saņemtie",
         "recipients": "Adresāts",
         "release": "Atbrīvot",
-        "release_body": "Šim ziņojumam mēs esam pievienojuši jūsu ziņojumu kā eml failu.",
+        "release_body": "Mēs pievienojām Tavu ziņojumu kā .eml datni šim ziņojumam.",
         "release_subject": "Potenciāli kaitīgs karantīnas vienums %s",
         "remove": "Noņemt",
         "sender": "Sūtītājs (SMTP)",
@@ -473,8 +486,14 @@
         "text_plain_content": "Saturs (teksts/vienkāršs)",
         "toggle_all": "Pārslēgt visu",
         "disabled_by_config": "Pašreizējā sistēmas konfigurācija atspējo karantīnu. Lūgums iestatīt \"saglabāšanu katrai pastkastītei\" un \"lielākais pieļaujamais lielums\" karantīnas vienumiem.",
-        "qhandler_success": "Pieprasījums veiksmīgi nosūtīts sistēmai. Tagad var aizvērt logu.",
-        "qinfo": "Karantīnas sistēma datubāzē saglabās noraidīto pastu (sūtītājam <em>netiks</em> radīts iespaids par piegādātu pastu), kā arī pastu, kas tiek piegādāts kā kopija pastkastes mēstuļu mapē.\n  <br>\"Apgūt kā surogātpastu un izdzēst\" apgūs ziņojumu kā surogātpastu ar Bajesa teorēmu un aprēķinās arī nestriktas jaucējvērtības, lai nākotnē noraidītu līdzīgus ziņojumus.\n  <br>Lūgums apzināties, ka vairāku ziņojumu apgūšana var būt laikietilpīga atkarībā no sistēmas.<br>Melnā saraksta vienumi karantīnā netiek iekļauti."
+        "qhandler_success": "Pieprasījums sekmīgi nosūtīts sistēmai. Logu tagad var aizvērt.",
+        "qinfo": "Karantīnas sistēma datubāzē saglabās noraidīto pastu (sūtītājam <em>netiks</em> radīts iespaids par piegādātu pastu), kā arī pastu, kas tiek piegādāts kā kopija pastkastes mēstuļu mapē.\n  <br>\"Apgūt kā surogātpastu un izdzēst\" apgūs ziņojumu kā surogātpastu ar Bajesa teorēmu un aprēķinās arī nestriktas jaucējvērtības, lai nākotnē noraidītu līdzīgus ziņojumus.\n  <br>Lūgums apzināties, ka vairāku ziņojumu apgūšana var būt laikietilpīga atkarībā no sistēmas.<br>Lieguma saraksta vienumi karantīnā netiek iekļauti.",
+        "danger": "Bīstamība",
+        "notified": "Paziņots",
+        "refresh": "Atsvaidzināt",
+        "rspamd_result": "Rspamd iznākums",
+        "settings_info": "Lielākais pieļaujamais karantējamo vienumu daudzums: %s<br>Lielākais pieļaujamais e-pasta lielums: %s MiB",
+        "spam_score": "Novērtējums"
     },
     "queue": {
         "queue_manager": "Rindas pārvaldnieks",
@@ -505,8 +524,8 @@
         "f2b_modified": "Fail2ban parametru izmaiņas tika saglabātas",
         "forwarding_host_added": "Pāradresācijas hosts %s pievienotsd",
         "forwarding_host_removed": "Pāradresācijas hosts %s noņemts",
-        "item_deleted": "Vērtība %s veiksmīgi dzēsta",
-        "items_deleted": "Vērtība %s veiksmīgi dzēsta",
+        "item_deleted": "Vienums %s izdzēsts sekmīgi",
+        "items_deleted": "Vienums %s izdzēsts sekmīgi",
         "items_released": "Atlasītie vienumi tika izlaisti",
         "mailbox_added": "Pastkaste %s ir pievienota",
         "mailbox_modified": "Izmaiņas pastkastei %s ir saglabātas",
@@ -519,20 +538,21 @@
         "resource_modified": "Izmaiņas %s ir saglabātas",
         "resource_removed": "Resurs %s tika noņemts",
         "ui_texts": "Saglabāt UI izmaiņas tekstiem",
-        "upload_success": "Faila augšupielāde veiksmīga",
+        "upload_success": "Datne sekmīgi augšupielādēta",
         "verified_fido2_login": "Apliecināta FIDO2 pieteikšanās",
         "verified_webauthn_login": "Apliecināta WebAuthn pieteikšanās",
         "verified_totp_login": "Apliecināta TOTP pieteikšanās",
         "verified_yotp_login": "Apliecināta Yubico OTP pieteikšanās",
         "app_passwd_removed": "Noņemta lietotnes parole ar Id %s",
-        "app_passwd_added": "Pievienota jauna lietotnes parole"
+        "app_passwd_added": "Pievienota jauna lietotnes parole",
+        "f2b_banlist_refreshed": "Liegumu saraksta Id tika sekmīgi atsvaidzināts."
     },
     "tfa": {
         "api_register": "%s izmanto Yubico Cloud API. Lūdzu iegūstiet API atslēgu priekš Jūsu atslēgas<a href=\"https://upgrade.yubico.com/getapikey/\" target=\"_blank\">here</a>",
         "confirm": "Apstiprināt",
-        "confirm_totp_token": "Lūdzu apstipriniet Jūsu izmaiņas ievadot uzģenerēto tekstu",
+        "confirm_totp_token": "Lūgums apstiprināt savas izmaiņas ar izveidotās tekstvienības ievadīšanu",
         "delete_tfa": "Atspējot TFA",
-        "disable_tfa": "Atspējot TFA līdz nākamajai veiksmīgajai pieteikšanās reizei",
+        "disable_tfa": "Atspējot TFA līdz nākamajai sekmīgajai pieteikšanās reizei",
         "enter_qr_code": "TOTP kods, ja Tava ierīce nevar nolasīt kvadrātkodus",
         "key_id": "Jūsu YubiKey identifikators",
         "key_id_totp": "Identifikators Jūsu atslēgai",
@@ -544,7 +564,7 @@
         "totp": "Uz laiku bāzēta vienreizēja parole (Google Autentifikātors utt.)",
         "webauthn": "WebAuthn autentifikācija",
         "waiting_usb_auth": "<i>Gaida USB ierīci...</i><br><br>Lūdzu, tagad nospiežiet pogu uz Jūsu WebAuthn USB ierīces.",
-        "waiting_usb_register": "<i>Gaida USB ierīci...</i><br><br>Lūdzu augšā ievadiet Jūsu paroli un apstipriniet WebAuthn reģistrāciju nospiežot pogu uz Jūsu WebAuthn USB ierīces.",
+        "waiting_usb_register": "<i>Gaida USB ierīci...</i><br><br>Lūgums augstāk ievadīt savu paroli un apstiprināt reģistrēšanos ar USB ierīces pogas nospiešanu.",
         "yubi_otp": "Yubico OTP autentifikators",
         "authenticators": "Autentificētāji"
     },
@@ -589,7 +609,7 @@
         "new_password_repeat": "Paroles apstiprinājums (atkārtoti)",
         "no_active_filter": "Nav pieejami aktīvi filtri",
         "no_record": "Nav ieraksta",
-        "password_now": "Pašreizējā parole (Apstiprināt izmaiņas)",
+        "password_now": "Pašreizējā parole (apstiprināt izmaiņas)",
         "remove": "Noņemt",
         "running": "Darbojas",
         "save_changes": "Saglabāt izmaiņas",
@@ -599,11 +619,11 @@
         "spam_aliases": "Pagaidu e-pasta aizstājvārdi",
         "spamfilter": "Mēstuļu filtrs",
         "spamfilter_behavior": "Reitings",
-        "spamfilter_bl": "Melnais saraksts",
-        "spamfilter_bl_desc": "No melnajā sarakstā iekļautajām e-pasta adresēm saņemtās vēstules <b>vienmēr</b> tiks atzīmētas kā mēstules un noraidītas. Noraidītais pasts <b>netiks</b> ievietots karantīnā. Var izmantot aizstājzīmes. Atlasīšana tiek pielietota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
+        "spamfilter_bl": "Liegumu saraksts",
+        "spamfilter_bl_desc": "No lieguma sarakstā iekļautajām e-pasta adresēm saņemtās vēstules <b>vienmēr</b> tiks atzīmētas kā mēstules un noraidītas. Noraidītais pasts <b>netiks</b> ievietots karantīnā. Var izmantot aizstājzīmes. Atlasīšana tiek pielietota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
         "spamfilter_default_score": "Noklusējuma vērtības",
         "spamfilter_green": "Zaļš: šī nav mēstule",
-        "spamfilter_hint": "Pirmā vērtība norāda uz zemu \"Spam vērtējumu\" vērtējumu, otra vērtība par \"Augstu spam vērtējumu\".",
+        "spamfilter_hint": "Pirmā vērtība norāda uz zemu \"mēstules novērtējumu\", otrā atspoguļo \"augstu mēstules novērtējumu\".",
         "spamfilter_red": "Sarkans: Šī vēstule noteikti ir spams un tiek nekavējoties noraidīta",
         "spamfilter_table_action": "Darbība",
         "spamfilter_table_add": "Pievienot vienību",
@@ -611,8 +631,8 @@
         "spamfilter_table_empty": "Nav datu ko parādīt",
         "spamfilter_table_remove": "noņemt",
         "spamfilter_table_rule": "Noteikums",
-        "spamfilter_wl": "Baltais saraksts",
-        "spamfilter_wl_desc": "No baltā saraksta e-pasta adresēm saņemtās vēstules <b>nekad</b> netiks atzīmētas kā mēstules. Var tikt izmantotas aizstājzīmes. Atlase tiek piemērota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
+        "spamfilter_wl": "Atļautais saraksts",
+        "spamfilter_wl_desc": "No atļautā saraksta e-pasta adresēm saņemtās vēstules <b>nekad</b> netiks atzīmētas kā mēstules. Var tikt izmantotas aizstājzīmes. Atlase tiek piemērota tikai tiešiem aizstājvārdiem (aizstājvārdiem ar vienu mērķa pastkasti), izņemot visu tverošos aizstājvārdus un pašu pastkasti.",
         "spamfilter_yellow": "Dzeltens: šī vēstule visticamāk ir spams un tiks pārvietota uz Junk mapi",
         "status": "Status",
         "sync_jobs": "Sinhronizācijas uzdevumi",
@@ -644,15 +664,21 @@
         "change_password_hint_app_passwords": "Kontā ir %d lietotņu paroles, kas netiks mainītas. Lai pārvaldītu tās, jādodas uz cilni \"Lietotņu paroles\".",
         "with_app_password": "ar lietotnes paroli",
         "apple_connection_profile_with_app_password": "Jauna lietotnes parole ir izveidota un pievienota profilam, lai ierīces iestatīšanas laikā nebūtu nepieciešams ievadīt paroli. Lūgums nekopīgot datni, jo tā nodrošina pilnu piekļuvi pastkastei.",
-        "tfa_info": "Divpakāpju autentificēšanās palīdz aizsargāt kontu.Ja tā ir iespējota, var būt nepieciešamas lietotņu paroles, lai pieteiktos lietotnēs vai pakalpojumos, kas nenodrošina divpakāpju autentificēšanos (piem., e-pasta klienti).",
+        "tfa_info": "Divpakāpju autentificēšanās palīdz aizsargāt kontu.Ja tā ir iespējota, ir nepieciešamas lietotņu paroles, lai pieteiktos lietotnēs vai pakalpojumos, kas nenodrošina divpakāpju autentificēšanos (piem., e-pasta klienti).",
         "app_passwds": "Lietotņu paroles",
-        "create_app_passwd": "Izveidot lietotnes paroli"
+        "create_app_passwd": "Izveidot lietotnes paroli",
+        "empty": "Nav iznākuma",
+        "quarantine_notification_info": "Tiklīdz paziņojums ir nosūtīts, vienumi tiks atzīmēti kā \"paziņoti\", un par šo vienumu vairs netiks sūtīti paziņojumi.",
+        "sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">Sūtītāja pārbaude ir atspējota</span>",
+        "syncjob_last_run_result": "Pēdējās izpildes iznākums"
     },
     "datatables": {
         "paginate": {
             "first": "Pirmā",
             "last": "Pēdējā"
-        }
+        },
+        "emptyTable": "Tabulā nav datu",
+        "search": "Meklēt:"
     },
     "debug": {
         "last_modified": "Pēdējoreiz mainīts",

+ 153 - 148
data/web/lang/lang.si-si.json

@@ -42,7 +42,7 @@
         "app_name": "Ime aplikacije",
         "app_password": "Dodaj geslo aplikacije",
         "app_passwd_protocols": "Dovoljeni protokoli za geslo aplikacije",
-        "automap": "Poskusi samodejno preslikati mape (\"Sent items\", \"Sent\" => \"Poslano\" ipd.)",
+        "automap": "Poskusi samodejno preslikati mape (\"Poslani elementi\", \"Poslano\" => \"Poslano\" ipd.)",
         "backup_mx_options": "Možnosti posredovanja (relay)",
         "comment_info": "Zasebni komentarji niso vidni uporabnikom, javni komentarji pa so prikazani kot opis, ko se z miško postavimo nad uporabnika v pregledu",
         "custom_params": "Parametri po meri",
@@ -109,7 +109,9 @@
         "relay_transport_info": "<div class=\"badge fs-6 bg-info\">Info</div> Definirate lahko preslikave transportov za cilj po meri za to domeno. Če ni nastavljena, se ustvari MX poizvedba.",
         "syncjob_hint": "Pozor! Gesla se morajo shraniti v golo besedilo!",
         "timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja",
-        "dry": "Simuliraj sinhronizacijo"
+        "dry": "Simuliraj sinhronizacijo",
+        "internal": "Notranje",
+        "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen."
     },
     "admin": {
         "access": "Dostop",
@@ -150,7 +152,7 @@
         "customize": "Prilagodi",
         "destination": "Cilj",
         "dkim_add_key": "Dodaj ARC/DKIM ključ",
-        "dkim_domains_selector": "Izbira",
+        "dkim_domains_selector": "Izbirnik",
         "dkim_domains_wo_keys": "Izberi domene z manjkajočimi ključi",
         "dkim_from": "Od",
         "dkim_from_title": "Izvorna domena od katere prekopiram podatke",
@@ -176,8 +178,8 @@
         "f2b_filter": "Regex filtri",
         "f2b_max_attempts": "Največ poskusov",
         "f2b_max_ban_time": "Maksimalno trajanje blokade (s)",
-        "f2b_netban_ipv4": "velikost subneta IPv4 za blokiranje (8-32)",
-        "f2b_netban_ipv6": "Velikost subneta IPv6 za blokiranje (8-128)",
+        "f2b_netban_ipv4": "velikost podomrežja IPv4 za blokiranje (8-32)",
+        "f2b_netban_ipv6": "Velikost podomrežja IPv6 za blokiranje (8-128)",
         "f2b_parameters": "Fail2ban parametri",
         "f2b_regex_info": "Upoštevajo se dnevniki SOGo, Postfix, Dovecot, PHP-FPM.",
         "f2b_retry_window": "Upoštevan čas (s) za največ poskusov",
@@ -187,41 +189,41 @@
         "generate": "ustvari",
         "guid": "GUID - enolični ID instance",
         "guid_and_license": "GUID & licenca",
-        "hash_remove_info": "Odstranitev hasha za omejitev (če obstaja) bo povsem ponastavilo njen števec.<br>\n  Vsak hash je prikazan z individualno barvo.",
-        "help_text": "Zamenjaj tekst za pomoč pod masko za prijavo (HTML je dovoljen)",
+        "hash_remove_info": "Odstranitev zgoščene vrednosti za omejitev (če obstaja) bo povsem ponastavilo njen števec.<br>\n  Vsaka zgoščena vrednost je prikazana z individualno barvo.",
+        "help_text": "Preglasi besedilo za pomoč pod masko za prijavo (HTML je dovoljen)",
         "host": "Gostitelj",
         "html": "HTML",
         "import": "Uvozi",
         "import_private_key": "Uvozi zasebni ključ",
-        "in_use_by": "V uporabi",
+        "in_use_by": "V uporabi od",
         "inactive": "Neaktivno",
         "include_exclude": "Vključi/Izključi",
         "include_exclude_info": "Privzeto - če ni izbire - so vključeni <b>vsi poštni predali</b>",
         "includes": "Vključi te prejemnike",
-        "ip_check": "Kontrola IP",
-        "ip_check_disabled": "Kontrola IP je onemogočena. Lahko jo omogočite pod <br/> <strong>Sistem > Konfiguracija > Možnosti > Prilagodi</strong>",
-        "ip_check_opt_in": "Opt-in za uporabo zunanje storitve <strong>ipv4.mailcow.email</strong> in <strong>ipv6.mailcow.email</strong> za razreševanje zunanjih IP.",
-        "is_mx_based": "Glede na MX",
-        "last_applied": "Nazadnje aplicirano",
+        "ip_check": "Preverjanje IP-ja",
+        "ip_check_disabled": "Preverjanje IP-ja je onemogočeno. Lahko ga omogočite pod <br/> <strong>Sistem > Konfiguracija > Možnosti > Prilagodi</strong>",
+        "ip_check_opt_in": "Prijavite se za uporabo storitev tretjih oseb <strong>ipv4.mailcow.email</strong> in <strong>ipv6.mailcow.email</strong> za razreševanje zunanjih IP naslovov.",
+        "is_mx_based": "Glede na MX zapis",
+        "last_applied": "Nazadnje uporabljeno",
         "link": "Povezava",
         "loading": "Prosim počakajte...",
         "login_time": "Čas prijave",
-        "logo_info": "Vaša slika bo pomanjšana na velikost 40px za zgornjo navigacijo in največjo velikost 250px za začetno stran. Zelo priporočena je uporaba grafike brez izgube kakovosti ob spremembi velikosti.",
+        "logo_info": "Vaša slika bo pomanjšana na višino 40 slikovnih pik za zgornjo navigacijsko vrstico in na največjo širino 250 slikovnih pik za začetno stran. Zelo priporočljiva je skalabilna grafika.",
         "message": "Sporočilo",
         "message_size": "Velikost sporočila",
         "nexthop": "Naslednji skok",
         "no": "&#10005;",
         "no_active_bans": "Ni aktivnih blokad",
-        "no_new_rows": "Ni dodatnih vrstic",
+        "no_new_rows": "Nadaljnjih vrstic ni na voljo",
         "no_record": "Ni zapisa",
         "oauth2_apps": "OAuth2 aplikacije",
         "oauth2_add_client": "Dodaj OAuth2 klienta",
-        "oauth2_client_id": "ID klienta",
-        "oauth2_client_secret": "Skrivnost (secret)",
+        "oauth2_client_id": "ID odjemalca",
+        "oauth2_client_secret": "Skrivnost odjemalca",
         "oauth2_redirect_uri": "URI za preusmeritev",
-        "oauth2_renew_secret": "Generiraj nov client secret",
-        "oauth2_revoke_tokens": "Zavrni vse tokene klientov",
-        "optional": "opcijsko",
+        "oauth2_renew_secret": "Generiraj novo skrivnost odjemalca",
+        "oauth2_revoke_tokens": "Prekliči vse žetone odjemalca",
+        "optional": "neobvezno",
         "options": "Možnosti",
         "password": "Geslo",
         "password_length": "Dolžina gesla",
@@ -236,21 +238,21 @@
         "private_key": "Zasebni ključ",
         "quarantine": "Karantena",
         "quarantine_bcc": "Pošlji kopijo vseh obvestil (BCC) temu prejemniku:<br><small>Pustite prazno za izklop te funkcije. <b>Nepodpisana, nepreverjena pošta. Uporabljalo naj bi se samo za interno dostavo.</b></small>",
-        "quarantine_exclude_domains": "Izključi domene in alias-domene",
-        "quarantine_max_age": "Maksimalna starost v dnevnih<br><small>Vrednost mora biti večja ali enaka 1 dnevu</small>",
-        "quarantine_max_score": "Opusti obvestilo, če je ocena spama večja od te vrednosti:<br><small>Privzeto 9999.0</small>",
-        "quarantine_max_size": "Največja velikost v MiB (Večji elementi so zavrženi):<br><small>0 <b>ne</b> pomeni neomejeno.</small>",
-        "quarantine_notification_html": "Predloga sporočila za obvestilo:<br><small>Pustite prazno za obnovitev privzete predloge.</small>",
-        "quarantine_notification_sender": "Pošiljatelj obvestila",
-        "quarantine_notification_subject": "Naslov obvestila",
-        "quarantine_release_format": "Oblika sproščenih elementov",
+        "quarantine_exclude_domains": "Izključi domene in vzdevke domen",
+        "quarantine_max_age": "Najvišja starost v dneh<br><small>Vrednost mora biti enaka ali večja od 1 dneva.</small>",
+        "quarantine_max_score": "Zavrzi obvestilo, če je ocena neželene pošte višja od te vrednosti:<br><small>Privzeto 9999,0</small>",
+        "quarantine_max_size": "Največja velikost v MiB (večji elementi so zavrženi):<br><small>0 <b>ne</b> pomeni neomejeno.</small>",
+        "quarantine_notification_html": "Predloga za obvestilo po e-pošti:<br><small>Pustite prazno, če želite obnoviti privzeto predlogo.</small>",
+        "quarantine_notification_sender": "Pošiljatelj obvestil po e-pošti",
+        "quarantine_notification_subject": "Zadeva e-poštnega obvestila",
+        "quarantine_release_format": "Oblika izdanih elementov",
         "quarantine_release_format_att": "Kot priponka",
-        "quarantine_release_format_raw": "Nespremenjen original",
-        "quarantine_retention_size": "Število zadržanj na poštni predal: <br><small>0 pomeni <b>neaktivno</b>,</small>",
+        "quarantine_release_format_raw": "Nespremenjen izvirnik",
+        "quarantine_retention_size": "Hrambe na poštni predal:<br><small>0 pomeni <b>neaktivno</b>.</small>",
         "quota_notification_sender": "Pošiljatelj obvestila",
         "quota_notification_subject": "Predmet obvestila",
-        "quota_notifications": "Obvestila o omejitvi",
-        "quota_notifications_info": "Obvestila o omejitvi so poslana uporabnikom enkrat, ko presežejo 80% in enkrat ko presežejo 95% zasedenosti.",
+        "quota_notifications": "Obvestila o kvotah",
+        "quota_notifications_info": "Obvestila o kvoti se uporabnikom pošljejo enkrat, ko presežejo 80 % in enkrat, ko presežejo 95 % porabe.",
         "queue_unban": "odblokiraj",
         "r_active": "Aktivne omejitve",
         "r_inactive": "Neaktivne omejitve",
@@ -266,8 +268,8 @@
         "remove": "Odstrani",
         "remove_row": "Odstrani vrstico",
         "reset_default": "Ponastavi na privzeto",
-        "reset_limit": "Odstrani hash",
-        "routing": "Routing",
+        "reset_limit": "Odstrani zgoščeno vrednost",
+        "routing": "Usmerjanje",
         "rsetting_add_rule": "Dodaj pravilo",
         "rsetting_content": "Vsebina pravila",
         "rsetting_desc": "Kratek opis",
@@ -275,10 +277,10 @@
         "rsetting_none": "Ni pravil na voljo",
         "rsettings_insert_preset": "Vstavi prednastavljen primer \"%s\"",
         "rsettings_preset_1": "Onemogoči vse razen DKIM in omejitve za prijavljene uporabnike",
-        "rsettings_preset_2": "Postmasterji želijo spam",
-        "rsettings_preset_3": "Dovoli samo specifične pošiljatelje za poštni predal (npr. uporaba samo kot interni poštni predal)",
+        "rsettings_preset_2": "Poštni upravitelji želijo neželeno pošto",
+        "rsettings_preset_3": "Dovoli samo določene pošiljatelje za poštni predal (tj. uporabo samo kot notranji poštni predal)",
         "rsettings_preset_4": "Onemogoči Rspamd za domeno",
-        "rspamd_com_settings": "Ime nastavitve bo samodejno generirano. Prosim oglejte si primere nastavitev spodaj. Za več informacij si oglejte <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">dokumentacijo Rspamd</a>",
+        "rspamd_com_settings": "Ime nastavitve bo samodejno ustvarjeno, oglejte si spodnje primere prednastavitev. Za več podrobnosti glejte <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">dokumentacijo Rspamd</a>",
         "rspamd_global_filters": "Globalne preslikave filtrov",
         "rspamd_global_filters_agree": "Previden bom!",
         "rspamd_global_filters_info": "Globalni filtri vsebujejo različne vrste globalnih seznamov zavrnjenih in dovoljenih vsebin.",
@@ -293,30 +295,30 @@
         "f2b_list_info": "Gostitelj ali omrežje na seznamu zavrnjenih bo vedno imelo prednost pred entiteto na seznamu dovoljenih. <b>Posodobitve seznama bodo trajale nekaj sekund, da se uporabijo.</b>",
         "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. <br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"Naročilo SAL\">Registrirajte svoj GUID tukaj</a> ali <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Naročilo podpora\">Kupite podporo za svojo namestitev Mailcow.</a>",
-        "lookup_mx": "Cilj je regular expression za ujemanje MX zapisov (<code>.*\\.google\\.com</code> za usmeritev vse pošte na MX, ki se konča z google.com, preko tega skoka)",
+        "forwarding_hosts_hint": "Dohodna sporočila so brezpogojno sprejeta od katerih koli gostiteljev v tem seznamu. Ti gostitelji se ne bodo preverjali po DNSBL seznamih in ne bodo dodani v listo sivih. Prejeta neželena pošta s teh gostiteljev ni nikoli zavrnjena, opcijsko pa se lahko premakne v mapo neželene pošte. Najpogostejša uporaba za to je navedba poštnih strežnikov, iz katerih ste nastavili pravilo za posredovanje pošte na vaš mailcow strežnik.",
+        "license_info": "Licenca ni zahtevana, a pomaga pri nadaljnjem razvoju. <br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"Naročilo SAL\">Registrirajte svoj GUID tukaj</a> ali <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Naročilo podpore\">Kupite podporo za svojo namestitev Mailcow.</a>",
+        "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (<code>.*\\.google\\.com</code> za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka).",
         "main_name": "Naziv \"mailcow UI\"",
         "merged_vars_hint": "Sive vrstice so združene iz <code>vars.(local.)inc.php</code> in jih ni mogoče spremeniti.",
-        "oauth2_info": "OAuth2 implementacija omogoča grant vrste \"Authorization code\" in izdaja refresh tokene.<br>\nStrežnik prav tako izda nove refresh tokene, ko je bil refresh token uporabljen<br><br>\n&#8226; Privzeti obseg je <i>profile</i>. Samo uporabniki poštnih predalov se lahko prijavijo s pomočjo OAuth2. Če parameter obsega ni vnesen, se nastavi na <i>profile</i>.<br>\n&#8226; Parameter <i>state</i> mora biti poslan s strani klienta kot del zahtevka za avtorizacijo .<br><br>\nPoti za OAuth2 API: <br>\n<ul>\n  <li>Endpoint za avtorizacijo: <code>/oauth/authorize</code></li>\n  <li>Endpoint za tokene: <code>/oauth/token</code></li>\n  <li>Stran vira: <code>/oauth/profile</code></li>\n</ul>\nPonovno generiranje client secret ne bo razveljavilo obstoječih avtorizacijskih kod, ne bodo pa mogle obnoviti svoje tokene.<br><br>\nZavrnitev client tokenov bo povzročilo tekojčno prekinitev aktivnih sej. Vsi klienti se bodo morali ponovno prijaviti.",
-        "quarantine_redirect": "<b>Preusmeri vsa obvestila</b> k temu prejemniku:<br><small>Pustite prazno, da onemogočite. <b>Nepodpisana, nepreverjena pošta. Uporabljalo bi se naj samo za interno dostavo.</b></small>",
+        "oauth2_info": "Implementacija OAuth2 podpira vrsto odobritve »Avtorizacijska koda« in izda osvežilne žetone.<br>\nStrežnik samodejno izda tudi nove osvežilne žetone, ko je žeton za osvežitev uporabljen.<br><br>\n&#8226; Privzeti obseg je <i>profile</i>. Prek OAuth2 je mogoče overiti samo uporabnike poštnega predala. Če parameter obsega izpustite, se vrne na <i>profile</i>.<br>\n&#8226; Parameter <i>state</i> mora odjemalec poslati kot del zahteve za avtorizacijo.<br><br>\nPoti za zahteve do API-ja OAuth2: <br>\n<ul>\n<li>Končna točka avtorizacije: <code>/oauth/authorize</code></li>\n<li>Končna točka žetona: <code>/oauth/token</code></li>\n<li>Stran z viri: <code>/oauth/profile</code></li>\n</ul>\nPonovno ustvarjanje skrivnosti odjemalca ne bo poteklo obstoječih kod za avtorizacijo, vendar ne bo obnovilo žetona.<br><br>\nPreklic žetonov odjemalca bo povzročil takojšnjo prekinitev vseh aktivnih sej. Vse stranke se morajo ponovno overiti.",
+        "quarantine_redirect": "<b>Preusmerite vsa obvestila</b> temu prejemniku:<br><small>Pustite prazno, če želite onemogočiti. <b>Nepodpisana, nepreverjena pošta. Dostavljeno samo interno.</b></small>",
         "quota_notification_html": "Predloga sporočila za obvestilo:<br><small>Pustite prazno za obnovitev privzete predloge.</small>",
-        "quota_notifications_vars": "{{percent}} pomeni trenutna omejitev uporabnika<br>{{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. <br>Nove elemente lahko dodate v <code>inc/vars.local.inc.php</code> da jih lahko vklopite ali izklopite.",
-        "relayhosts_hint": "Določite transporte glede na pošiljatelja, da jih lahko izberete v konfiguraciji domene.<br>\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.<br>\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": "&#8226; 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. <code>/.+@domain\\.tld/i</code>).<br>\nČeprav se v vsaki vrstici regexa izvedejo osnovni pregledi, je lahko funkcionalnost programa Rspamd motena, če sintaksa ni pravilna.<br>\nRspamd bo poskušal prebrati vsebino preslikave, ko bo spremenjena. Če imate težave, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">ponovno zaženite Rspamd</a>, da prisilite ponovno nalaganje preslikav.<br> Elementi na seznamu zavrnjenih so izključeni iz karantene.",
+        "quota_notifications_vars": "{{percent}} je enako trenutni kvoti uporabnika<br>{{username}} je ime poštnega predala",
+        "r_info": "Sivi/onemogočeni elementi v seznamu aktivnih omejitev niso znane kot veljavne omejitve za mailcow in ne morejo biti premaknjene. Neznane omejitve bodo kljub temu nastavljene po vrstnem redu pojavljanja. <br>Nove elemente lahko dodate v <code>inc/vars.local.inc.php</code> da jih lahko vklopite ali izklopite.",
+        "relayhosts_hint": "Določite transporte, odvisne od pošiljatelja, da jih boste lahko izbrali v pogovornem oknu za konfiguracijo domen.<br>\n  Transportna storitev je vedno »smtp:« in bo zato poskusila s TLS, ko bo ponujena. Zaviti TLS (SMTPS) ni podprt. Upošteva se individualna nastavitev pravilnika za odhodni TLS uporabnika.<br>\n  Vpliva na izbrane domene, vključno z vzdevki domen.",
+        "transport_dest_format": "Regex ali sintaksa: example.org, .example.org, *, box@example.org (več vrednosti je lahko ločenih z vejicami)",
+        "transport_test_rcpt_info": "&#8226; Za preizkus posredovanja v tujino uporabite null@hosted.mailcow.de.",
+        "rspamd_global_filters_regex": "Njihova imena pojasnjujejo njihov namen. Vsa vsebina mora vsebovati veljaven regularni izraz v obliki »/vzorec/možnosti« (npr. <code>/.+@domena\\.tld/i</code>).<br>\n  Čeprav se v vsaki vrstici regularnega izraza izvajajo osnovna preverjanja, je lahko funkcionalnost Rspamdsa pokvarjena, če sintakse ne prebere pravilno.<br>\n  Rspamd bo poskušal prebrati vsebino zemljevida, ko se bo spremenila. Če pride do težav, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">znova zaženite Rspamd</a>, da uveljavite ponovno nalaganje zemljevida.<br>Elementi na seznamu zavrnjenih so izključeni iz karantene.",
         "rspamd_settings_map": "Preslikava nastavitev Rspamd",
         "sal_level": "Moo stopnja",
         "save": "Shrani spremembe",
         "search_domain_da": "Išči domene",
         "send": "Pošlji",
         "sender": "Pošiljatelj",
-        "service": "Servis",
-        "service_id": "ID servisa",
+        "service": "Storitev",
+        "service_id": "ID storitve",
         "source": "Vir",
-        "spamfilter": "Spam filter",
+        "spamfilter": "Filter neželene pošte",
         "subject": "Predmet",
         "success": "Uspešno",
         "sys_mails": "Sistemska pošta",
@@ -326,7 +328,7 @@
         "title_name": "Naziv spletnega mesta \"mailcow UI\"",
         "to_top": "Nazaj na vrh",
         "transport_maps": "Preslikave transportov",
-        "transports_hint": "&#8226; Vpis preslikave transporta <b>nadredi</b> preslikavo transporta odvisno od pošiljatelja.<br>\n&#8226; Preferenčno se uporabljajo transporti glede na MX zapise.<br>\n&#8226; Izhodne TLS politike na uporabnika so ignorirane in se lahko vsilijo samo s preslikavami TLS politik.<br>\n&#8226; Transportni servis za definirane transporte je vedno \"smtp:\" in bo posledično poskušal TLS ko bo ponujeno. Wrapped TLS (SMTPS) ni podprto.<br>\n&#8226; Naslovi, ki se ujemajo z \"/localhost$/\" bodo vedno preneseni preko \"local:\", in zato destinacija \"*\" ne bo vplivala na te naslove.<br>\n&#8226; Za določitev poverilnic za naslednji skok (npr. \"[host]:25\"), Postfix <b>vedno</b> preveri \"host\" preden išče \"[host]:25\". Zaradi takšnega obnašanja je nemogoče hkrati uporabiti \"host\" in \"[host]:25\".",
+        "transports_hint": "&#8226; Vnos preslikave transporta <b>preglasi</b> preslikavo transporta, ki je odvisen od pošiljatelja.<br>\n&#8226; Po možnosti se uporabljajo transporti, ki temeljijo na MX.<br>\n&#8226; Nastavitve pravilnika TLS za odhodne uporabnike se prezrejo in jih je mogoče uveljaviti le z vnosi v zemljevidu pravilnika TLS.<br>\n&#8226; Storitev transporta za definirane transporte je vedno »smtp:« in bo zato poskusila s TLS, ko bo ponujena. Zaviti TLS (SMTPS) ni podprt.<br>\n&#8226; Naslovi, ki se ujemajo z \"/localhost$/\" bodo vedno preneseni preko \"local:\", in zato cilj \"*\" ne bo veljal za te naslove.<br>\n&#8226; Za določitev poverilnic za zgledni naslednji skok \"[host]:25\", Postfix <b>vedno</b> poišče \"host\" preden poišče \"[host]:25\". Zaradi tega vedenja je nemogoče hkrati uporabljati \"host\" in \"[host]:25\".",
         "ui_footer": "Noga (HTML dovoljen)",
         "ui_header_announcement": "Obvestila",
         "ui_header_announcement_active": "Nastavi obvestilo kot aktivno",
@@ -338,7 +340,7 @@
         "ui_header_announcement_type_info": "Info",
         "ui_header_announcement_type_warning": "Pomembno",
         "ui_texts": "Oznake in besedila UI",
-        "unban_pending": "unban v postopku",
+        "unban_pending": "odblokada v teku",
         "unchanged_if_empty": "Če je nespremenjeno, pustite prazno",
         "upload": "Naloži",
         "username": "Uporabniško ime",
@@ -393,7 +395,7 @@
         "iam_token_url": "Končna točka žetona",
         "iam_userinfo_url": "Končna točka z uporabniškimi podatki",
         "iam_username_field": "Polje z uporabniškim imenom",
-        "iam_binddn": "Povezava DN",
+        "iam_binddn": "Vezava DN",
         "iam_use_ssl": "Uporabi SSL",
         "iam_use_tls": "Uporabi StartTLS",
         "iam_version": "Različica",
@@ -412,9 +414,9 @@
         "needs_restart": "potreben je ponovni zagon"
     },
     "danger": {
-        "alias_goto_identical": "Alias in goto naslov morata biti identična",
-        "aliasd_targetd_identical": "Alias domena ne sme biti enaka ciljni domeni: %s",
-        "bcc_exists": "BCC preslikava obstaja za vrsto %s",
+        "alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati.",
+        "aliasd_targetd_identical": "Vzdevek domene ne sme biti enak ciljni domeni: %s",
+        "bcc_exists": "Za tip %s obstaja BCC preslikava %s",
         "dkim_domain_or_sel_exists": "DKIM ključ za \"%s\" obstaja in ne bo prepisan",
         "domain_quota_m_in_use": "Kvota domene mora biti večja ali enaka %s MiB",
         "extra_acl_invalid_domain": "Zunanji pošiljatelj \"%s\" uporablja neveljavno domeno",
@@ -423,71 +425,71 @@
         "invalid_nexthop": "Oblika naslednjega skoka ni veljavna",
         "invalid_nexthop_authenticated": "Naslednji skok obstaja z drugačnimi poverilnicami. Prosim najprej posodobite obstoječe poverilnice za ta naslednji skok.",
         "demo_mode_enabled": "Demo način je omogočen",
-        "access_denied": "Dostop zavrnjen ali pa so podatki obrazca napačni",
-        "alias_domain_invalid": "Alias domena %s ni veljavna",
-        "alias_empty": "Alias naslov ne sme biti prazen",
-        "alias_invalid": "Alias naslov %s ni veljaven",
-        "aliases_in_use": "Max. aliasov mora biti večje ali enako %d",
-        "app_name_empty": "Naziv aplikacije ne more biti prazno",
-        "app_passwd_id_invalid": "ID gesla aplikacije %s je neveljaven",
-        "bcc_empty": "BCC cilj ne more biti prazen",
-        "bcc_must_be_email": "BCC cilj %s ni veljaven e-poštni naslov",
+        "access_denied": "Dostop zavrnjen ali neveljavni podatki obrazca",
+        "alias_domain_invalid": "Vzdevek domene %s ni veljaven",
+        "alias_empty": "Naslov vzdevka ne sme biti prazen",
+        "alias_invalid": "Naslov vzdevka %s ni veljaven",
+        "aliases_in_use": "Največje število vzdevkov mora biti večje ali enako %d",
+        "app_name_empty": "Ime aplikacije ne sme biti prazno",
+        "app_passwd_id_invalid": "ID gesla za aplikacijo %s neveljaven",
+        "bcc_empty": "Polje za prejemnika BCC ne sme biti prazno",
+        "bcc_must_be_email": "Cilj BCC %s ni veljaven e-poštni naslov",
         "comment_too_long": "Komentar je predolg, dovoljeno je največ 160 znakov",
         "defquota_empty": "Privzeta kvota na poštni predal ne more biti 0.",
-        "description_invalid": "Opis resursa za %s ni veljaven",
+        "description_invalid": "Opis vira za %s je neveljaven",
         "dkim_domain_or_sel_invalid": "Domena ali izbirnik DKIM ni veljaven: %s",
         "domain_cannot_match_hostname": "Domena se ne more ujemati z imenom gostitelja",
         "domain_exists": "Domena %s že obstaja",
-        "domain_invalid": "Manjka ali napačno ime domene",
-        "domain_not_empty": "Ne morem odstraniti ne-prazno domeno %s",
+        "domain_invalid": "Ime domene je prazno ali neveljavno",
+        "domain_not_empty": "Neprazne domene %s ni mogoče odstraniti",
         "domain_not_found": "Domene %s ni bilo mogoče najti",
         "extended_sender_acl_denied": "manjka ACL za določitev naslovov zunanjih pošiljateljev",
         "extra_acl_invalid": "Naslov zunanjega pošiljatelja \"%s\" ni veljaven",
         "fido2_verification_failed": "Preverjanje FIDO2 ni uspelo: %s",
-        "file_open_error": "Datoteka ne more biti odprta za urejanje",
+        "file_open_error": "Datoteke ni mogoče odpreti za pisanje",
         "filter_type": "Napačna vrsta filtra",
-        "from_invalid": "Pošiljatelj ne sme biti prazno",
+        "from_invalid": "Polje za pošiljatelja ne sme biti prazno",
         "global_filter_write_error": "Ni mogoče zapisati datoteke filtra: %s",
         "global_map_invalid": "ID globalne preslikave %s ni veljaven",
-        "goto_empty": "Alias naslov mora vsebovati vsaj en veljaven goto naslov",
-        "goto_invalid": "Goto naslov %s ni veljaven",
+        "goto_empty": "Naslov vzdevka mora vsebovati vsaj en veljaven ciljni naslov",
+        "goto_invalid": "Ciljni naslov %s ni veljaven",
         "ham_learn_error": "Napaka pri učenju Ham: %s",
-        "imagick_exception": "Napaka: Imagick napaka pri branju slike",
+        "imagick_exception": "Napaka: Izjema Imagick med branjem slike",
         "img_invalid": "Ni možno preveriti slikovne datoteke",
         "invalid_bcc_map_type": "Neveljavna vrsta preslikave BCC",
         "invalid_destination": "Ciljna oblika \"%s\" ni veljavna",
         "invalid_filter_type": "Neveljavna vrsta filtra",
         "invalid_host": "Naveden je neveljaven gostitelj (host): %s",
-        "invalid_mime_type": "Neveljaven mime type",
+        "invalid_mime_type": "Neveljavna vrsta MIME",
         "max_quota_in_use": "Kvota poštnega predala mora biti večja ali enaka %d MB",
         "password_complexity": "Geslo ne ustreza varnostni politiki",
-        "pushover_credentials_missing": "Manjka Pushover token ali ključ",
+        "pushover_credentials_missing": "Manjka žeton in/ali ključ Pushover",
         "release_send_failed": "Sporočila ni bilo mogoče sprostiti: %s",
-        "tls_policy_map_dest_invalid": "Cilj politike ni veljaven",
+        "tls_policy_map_dest_invalid": "Cilj pravilnika je neveljaven",
         "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",
+        "validity_missing": "Prosim določite 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)",
+        "ip_list_empty": "Seznam dovoljenih IP-jev ne sme biti prazen",
+        "is_alias": "%s je že znan kot naslov vzdevka",
+        "is_alias_or_mailbox": "%s je že znan kot vzdevek, poštni predal ali naslov vzdevka, razširjen iz vzdevka domene.",
+        "is_spam_alias": "%s je že znan kot začasni vzdevek (neželeni vzdevek)",
         "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_exceeded": "Kvota presega omejitev domene (največ %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_alias_exceeded": "Preseženo največje število vzdevkov",
         "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",
+        "network_host_invalid": "Nepravilno omrežje ali gostitelj: %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",
@@ -500,30 +502,30 @@
         "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",
+        "pushover_token": "Pushover žeton ni v pravilni obliki",
+        "quota_not_0_not_numeric": "Kvota mora biti numerična in >= 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",
+        "resource_invalid": "Ime vira %s je neveljavno",
+        "rl_timeframe": "Časovni okvir omejitve je nepravilen",
         "rspamd_ui_pw_length": "Rspamd UI geslo mora biti dolgo vsaj 6 znakov",
-        "script_empty": "Script ne more biti prazen",
+        "script_empty": "Skripta ne sme biti prazna",
         "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",
+        "sieve_error": "Napaka Sieve razčlenjevalnika: %s",
+        "spam_learn_error": "Napaka pri učenju neželene pošte: %s",
+        "subject_empty": "Zadeva ne sme biti prazna",
         "targetd_not_found": "Ciljna domena %s ni bila najdena",
-        "targetd_relay_domain": "Ciljna domena %s je relay domena",
+        "targetd_relay_domain": "Ciljna domena %s je posredovalna 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",
+        "tfa_token_invalid": "Neveljaven TFA žeton",
+        "tls_policy_map_entry_exists": "Vnos pravilnika preslikave TLS \"%s\" obstaja",
+        "tls_policy_map_parameter_invalid": "Parameter pravilnika je neveljaven",
         "totp_verification_failed": "Neuspešno preverjanje TOTP",
         "transport_dest_exists": "Cilj transporta \"%s\" že obstaja",
         "webauthn_verification_failed": "Preverjanje WebAuthn ni uspelo: %s",
@@ -557,7 +559,7 @@
         "version_invalid": "Različica %s je neveljavna"
     },
     "debug": {
-        "containers_info": "Informacije o vsebniku (containerju)",
+        "containers_info": "Informacije o zabojniku",
         "architecture": "Arhitektura",
         "chart_this_server": "Diagram (ta strežnik)",
         "container_running": "Aktiven",
@@ -571,23 +573,23 @@
         "external_logs": "Zunanji dnevniki",
         "last_modified": "Nazadnje spremenjeno",
         "history_all_servers": "Zgodovina (vsi strežniki)",
-        "in_memory_logs": "In-memory dnevniki",
-        "service": "Servis",
+        "in_memory_logs": "Dnevniki v pomnilniku",
+        "service": "Storitev",
         "show_ip": "Prikaži javni IP",
         "size": "Velikost",
         "started_at": "Zagnano ob",
         "started_on": "Zagnano na",
         "static_logs": "Statični dnevniki",
         "success": "Uspešno",
-        "system_containers": "Sistem in Containerji",
+        "system_containers": "Sistem in zabojniki",
         "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",
-        "log_info": "<p>mailcow <b>in-memory dnevniki</b> se zbirajo v Redis seznamih in se vsako minuto omejijo na LOG_LINES (%d) da se zmanjša obremenitev.\n  <br>In-memory dnevniki niso namenjeni trajnemu shranjevanju. Vse aplikacije, ki beležijo dnevnike in-memory, tudi beležijo v Docker daemon in posledično v privzeti gonilnik za dnevnik.\n  <br>In-memory dnevniki se naj uporabljajo za odpravljanje manjših napak s containerji.</p>\n  <p><b>Eksterni dnevniki</b> se zbirajo preko API-ja posamezne aplikacije.</p>\n  <p><b>Statični dnevniki</b> so večinoma dnevniki aktivnosti, ki se ne beležijo v Dockerd, a jih je vseeno treba hraniti (razen API dnevnikov).</p>",
+        "wip": "Trenutno delo v teku",
+        "log_info": "<p>Dnevniki v pomnilniku mailcow se zbirajo na seznamih Redis in vsako minuto skrajšajo na LOG_LINES (%d), da se zmanjša preobremenitev.\n  <br>Dnevniki v pomnilniku niso namenjeni trajnemu beleženju. Vse aplikacije, ki se beležijo v pomnilnik, se beležijo tudi v Dockerjev demon in s tem v privzeti gonilnik beleženja.</p>\n  </p>Vrsta dnevnika v pomnilniku se mora uporabljati za odpravljanje manjših težav s kontejnerji.</p>\n  <p><b>Zunanji dnevniki</b> se zbirajo prek API-ja dane aplikacije.</p>\n  <p><b>Statični dnevniki</b> so večinoma dnevniki dejavnosti, ki se ne beležijo v Dockerd, vendar morajo biti še vedno trajni (razen dnevnikov API-ja).</p>",
         "login_time": "Čas",
         "logs": "Dnevniki",
         "memory": "Spomin",
@@ -598,7 +600,7 @@
         "infoFiltered": "(filtrirano od _MAX_ skupaj zapisov)",
         "collapse_all": "Strni vse",
         "decimal": ",",
-        "emptyTable": "Ni podatkov",
+        "emptyTable": "V tabeli ni na voljo podatkov",
         "expand_all": "Razširi vse",
         "info": "Prikazano _START_ do _END_ od _TOTAL_ zapisov",
         "infoEmpty": "Prikazano 0 do 0 od 0 zapisov",
@@ -620,9 +622,9 @@
         }
     },
     "diagnostics": {
-        "cname_from_a": "Vrednost pridobljena iz A/AAAA zapisa. To je podprto, če zapis kaže na pravilen resurs.",
+        "cname_from_a": "Vrednost, izpeljana iz zapisa A/AAAA. To je podprto, če zapis kaže na pravilen vir.",
         "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_24hours": "Upoštevajte, da se lahko spremembe DNS-a pravilno odražajo na tej strani v 24 urah. Namenjena je temu, da si preprosto ogledate, kako konfigurirati zapise DNS, in preverite, ali so vsi vaši zapisi pravilno shranjeni v DNS-u.",
         "dns_records_data": "Pravilni podatki",
         "dns_records_docs": "Prosim preverite tudi <a target=\"_blank\" href=\"https://docs.mailcow.email/getstarted/prerequisite-dns\">dokumentacijo</a>.",
         "dns_records_name": "Ime",
@@ -633,60 +635,60 @@
     "edit": {
         "acl": "ACL (Dovoljenje)",
         "active": "Aktivno",
-        "allow_from_smtp": "Dovoli samo tem IP naslovom da uporabijo <b>SMTP</b>",
-        "bcc_dest_format": "Cilj BCC mora biti en veljaven email naslov.<br>Če morate poslati kopijo na več naslovov, ustvarite alias in ga uporabite tukaj.",
-        "automap": "Poskušaj samodejno preslikati mape (\"Sent items\", \"Sent\" => \"Poslano\" ipd.)",
+        "allow_from_smtp": "Dovoli samo tem IP naslovom uporabo <b>SMTP</b>",
+        "bcc_dest_format": "Ciljna stran za polje SKP (BCC) mora biti en veljaven e-poštni naslov.<br>Če morate kopijo poslati na več naslovov, ustvarite vzdevek in ga uporabite tukaj.",
+        "automap": "Poskusite samodejno preslikati mape (\"Poslani predmeti\", \"Poslano\" => \"Poslano\" itd.)",
         "admin": "Uredi skrbnika",
         "domain_footer_info_vars": {
-            "custom": "{= foo =}         - Če ima poštni predal atribut po meri \"foo\" z vrednostjo \"bar\", spremenljivka vrne \"bar\"",
-            "auth_user": "{= auth_user =}   - Prijavljeno uporabniško ime, ki ga določi MTA",
-            "from_user": "{= from_user =}   - leva stran email naslova uporabnika, npr. za \"moo@mailcow.tld\" vrne \"moo\"",
-            "from_name": "{= from_name =}   - Prikazno ime, npr. za \"Mailcow &lt;moo@mailcow.tld&gt;\" vrne \"Mailcow\"",
-            "from_addr": "{= from_addr =}   - e-poštni naslov \"Od\"",
-            "from_domain": "{= from_domain =} - domena e-poštnega naslova \"Od\""
+            "custom": "{= foo =}         - Če ima poštni predal atribut po meri \"foo\" z vrednostjo \"bar\", vrne \"bar\"",
+            "auth_user": "{= auth_user =}    - Preverjeno uporabniško ime, ki ga določi MTA",
+            "from_user": "{= from_user =}    - Iz uporabniškega dela ovojnice, npr. za \"moo@mailcow.tld\" vrne \"moo\"",
+            "from_name": "{= from_name =}    - Iz imena ovojnice, npr. za \"Mailcow &lt;moo@mailcow.tld&gt;\" vrne \"Mailcow\"",
+            "from_addr": "{= from_addr =}    - Del ovojnice z naslovom od",
+            "from_domain": "{= from_domain =} - Iz domenskega dela ovojnice"
         },
-        "dont_check_sender_acl": "Onemogoči kontrolo pošiljatelja za domeno %s (+ alias domene)",
+        "dont_check_sender_acl": "Onemogoči preverjanje pošiljatelja za domeno %s (+ vzdevki domen)",
         "pushover_title": "Naslov obvestila",
         "domains": "Domene",
-        "extended_sender_acl_info": "Če je DKIM domenski ključ na voljo, ga uvozite.<br>\n  Ne pozabite dodati ta strežnik k ustreznemu SPF TXT zapisu.<br>\n  Kadar koli je domena ali alias domena dodana k tem strežniku, ki se prekriva z zunanjim naslovom, je zunanji naslov odstranjen.<br>\n  uporabite @domain.tld da dovolite pošiljanje kot *@domain.tld.",
-        "lookup_mx": "Cilj je regular expression za ujemanje MX zapisov (<code>.*\\.google\\.com</code> za usmeritev vse pošte na MX, ki se konča z google.com, preko tega skoka)",
-        "maxbytespersecond": "Največ bytov na sekundo <br><small>(0 = neomejeno)</small>",
+        "extended_sender_acl_info": "Uvoziti je treba ključ domene DKIM, če je na voljo.<br>\n  Ne pozabite dodati tega strežnika v ustrezni zapis SPF TXT.<br>\n  Kadar koli je temu strežniku dodana domena ali vzdevek domene, ki se prekriva z zunanjim naslovom, se zunanji naslov odstrani.<br>\n  Uporabite @domain.tld, da omogočite pošiljanje kot *@domain.tld.",
+        "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (<code>.*\\.google\\.com</code> za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka).",
+        "maxbytespersecond": "Največ bajtov na sekundo <br><small>(0 = neomejeno)</small>",
         "pushover_sender_array": "Upoštevaj samo sledeče e-poštne naslove pošiljateljev <small>(ločeni z vejico)</small>",
-        "mbox_rl_info": "Ta omejitev velja za SASL uporabniško ime, preverja se ujemanje s katerim koli \"from\" naslovom, ki ga uporablja prijavljeni uporabnik. Omejitev pošiljanja za poštni predal preglasi pravilo omejitve za domeno.",
+        "mbox_rl_info": "Ta omejitev se uporabi za prijavno ime SASL in se ujema z naslovom \"od\", ki ga uporablja prijavljeni uporabnik. Omejitev poštnega nabiralnika preglasi omejitev za celotno domeno.",
         "kind": "Tip",
         "client_secret": "Skrivnost odjemalca",
         "comment_info": "Zasebni komentar ni viden uporabniku, javni komentar pa se prikaže kot opis orodja, ko nanj v pregledu uporabnika zadržite miško",
         "created_on": "Ustvarjeno",
         "custom_attributes": "Atributi po meri",
-        "delete1": "Izbriši na viru, ko je končano",
-        "delete2": "Izbriši sporočila na cilju, ki ne obstajajo na viru",
+        "delete1": "Izbriši iz vira, ko je končano",
+        "delete2": "Izbriši sporočila na cilju, ki niso na izvoru",
         "delete2duplicates": "Izbriši dvojnike na cilju",
         "delete_ays": "Prosim potrdite proces izbrisa.",
         "description": "Opis",
         "disable_login": "Onemogoči prijavo (dohodna pošta je še vedno sprejeta)",
         "domain": "Uredi domeno",
-        "domain_admin": "Uredi domenskega skrbnika",
+        "domain_admin": "Uredi skrbnika domene",
         "domain_footer": "Noga za celo domeno",
         "domain_footer_html": "HTML noga",
-        "pushover_vars": "Če ni definiran noben filter pošiljatelja, bodo upoštevana vsa sporočila.<br>Regex filtre in natančna preverjanja pošiljateljev je mogoče definirati posamezno in bodo obravnavani v nadaljevanju. Niso odvisni drug od drugega.<br>Uporabne spremenljivke za besedilo in naslov (prosimo, upoštevajte politike varstva podatkov)",
+        "pushover_vars": "Če filter pošiljatelja ni definiran, bodo upoštevana vsa e-poštna sporočila.<br>Filtre regularnih izrazov in natančna preverjanja pošiljateljev je mogoče definirati posamično in bodo obravnavana zaporedno. Niso odvisna drug od drugega.<br>Uporabne spremenljivke za besedilo in naslov (upoštevajte pravilnike o varstvu podatkov)",
         "pushover_verify": "Preveri poverilnice",
         "quota_mb": "Omejitev (MiB)",
-        "quota_warning_bcc": "BCC za sporočilo z opozorilom omejitve",
+        "quota_warning_bcc": "Opozorilo o kvoti BCC",
         "quota_warning_bcc_info": "Opozorila bodo poslana kot ločene kopije naslednjim prejemnikom. Zadevi bo v oklepaju dodano ustrezno uporabniško ime, na primer: <code>Opozorilo o kvoti (uporabnik@example.com)</code>.",
         "ratelimit": "Omejitev pošiljanja",
         "advanced_settings": "Napredne nastavitve",
-        "allow_from_smtp_info": "Pustite prazno da dovolite vse pošiljatelje.<br>IPv4/IPv6 naslovi in omrežja.",
+        "allow_from_smtp_info": "Pustite prazno, da dovolite vse pošiljatelje.<br>Naslovi in omrežja IPv4/IPv6.",
         "allowed_protocols": "Dovoljeni protokoli za neposreden dostop uporabnikov (ne vpliva na protokole za gesla aplikacij)",
         "app_name": "Ime aplikacije",
         "app_passwd": "Geslo aplikacije",
         "app_passwd_protocols": "Dovoljeni protokoli za geslo aplikacije",
-        "backup_mx_options": "Možnosti posredovanja (relay)",
-        "client_id": "Client ID",
-        "domain_footer_info": "Noge za celo domeno so dodane k vsem izhodnim e-poštnim sporočilom v tej domeni.<br> V nogi se lahko uporabijo sledeče spremenljivke:",
-        "domain_footer_plain": "PLAIN noga",
-        "domain_footer_skip_replies": "Ne dodajaj noge v odgovorih na e-poštna sporočila",
-        "domain_quota": "Omejitev (kvota) domene",
-        "edit_alias_domain": "Uredi alias domeno",
+        "backup_mx_options": "Možnosti posredovanja",
+        "client_id": "ID odjemalca",
+        "domain_footer_info": "Noge za celotno domeno so dodane vsem odhodnim e-poštnim sporočilom, povezanim z naslovom znotraj te domene. <br> Za nogo se lahko uporabijo naslednje spremenljivke:",
+        "domain_footer_plain": "NAVADNA noga",
+        "domain_footer_skip_replies": "Prezri nogo v odgovorih na e-poštna sporočila",
+        "domain_quota": "Kvota domene",
+        "edit_alias_domain": "Uredi vzdevek domene",
         "exclude": "Izključi objekte (regex)",
         "extended_sender_acl": "Naslovi zunanjih pošiljateljev",
         "force_pw_update": "Obvezna zamenjava gesla ob naslednji prijavi",
@@ -695,18 +697,18 @@
         "full_name": "Polno ime",
         "gal": "Globalni seznam naslovov (GAL)",
         "gal_info": "GAL vsebuje vse objekte v domeni in jih uporabniki ne morejo urejati. Če je onemogočeno, ni podatkov o o zasedenosti objekta! <b>Ponovno zaženite SOGo za uveljavitev sprememb.</b>",
-        "generate": "generiraj",
+        "generate": "ustvari",
         "grant_types": "Vrste dovoljenj",
         "hostname": "Ime gostitelja",
         "inactive": "Neaktivno",
         "last_modified": "Nazadnje spremenjeno",
         "mailbox": "Uredi poštni predal",
-        "mailbox_quota_def": "Privzeta omejitev/kvota za poštni predal",
-        "mailbox_relayhost_info": "Velja samo za poštni predal in neposredne aliase. Ne prepiše domenskega relay gostitelja.",
-        "max_aliases": "Največ aliasov",
-        "max_mailboxes": "Največ možnih poštnih predalov",
-        "max_quota": "Največja omejitev/kvota na poštni predal (MiB)",
-        "maxage": "Največja starost sporočil (v dnevih), po katerih bo poizvedeno iz oddaljenega vira <br><small>(0 = ne omejuj)</small>",
+        "mailbox_quota_def": "Privzeta kvota nabiralnika",
+        "mailbox_relayhost_info": "Uporablja se samo za poštni nabiralnik in neposredne vzdevke, preglasi gostitelja posredovalne domene.",
+        "max_aliases": "Največje število vzdevkov",
+        "max_mailboxes": "Največje možno število poštnih predalov",
+        "max_quota": "Največja kvota na poštni predal (MiB)",
+        "maxage": "Najvišja starost sporočil v dnevih, ki bodo prebrana z oddaljenega strežnika<br><small>(0 = prezri starost)</small>",
         "mins_interval": "Interval (min)",
         "multiple_bookings": "Več rezervacij",
         "none_inherit": "Brez / podeduj",
@@ -724,7 +726,7 @@
         "pushover_text": "Besedilo obvestila",
         "pushover_sound": "Zvok",
         "encryption": "Šifriranje",
-        "alias": "Uredi alias",
+        "alias": "Uredi vzdevek",
         "relayhost": "Prenosi, odvisni od pošiljatelja",
         "mailbox_rename_alias": "Samodejno ustvari vzdevek",
         "sender_acl_info": "Če lahko uporabnik poštnega predala A pošilja kot uporabnik poštnega predala B, se naslov pošiljatelja v SOGo ne prikaže samodejno kot izbirno polje \"od\".<br>\n  Uporabnik poštnega predala B mora v SOGo ustvariti pooblastilo, da lahko uporabnik poštnega predala A izbere svoj naslov kot pošiljatelja. Če želite pooblastiti poštni predal v SOGo, uporabite meni (tri pike) desno od imena vašega poštnega predala v zgornjem levem kotu v pogledu pošte. To vedenje ne velja za vzdevke.",
@@ -747,7 +749,7 @@
         "sogo_access": "Neposredno posredovanje na SOGo",
         "sogo_access_info": "Po prijavi je uporabnik samodejno preusmerjen na SOGo.",
         "sogo_visible": "Vzdevek je viden v SOGo",
-        "sogo_visible_info": "Ta možnost vpliva samo na objekte, ki jih je mogoče prikazati v SOGo (naslovi aliasov v skupni rabi ali brez nje, ki kažejo na vsaj en lokalni poštni predal). Če je skrita, vzdevek ne bo prikazan kot izbirni pošiljatelj v SOGo.",
+        "sogo_visible_info": "Ta možnost vpliva samo na objekte, ki jih je mogoče prikazati v SOGo (naslovi vzdevkov v skupni rabi ali brez nje, ki kažejo na vsaj en lokalni poštni predal). Če je skrita, vzdevek ne bo prikazan kot izbirni pošiljatelj v SOGo.",
         "spam_alias": "Ustvarjanje ali spreminjanje časovno omejenih vzdevkovnih naslovov",
         "spam_filter": "Filter neželene pošte",
         "spam_policy": "Dodajanje ali odstranjevanje elementov na seznam dovoljenih/zavrnjenih",
@@ -773,13 +775,15 @@
         "mta_sts_mode": "Način",
         "mta_sts_mode_info": "Na voljo so trije načini:<ul><li><em>testiranje</em> – pravilnik se samo spremlja, kršitve nimajo vpliva.</li><li><em>uveljavljanje</em> – pravilnik se strogo uveljavlja, povezave brez veljavnega TLS so zavrnjene.</li><li><em>brez</em> – pravilnik je objavljen, vendar se ne uporablja.</li></ul>",
         "mta_sts_max_age": "Najvišja starost",
-        "mta_sts_max_age_info": "Čas v sekundah, ki ga lahko prejemni poštni strežniki shranijo v predpomnilnik, dokler se ne ponovno naloži.",
+        "mta_sts_max_age_info": "Čas v sekundah, ki ga lahko prejemni poštni strežniki shranijo v predpomnilnik, dokler se ne naloži ponovno.",
         "mta_sts_mx": "MX strežnik",
         "mta_sts_mx_info": "Omogoča pošiljanje samo na izrecno navedena imena gostiteljskih strežnikov poštnih strežnikov; pošiljajoči MTA preveri, ali se ime gostitelja DNS MX ujema s seznamom pravilnikov, in dovoljuje dostavo le z veljavnim potrdilom TLS (zaščita pred MITM).",
-        "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami)."
+        "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami).",
+        "internal": "Notranje",
+        "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen."
     },
     "footer": {
-        "restart_container_info": "<b>Pomembno:</b> Ugoden ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
+        "restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
         "delete_these_items": "Prosimo, potrdite spremembe naslednjega ID-ja objekta",
         "confirm_delete": "Potrdi brisanje",
         "delete_now": "Izbriši zdaj",
@@ -991,7 +995,8 @@
         "yes": "&#10003;",
         "weekly": "Tedensko",
         "sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.<br>\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.<br><br>Globalni predfilter sita &#8226; Predfilter &#8226; Uporabniški skripti &#8226; Postfilter &#8226; Globalni postfilter sita",
-        "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n  Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>."
+        "tls_policy_maps_info": "Ta preslikava pravilnikov preglasi pravila odhodnega prenosa TLS neodvisno od uporabnikovih nastavitev pravilnikov TLS.<br>\n  Za več informacij preverite <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">dokumentacijo »smtp_tls_policy_maps«</a>.",
+        "internal": "Notranje"
     },
     "fido2": {
         "known_ids": "Znani ID-ji",
@@ -1362,7 +1367,7 @@
         "spamfilter_default_score": "Privzete vrednosti",
         "spamfilter_green": "Zelena: to sporočilo ni neželena pošta",
         "spamfilter_hint": "Prva vrednost opisuje »nizko oceno neželene pošte«, druga pa »visoko oceno neželene pošte«.",
-        "spamfilter_red": "Rdeča: To sporočilo je neželena pošta in ga bo strežnik zavrnil.",
+        "spamfilter_red": "Rdeča: To sporočilo je neželena pošta in ga bo strežnik zavrnil",
         "spamfilter_table_action": "Dejanje",
         "spamfilter_table_add": "Dodaj element",
         "spamfilter_table_domain_policy": "ni na voljo (pravilnik domene)",
@@ -1407,7 +1412,7 @@
     "warning": {
         "cannot_delete_self": "Prijavljenega uporabnika ni mogoče izbrisati",
         "domain_added_sogo_failed": "Domena je bila dodana, vendar ponovni zagon SOGo ni uspel. Preverite dnevnike strežnika.",
-        "dovecot_restart_failed": "Dovecota ni uspelo znova zagnati, preverite dnevnike.",
+        "dovecot_restart_failed": "Dovecota ni uspelo znova zagnati, preverite dnevnike",
         "fuzzy_learn_error": "Napaka učenja mehkega zgoščevanja: %s",
         "hash_not_found": "Zgoščena vrednost ni bila najdena ali je bila že izbrisana",
         "ip_invalid": "Preskočen neveljaven IP: %s",

+ 18 - 5
data/web/lang/lang.zh-cn.json

@@ -109,7 +109,9 @@
         "username": "用户名",
         "validate": "验证",
         "validation_success": "验证成功",
-        "dry": "模拟同步(Dry run)"
+        "dry": "模拟同步(Dry run)",
+        "internal_info": "内部的别名只能在域内部或者别名域内部访问。",
+        "internal": "内部的"
     },
     "admin": {
         "access": "权限管理",
@@ -405,7 +407,9 @@
         "user_quicklink": "隐藏指向用户登陆页面的快捷链接",
         "admin_quicklink": "隐藏指向管理员登陆页面的快捷链接",
         "force_sso": "强制要求单点登录(SSO)",
-        "user_link": "自定义链接"
+        "user_link": "自定义链接",
+        "app_hide": "在登入界面隐藏",
+        "needs_restart": "需要重启"
     },
     "danger": {
         "access_denied": "访问被拒绝或者表单数据无效",
@@ -546,7 +550,11 @@
         "generic_server_error": "服务器错误。请联系您的管理员。",
         "authsource_in_use": "由于当前有一个或多个用户正在使用该身份提供者(IDP),因此无法更改或删除。",
         "iam_test_connection": "连接失败",
-        "required_data_missing": "缺少需要的 %s 数据"
+        "required_data_missing": "缺少需要的 %s 数据",
+        "max_age_invalid": "最大有效时间 %s 无效",
+        "mode_invalid": "模式 %s 无效",
+        "mx_invalid": "MX 记录 %s 无效",
+        "version_invalid": "版本 %s 无效"
     },
     "debug": {
         "chart_this_server": "图表 (此服务器)",
@@ -732,7 +740,11 @@
         "domain_footer_skip_replies": "在回信中忽略 footer",
         "footer_exclude": "从 footer 中排除",
         "last_modified": "上次修改时间",
-        "pushover_sound": "声音"
+        "pushover_sound": "声音",
+        "internal": "内部的",
+        "internal_info": "内部的别名只能在域内部或者别名域内部访问。",
+        "mta_sts": "邮件传输代理严格传输安全协议(MTA-STS)",
+        "mta_sts_version": "版本"
     },
     "fido2": {
         "confirm": "确认",
@@ -978,7 +990,8 @@
         "relay_unknown": "转发未知信箱",
         "templates": "模板",
         "template": "模板",
-        "iam": "身份提供者(IDP)"
+        "iam": "身份提供者(IDP)",
+        "internal": "内部的"
     },
     "oauth2": {
         "access_denied": "请作为邮箱所有者登录以使用 OAuth2 授权。",

+ 2 - 1
data/web/mta-sts.php

@@ -6,7 +6,8 @@ if (!isset($_SERVER['HTTP_HOST']) || strpos($_SERVER['HTTP_HOST'], 'mta-sts.') !
   exit;
 }
 
-$domain = str_replace('mta-sts.', '', $_SERVER['HTTP_HOST']);
+$host = preg_replace('/:[0-9]+$/', '', $_SERVER['HTTP_HOST']);
+$domain = str_replace('mta-sts.', '', $host);
 $mta_sts = mailbox('get', 'mta_sts', $domain);
 
 if (count($mta_sts) == 0 ||

+ 1 - 4
data/web/sogo-auth.php

@@ -64,7 +64,7 @@ elseif (isset($_GET['login'])) {
           ':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
         ));
         // redirect to sogo (sogo will get the correct credentials via nginx auth_request
-        header("Location: /SOGo/so/{$login}");
+        header("Location: /SOGo/so/");
         exit;
       }
     }
@@ -81,10 +81,7 @@ elseif (isset($_SERVER['HTTP_X_ORIGINAL_URI']) && strcasecmp(substr($_SERVER['HT
   }
   require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
 
-  // extract email address from "/SOGo/so/user@domain/xy"
-  $url_parts = explode("/", $_SERVER['HTTP_X_ORIGINAL_URI']);
   $email_list = array(
-      $url_parts[3],                                // Requested mailbox
       ($_SESSION['mailcow_cc_username'] ?? ''),     // Current user
       ($_SESSION["dual-login"]["username"] ?? ''),  // Dual login user
   );

+ 4 - 4
data/web/templates/edit/app-passwd.twig

@@ -13,15 +13,15 @@
     </div>
   </div>
   <div class="row mb-2">
-    <label class="control-label col-sm-2" for="password">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
+    <label class="control-label col-sm-2" for="app_passwd">{{ lang.edit.password }} (<a href="#" class="generate_password">{{ lang.edit.generate }}</a>)</label>
     <div class="col-sm-10">
-      <input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="password" placeholder="" autocomplete="new-password">
+      <input type="password" data-pwgen-field="true" data-hibp="true" class="form-control" name="app_passwd" placeholder="" autocomplete="new-password">
     </div>
   </div>
   <div class="row mb-4">
-    <label class="control-label col-sm-2" for="password2">{{ lang.edit.password_repeat }}</label>
+    <label class="control-label col-sm-2" for="app_passwd2">{{ lang.edit.password_repeat }}</label>
     <div class="col-sm-10">
-      <input type="password" data-pwgen-field="true" class="form-control" name="password2" autocomplete="new-password">
+      <input type="password" data-pwgen-field="true" class="form-control" name="app_passwd2" autocomplete="new-password">
     </div>
   </div>
   <div class="row mb-2">

+ 5 - 3
data/web/templates/edit/domain.twig

@@ -39,7 +39,7 @@
                   <div class="row mb-2" data-acl="{{ acl.domain_desc }}">
                     <label class="control-label col-sm-2" for="description">{{ lang.edit.description }}</label>
                     <div class="col-sm-10">
-                      <input type="text" class="form-control" name="description" value="{{ result.description }}">
+                      <input type="text" class="form-control" name="description" value="{{ result.description }}"{% if acl.domain_desc == '0' %} readonly{% endif %}>
                     </div>
                   </div>
                   <div class="row mb-4">
@@ -58,6 +58,7 @@
                       </div>
                     </div>
                   </div>
+                  {% if acl.domain_relayhost == '1' %}
                   <div class="row mb-2">
                     <label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
                     <div class="col-sm-10">
@@ -76,6 +77,7 @@
                       </select>
                     </div>
                   </div>
+                  {% endif %}
                   {% if mailcow_cc_role == 'admin' %}
                   <div class="row mb-2">
                     <label class="control-label col-sm-2" for="aliases">{{ lang.edit.max_aliases }}</label>
@@ -147,7 +149,7 @@
                   <div class="row">
                     <div class="offset-sm-2 col-sm-10">
                       <small class="fst-italic d-block">{{ lang.edit.created_on }}: {{ result.created }}</small>
-                      <small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified }}</small>
+                      <small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified|default(lang.user.never) }}</small>
                     </div>
                   </div>
                 </form>
@@ -293,7 +295,7 @@
                   <input type="hidden" value="0" name="active">
                   <input type="hidden" value="{{ domain }}" name="domain">
                   <div class="row mb-2">
-                    <label class="control-label col-sm-2" for="version"> 
+                    <label class="control-label col-sm-2" for="version">
                       <i style="font-size: 16px; cursor: pointer;" class="bi bi-patch-question-fill m-2 ms-0" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom" title="{{ lang.edit.mta_sts_version_info|raw }}"></i>
                       {{ lang.edit.mta_sts_version }}
                     </label>

+ 3 - 1
data/web/templates/edit/mailbox.twig

@@ -114,6 +114,7 @@
                       <small class="text-muted d-block">{{ lang.edit.sender_acl_info|raw }}</small>
                     </div>
                   </div>
+                  {% if acl.mailbox_relayhost == '1' %}
                   <div class="row mb-2">
                     <label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
                     <div class="col-sm-10">
@@ -134,6 +135,7 @@
                       <small class="text-muted d-block mb-4">{{ lang.edit.mailbox_relayhost_info }}</small>
                     </div>
                   </div>
+                  {% endif %}
                   <div class="row mb-2">
                     <label class="control-label col-sm-2">{{ lang.user.tag_handling }}</label>
                     <div class="col-sm-10">
@@ -325,7 +327,7 @@
                   <div class="row">
                     <div class="offset-sm-2 col-sm-10">
                       <small class="fst-italic d-block">{{ lang.edit.created_on }}: {{ result.created }}</small>
-                      <small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified }}</small>
+                      <small class="fst-italic d-block">{{ lang.edit.last_modified }}: {{ result.modified|default(lang.user.never) }}</small>
                     </div>
                   </div>
                 </form>

+ 3 - 2
docker-compose.yml

@@ -200,7 +200,7 @@ services:
             - phpfpm
 
     sogo-mailcow:
-      image: ghcr.io/mailcow/sogo:1.135
+      image: ghcr.io/mailcow/sogo:1.136
       environment:
         - DBNAME=${DBNAME}
         - DBUSER=${DBUSER}
@@ -213,6 +213,7 @@ services:
         - ALLOW_ADMIN_EMAIL_LOGIN=${ALLOW_ADMIN_EMAIL_LOGIN:-n}
         - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
         - SOGO_EXPIRE_SESSION=${SOGO_EXPIRE_SESSION:-480}
+        - SOGO_URL_ENCRYPTION_KEY=${SOGO_URL_ENCRYPTION_KEY:-SOGoSuperSecret0}
         - SKIP_SOGO=${SKIP_SOGO:-n}
         - MASTER=${MASTER:-y}
         - REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
@@ -418,7 +419,7 @@ services:
         - php-fpm-mailcow
         - sogo-mailcow
         - rspamd-mailcow
-      image: ghcr.io/mailcow/nginx:1.04
+      image: ghcr.io/mailcow/nginx:1.05
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
       environment:

+ 10 - 37
generate_config.sh

@@ -172,7 +172,6 @@ cat << EOF > mailcow.conf
 # example.org is _not_ a valid hostname, use a fqdn here.
 # Default admin user is "admin"
 # Default password is "moohoo"
-
 MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
 
 # Password hash algorithm
@@ -183,19 +182,16 @@ MAILCOW_PASS_SCHEME=BLF-CRYPT
 # ------------------------------
 # SQL database configuration
 # ------------------------------
-
 DBNAME=mailcow
 DBUSER=mailcow
 
 # Please use long, random alphanumeric strings (A-Za-z0-9)
-
 DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
 DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
 
 # ------------------------------
 # REDIS configuration
 # ------------------------------
-
 REDISPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
 
 # ------------------------------
@@ -210,7 +206,6 @@ REDISPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
 # Example: HTTP_BIND=1.2.3.4
 # For IPv4 leave it as it is: HTTP_BIND= & HTTPS_PORT=
 # For IPv6 see https://docs.mailcow.email/post_installation/firststeps-ip_bindings/
-
 HTTP_PORT=80
 HTTP_BIND=
 
@@ -218,14 +213,13 @@ HTTPS_PORT=443
 HTTPS_BIND=
 
 # Redirect HTTP connections to HTTPS - y/n
-HTTP_REDIRECT=n
+HTTP_REDIRECT=y
 
 # ------------------------------
 # Other bindings
 # ------------------------------
 # You should leave that alone
 # Format: 11.22.33.44:25 or 12.34.56.78:465 etc.
-
 SMTP_PORT=25
 SMTPS_PORT=465
 SUBMISSION_PORT=587
@@ -241,25 +235,22 @@ REDIS_PORT=127.0.0.1:7654
 # Your timezone
 # See https://en.wikipedia.org/wiki/List_of_tz_database_time_zones for a list of timezones
 # Use the column named 'TZ identifier' + pay attention for the column named 'Notes'
-
 TZ=${MAILCOW_TZ}
 
 # Fixed project name
 # Please use lowercase letters only
-
 COMPOSE_PROJECT_NAME=mailcowdockerized
 
 # Used Docker Compose version
 # Switch here between native (compose plugin) and standalone
-# For more informations take a look at the mailcow docs regarding the configuration options.
+# For more information take a look at the mailcow docs regarding the configuration options.
 # Normally this should be untouched but if you decided to use either of those you can switch it manually here.
 # Please be aware that at least one of those variants should be installed on your machine or mailcow will fail.
-
 DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
 
 # Set this to "allow" to enable the anyone pseudo user. Disabled by default.
 # When enabled, ACL can be created, that apply to "All authenticated users"
-# This should probably only be activated on mail hosts, that are used exclusivly by one organisation.
+# This should probably only be activated on mail hosts, that are used exclusively by one organisation.
 # Otherwise a user might share data with too many other users.
 ACL_ANYONE=disallow
 
@@ -267,7 +258,6 @@ ACL_ANYONE=disallow
 # Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring
 # How long should objects remain in the garbage until they are being deleted? (value in minutes)
 # Check interval is hourly
-
 MAILDIR_GC_TIME=7200
 
 # Additional SAN for the certificate
@@ -282,8 +272,6 @@ MAILDIR_GC_TIME=7200
 #ADDITIONAL_SAN=srv1.example.net
 # ...or combine wildcard and static names:
 #ADDITIONAL_SAN=imap.*,srv1.example.com
-#
-
 ADDITIONAL_SAN=
 
 # Obtain certificates for autodiscover.* and autoconfig.* domains.
@@ -300,65 +288,52 @@ AUTODISCOVER_SAN=y
 # If the server name does not match a known site, Nginx decides by best-guess and may redirect users to the wrong web root.
 # You can understand this as server_name directive in Nginx.
 # Comma separated list without spaces! Example: ADDITIONAL_SERVER_NAMES=a.b.c,d.e.f
-
 ADDITIONAL_SERVER_NAMES=
 
 # Skip running ACME (acme-mailcow, Let's Encrypt certs) - y/n
-
 SKIP_LETS_ENCRYPT=n
 
-# Create seperate certificates for all domains - y/n
+# Create separate 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://doc.dovecot.org/admin_manual/ssl/sni_support
 ENABLE_SSL_SNI=n
 
 # Skip IPv4 check in ACME container - y/n
-
 SKIP_IP_CHECK=n
 
 # Skip HTTP verification in ACME container - y/n
-
 SKIP_HTTP_VERIFICATION=n
 
 # Skip Unbound (DNS Resolver) Healthchecks (NOT Recommended!) - y/n
-
 SKIP_UNBOUND_HEALTHCHECK=n
 
 # Skip ClamAV (clamd-mailcow) anti-virus (Rspamd will auto-detect a missing ClamAV container) - y/n
-
 SKIP_CLAMD=${SKIP_CLAMD}
 
 # Skip Olefy (olefy-mailcow) anti-virus for Office documents (Rspamd will auto-detect a missing Olefy container) - y/n
-
 SKIP_OLEFY=n
 
 # Skip SOGo: Will disable SOGo integration and therefore webmail, DAV protocols and ActiveSync support (experimental, unsupported, not fully implemented) - y/n
-
 SKIP_SOGO=n
 
 # Skip FTS (Fulltext Search) for Dovecot on low-memory, low-threaded systems or if you simply want to disable it.
 # Dovecot inside mailcow use Flatcurve as FTS Backend.
-
 SKIP_FTS=n
 
 # Dovecot Indexing (FTS) Process maximum heap size in MB, there is no recommendation, please see Dovecot docs.
 # Flatcurve (Xapian backend) is used as the FTS Indexer. It is supposed to be efficient in CPU and RAM consumption.
 # However: Please always monitor your Resource consumption!
-
 FTS_HEAP=128
 
 # Controls how many processes the Dovecot indexing process can spawn at max.
 # Too many indexing processes can use a lot of CPU and Disk I/O.
-# Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more informations
-
+# Please visit: https://doc.dovecot.org/configuration_manual/service_configuration/#indexer-worker for more information
 FTS_PROCS=1
 
 # Allow admins to log into SOGo as email user (without any password)
-
 ALLOW_ADMIN_EMAIL_LOGIN=n
 
 # Enable watchdog (watchdog-mailcow) to restart unhealthy containers
-
 USE_WATCHDOG=y
 
 # Send watchdog notifications by mail (sent from watchdog@MAILCOW_HOSTNAME)
@@ -367,7 +342,6 @@ USE_WATCHDOG=y
 # 2. Mails are sent unsigned (no DKIM)
 # 3. If you use DMARC, create a separate DMARC policy ("v=DMARC1; p=none;" in _dmarc.MAILCOW_HOSTNAME)
 # Multiple rcpts allowed, NO quotation marks, NO spaces
-
 #WATCHDOG_NOTIFY_EMAIL=a@example.com,b@example.com,c@example.com
 #WATCHDOG_NOTIFY_EMAIL=
 
@@ -398,25 +372,20 @@ WATCHDOG_EXTERNAL_CHECKS=n
 WATCHDOG_VERBOSE=n
 
 # Max log lines per service to keep in Redis logs
-
 LOG_LINES=9999
 
 # Internal IPv4 /24 subnet, format n.n.n (expands to n.n.n.0/24)
 # Use private IPv4 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv4_addresses
-
 IPV4_NETWORK=172.22.1
 
 # Internal IPv6 subnet in fc00::/7
 # Use private IPv6 addresses only, see https://en.wikipedia.org/wiki/Private_network#Private_IPv6_addresses
-
 IPV6_NETWORK=fd4d:6169:6c63:6f77::/64
 
 # Use this IPv4 for outgoing connections (SNAT)
-
 #SNAT_TO_SOURCE=
 
 # Use this IPv6 for outgoing connections (SNAT)
-
 #SNAT6_TO_SOURCE=
 
 # Create or override an API key for the web UI
@@ -436,6 +405,10 @@ MAILDIR_SUB=Maildir
 # SOGo session timeout in minutes
 SOGO_EXPIRE_SESSION=480
 
+# SOGo URL encryption key (exactly 16 characters, limited to A–Z, a–z, 0–9)
+# This key is used to encrypt email addresses within SOGo URLs
+SOGO_URL_ENCRYPTION_KEY=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2>/dev/null | head -c 16)
+
 # DOVECOT_MASTER_USER and DOVECOT_MASTER_PASS must both be provided. No special chars.
 # Empty by default to auto-generate master user and password on start.
 # User expands to DOVECOT_MASTER_USER@mailcow.local
@@ -541,4 +514,4 @@ else
   echo '  $MAILCOW_UPDATEDAT='$(date +%s)';' >> data/web/inc/app_info.inc.php
   echo '?>' >> data/web/inc/app_info.inc.php
   echo -e "\e[33mCannot determine current git repository version...\e[0m"
-fi
+fi

+ 3 - 3
helper-scripts/_cold-standby.sh

@@ -117,7 +117,7 @@ fi
 SCRIPT_DIR=$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )
 source "${SCRIPT_DIR}/../mailcow.conf"
 COMPOSE_FILE="${SCRIPT_DIR}/../docker-compose.yml"
-CMPS_PRJ=$(echo ${COMPOSE_PROJECT_NAME} | tr -cd 'A-Za-z-_')
+CMPS_PRJ=$(echo ${COMPOSE_PROJECT_NAME} | tr -cd '0-9A-Za-z-_')
 SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' "${COMPOSE_FILE}")
 
 preflight_local_checks
@@ -169,7 +169,7 @@ if ! ssh -o StrictHostKeyChecking=no \
   -i "${REMOTE_SSH_KEY}" \
   ${REMOTE_SSH_HOST} \
   -p ${REMOTE_SSH_PORT} \
-  ${COMPOSE_COMMAND} -f "${SCRIPT_DIR}/../docker-compose.yml" create 2>&1 ; then
+  "cd \"${SCRIPT_DIR}/../\" && ${COMPOSE_COMMAND} create 2>&1" ; then
     >&2 echo -e "\e[31m[ERR]\e[0m - Could not create networks, volumes and containers on remote"
 fi
 
@@ -284,7 +284,7 @@ echo "OK"
     -i "${REMOTE_SSH_KEY}" \
     ${REMOTE_SSH_HOST} \
     -p ${REMOTE_SSH_PORT} \
-    ${COMPOSE_COMMAND} -f "${SCRIPT_DIR}/../docker-compose.yml" pull --quiet 2>&1 ; then
+    "cd \"${SCRIPT_DIR}/../\" && ${COMPOSE_COMMAND} pull --quiet 2>&1" ; then
       >&2 echo -e "\e[31m[ERR]\e[0m - Could not pull images on remote"
   fi
 

+ 2 - 2
helper-scripts/docker-compose.override.yml.d/PROMETHEUS_EXPORTER/docker-compose.override.yml

@@ -7,8 +7,8 @@ services:
       environment:
         MAILCOW_EXPORTER_HOST: "<your-mail-domain>" # Replace with your Mailcow hostname
         MAILCOW_EXPORTER_API_KEY: "<your-API-Key>" # Replace with your API key
-        MAILCOW_EXPORTER_TOKEN: "<your-secure-token>" # Replace with your secure key
-        # MAILCOW_EXPORTER_TOKEN_DISABLE: "true" # Uncomment only if it is safe to disable token authentication (e.g., internal network only)
+        MAILCOW_EXPORTER_SECURITY_TOKEN: "<your-secure-token>" # Replace with your secure key
+        # MAILCOW_EXPORTER_SECURITY_DISABLE_ACCESS_PROTECTION: "true" # Uncomment only if it is safe to disable token authentication (e.g., internal network only)
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
       networks: