浏览代码

Merge branch 'staging' into nightly

FreddleSpl0it 21 小时之前
父节点
当前提交
eb84847a5b
共有 40 个文件被更改,包括 1128 次插入186 次删除
  1. 1 1
      .github/workflows/close_old_issues_and_prs.yml
  2. 1 1
      .github/workflows/image_builds.yml
  3. 1 1
      .github/workflows/pr_to_nightly.yml
  4. 1 1
      .github/workflows/rebuild_backup_image.yml
  5. 1 1
      .github/workflows/update_postscreen_access_list.yml
  6. 0 3
      README.md
  7. 1 1
      _modules/scripts/core.sh
  8. 109 39
      _modules/scripts/ipv6_controller.sh
  9. 1 1
      data/Dockerfiles/clamd/clamd.sh
  10. 2 2
      data/Dockerfiles/dovecot/imapsync_runner.pl
  11. 1 0
      data/Dockerfiles/postfix-tlspol/Dockerfile
  12. 3 1
      data/Dockerfiles/rspamd/docker-entrypoint.sh
  13. 3 2
      data/Dockerfiles/watchdog/Dockerfile
  14. 39 0
      data/Dockerfiles/watchdog/check_dns.sh
  15. 43 1
      data/Dockerfiles/watchdog/watchdog.sh
  16. 4 4
      data/conf/dovecot/auth/mailcowauth.php
  17. 75 20
      data/conf/postfix/postscreen_access.cidr
  18. 35 3
      data/conf/rspamd/dynmaps/settings.php
  19. 24 14
      data/conf/rspamd/lua/rspamd.local.lua
  20. 19 17
      data/web/inc/footer.inc.php
  21. 16 0
      data/web/inc/functions.auth.inc.php
  22. 1 1
      data/web/inc/functions.customize.inc.php
  23. 1 1
      data/web/inc/functions.inc.php
  24. 18 10
      data/web/inc/functions.mailbox.inc.php
  25. 2 1
      data/web/inc/init_db.inc.php
  26. 9 0
      data/web/js/site/mailbox.js
  27. 9 2
      data/web/lang/lang.de-de.json
  28. 8 2
      data/web/lang/lang.en-gb.json
  29. 590 38
      data/web/lang/lang.hu-hu.json
  30. 19 3
      data/web/lang/lang.si-si.json
  31. 12 0
      data/web/templates/base.twig
  32. 6 1
      data/web/templates/edit/alias.twig
  33. 7 2
      data/web/templates/modals/mailbox.twig
  34. 1 1
      data/web/templates/user_index.twig
  35. 8 6
      docker-compose.yml
  36. 21 0
      generate_config.sh
  37. 1 1
      helper-scripts/_cold-standby.sh
  38. 18 0
      helper-scripts/docker-compose.override.yml.d/PROMETHEUS_EXPORTER/docker-compose.override.yml
  39. 3 2
      helper-scripts/update_postscreen_whitelist.sh
  40. 14 2
      update.sh

+ 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@v9.1.0
+        uses: actions/stale@v10.0.0
         with:
           repo-token: ${{ secrets.STALE_ACTION_PAT }}
           days-before-stale: 60

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

@@ -27,7 +27,7 @@ jobs:
           - "watchdog-mailcow"
     runs-on: ubuntu-latest
     steps:
-      - uses: actions/checkout@v4
+      - uses: actions/checkout@v5
       - name: Setup Docker
         run: |
           curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh

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

@@ -8,7 +8,7 @@ jobs:
     runs-on: ubuntu-latest
     steps:
       - name: Checkout repository
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
         with:
           fetch-depth: 0
       - name: Run the Action

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

@@ -13,7 +13,7 @@ jobs:
       packages: write
     steps:
       - name: Checkout
-        uses: actions/checkout@v4
+        uses: actions/checkout@v5
 
       - name: Set up QEMU
         uses: docker/setup-qemu-action@v3

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

@@ -15,7 +15,7 @@ jobs:
    runs-on: ubuntu-latest
    steps:
     - name: Checkout
-      uses: actions/checkout@v4
+      uses: actions/checkout@v5
 
     - name: Generate postscreen_access.cidr
       run: |

+ 0 - 3
README.md

@@ -23,9 +23,6 @@ A big thank you to everyone supporting us on GitHub Sponsors—your contribution
   <a href="https://www.maehdros.com/" target=_blank><img
     src="https://avatars.githubusercontent.com/u/173894712" height="58"
   /></a>
-  <a href="https://macarne.com/" target=_blank><img
-    src="https://avatars.githubusercontent.com/u/149550368?s=200&v=4" height="58"
-  /></a>
 
 ### 50$/Month Sponsors
   <a href="https://github.com/vnukhr" target=_blank><img

+ 1 - 1
_modules/scripts/core.sh

@@ -185,7 +185,7 @@ detect_major_update() {
     MAJOR_VERSIONS=(
       "2025-02"
       "2025-03"
-      "2025-08"
+      "2025-09"
     )
 
     current_version=""

+ 109 - 39
_modules/scripts/ipv6_controller.sh

@@ -5,14 +5,65 @@
 
 # 1) Check if the host supports IPv6
 get_ipv6_support() {
-  if grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null \
-    || ! ip -6 route show default &>/dev/null; then
+  # ---- helper: probe external IPv6 connectivity without DNS ----
+  _probe_ipv6_connectivity() {
+    # Use literal, always-on IPv6 echo responders (no DNS required)
+    local PROBE_IPS=("2001:4860:4860::8888" "2606:4700:4700::1111")
+    local ip rc=1
+
+    for ip in "${PROBE_IPS[@]}"; do
+      if command -v ping6 &>/dev/null; then
+        ping6 -c1 -W2 "$ip" &>/dev/null || ping6 -c1 -w2 "$ip" &>/dev/null
+        rc=$?
+      elif command -v ping &>/dev/null; then
+        ping -6 -c1 -W2 "$ip" &>/dev/null || ping -6 -c1 -w2 "$ip" &>/dev/null
+        rc=$?
+      else
+        rc=1
+      fi
+      [[ $rc -eq 0 ]] && return 0
+    done
+    return 1
+  }
+
+  if [[ ! -f /proc/net/if_inet6 ]] || grep -qs '^1' /proc/sys/net/ipv6/conf/all/disable_ipv6 2>/dev/null; then
     DETECTED_IPV6=false
-    echo -e "${YELLOW}IPv6 not detected on host – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
-  else
-    DETECTED_IPV6=true
-    echo -e "IPv6 detected on host – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
+    echo -e "${YELLOW}IPv6 not detected on host – ${LIGHT_RED}IPv6 is administratively disabled${YELLOW}.${NC}"
+    return
+  fi
+
+  if ip -6 route show default 2>/dev/null | grep -qE '^default'; then
+    echo -e "${YELLOW}Default IPv6 route found – testing external IPv6 connectivity...${NC}"
+    if _probe_ipv6_connectivity; then
+      DETECTED_IPV6=true
+      echo -e "IPv6 detected on host – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
+    else
+      DETECTED_IPV6=false
+      echo -e "${YELLOW}Default IPv6 route present but external IPv6 connectivity failed – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
+    fi
+    return
+  fi
+
+  if ip -6 addr show scope global 2>/dev/null | grep -q 'inet6'; then
+    DETECTED_IPV6=false
+    echo -e "${YELLOW}Global IPv6 address present but no default route – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
+    return
   fi
+
+  if ip -6 addr show scope link 2>/dev/null | grep -q 'inet6'; then
+    echo -e "${YELLOW}Only link-local IPv6 addresses found – testing external IPv6 connectivity...${NC}"
+    if _probe_ipv6_connectivity; then
+      DETECTED_IPV6=true
+      echo -e "External IPv6 connectivity available – ${LIGHT_GREEN}leaving IPv6 support enabled${YELLOW}.${NC}"
+    else
+      DETECTED_IPV6=false
+      echo -e "${YELLOW}Only link-local IPv6 present and no external connectivity – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
+    fi
+    return
+  fi
+
+  DETECTED_IPV6=false
+  echo -e "${YELLOW}IPv6 not detected on host – ${LIGHT_RED}disabling IPv6 support${YELLOW}.${NC}"
 }
 
 # 2) Ensure Docker daemon.json has (or create) the required IPv6 settings
@@ -21,7 +72,7 @@ docker_daemon_edit(){
   DOCKER_MAJOR=$(docker version --format '{{.Server.Version}}' 2>/dev/null | cut -d. -f1)
   MISSING=()
 
-  _has_kv() { grep -Eq "\"$1\"\s*:\s*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null; }
+  _has_kv() { grep -Eq "\"$1\"[[:space:]]*:[[:space:]]*$2" "$DOCKER_DAEMON_CONFIG" 2>/dev/null; }
 
   if [[ -f "$DOCKER_DAEMON_CONFIG" ]]; then
 
@@ -38,12 +89,18 @@ docker_daemon_edit(){
     fi
 
     # Gather missing keys
-    ! _has_kv ipv6 true       && MISSING+=("ipv6: true")
-    ! grep -Eq '"fixed-cidr-v6"\s*:\s*".+"' "$DOCKER_DAEMON_CONFIG" \
-                              && MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"')
-    if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -le 27 ]]; then
+    ! _has_kv ipv6 true && MISSING+=("ipv6: true")
+
+    # For Docker < 28, keep requiring fixed-cidr-v6 (default bridge needs it on old engines)
+    if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
+      ! grep -Eq '"fixed-cidr-v6"[[:space:]]*:[[:space:]]*".+"' "$DOCKER_DAEMON_CONFIG" \
+                                && MISSING+=('fixed-cidr-v6: "fd00:dead:beef:c0::/80"')
+    fi
+
+    # For Docker < 27, ip6tables needed and was tied to experimental in older releases
+    if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
       _has_kv ipv6 true && ! _has_kv ip6tables true && MISSING+=("ip6tables: true")
-      ! _has_kv experimental true                 && MISSING+=("experimental: true")
+      ! _has_kv experimental true && MISSING+=("experimental: true")
     fi
 
     # Fix if needed
@@ -60,9 +117,19 @@ docker_daemon_edit(){
         cp "$DOCKER_DAEMON_CONFIG" "${DOCKER_DAEMON_CONFIG}.bak"
         if command -v jq &>/dev/null; then
           TMP=$(mktemp)
-          JQ_FILTER='.ipv6 = true | .["fixed-cidr-v6"] = "fd00:dead:beef:c0::/80"'
-          [[ "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]] \
-            && JQ_FILTER+=' | .ip6tables = true | .experimental = true'
+          # Base filter: ensure ipv6 = true
+          JQ_FILTER='.ipv6 = true'
+
+          # Add fixed-cidr-v6 only for Docker < 28
+          if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
+            JQ_FILTER+=' | .["fixed-cidr-v6"] = (.["fixed-cidr-v6"] // "fd00:dead:beef:c0::/80")'
+          fi
+
+          # Add ip6tables/experimental only for Docker < 27
+          if [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 27 ]]; then
+            JQ_FILTER+=' | .ip6tables = true | .experimental = true'
+          fi
+
           jq "$JQ_FILTER" "$DOCKER_DAEMON_CONFIG" >"$TMP" && mv "$TMP" "$DOCKER_DAEMON_CONFIG"
           echo -e "${LIGHT_GREEN}daemon.json updated. Restarting Docker...${NC}"
           (command -v systemctl &>/dev/null && systemctl restart docker) || service docker restart
@@ -97,12 +164,19 @@ docker_daemon_edit(){
   "experimental": true
 }
 EOF
-      else
+      elif [[ -n "$DOCKER_MAJOR" && "$DOCKER_MAJOR" -lt 28 ]]; then
         cat > "$DOCKER_DAEMON_CONFIG" <<EOF
 {
   "ipv6": true,
   "fixed-cidr-v6": "fd00:dead:beef:c0::/80"
 }
+EOF
+      else
+        # Docker 28+: ipv6 works without fixed-cidr-v6
+        cat > "$DOCKER_DAEMON_CONFIG" <<EOF
+{
+  "ipv6": true
+}
 EOF
       fi
       echo -e "${GREEN}Created $DOCKER_DAEMON_CONFIG with IPv6 settings.${NC}"
@@ -122,7 +196,7 @@ configure_ipv6() {
   # detect manual override if mailcow.conf is present
   if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]] && grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
     MANUAL_SETTING=$(grep '^ENABLE_IPV6=' "$MAILCOW_CONF" | cut -d= -f2)
-  elif [[ -z "$MAILCOW_CONF" ]] && [[ ! -z "${ENABLE_IPV6:-}" ]]; then
+  elif [[ -z "$MAILCOW_CONF" ]] && [[ -n "${ENABLE_IPV6:-}" ]]; then
     MANUAL_SETTING="$ENABLE_IPV6"
   else
     MANUAL_SETTING=""
@@ -131,38 +205,34 @@ configure_ipv6() {
   get_ipv6_support
 
   # if user manually set it, check for mismatch
-  if [[ -n "$MANUAL_SETTING" ]]; then
-    if [[ "$MANUAL_SETTING" == "false" && "$DETECTED_IPV6" == "true" ]]; then
-      echo -e "${RED}ERROR: You have ENABLE_IPV6=false but your host and Docker support IPv6.${NC}"
-      echo -e "${RED}This can create an open relay. Please set ENABLE_IPV6=true in your mailcow.conf and re-run.${NC}"
-      exit 1
-    elif [[ "$MANUAL_SETTING" == "true" && "$DETECTED_IPV6" == "false" ]]; then
-      echo -e "${RED}ERROR: You have ENABLE_IPV6=true but your host does not support IPv6.${NC}"
-      echo -e "${RED}Please disable or fix your host/Docker IPv6 support, or set ENABLE_IPV6=false.${NC}"
-      exit 1
+  if [[ "$DETECTED_IPV6" != "true" ]]; then
+    if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
+      if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
+        sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=false/' "$MAILCOW_CONF"
+      else
+        echo "ENABLE_IPV6=false" >> "$MAILCOW_CONF"
+      fi
     else
-      return
+      export IPV6_BOOL=false
     fi
-  fi
-
-  # no manual override: proceed to set or export
-  if [[ "$DETECTED_IPV6" == "true" ]]; then
-    docker_daemon_edit
-  else
     echo "Skipping Docker IPv6 configuration because host does not support IPv6."
+    echo "Make sure to check if your docker daemon.json does not include \"enable_ipv6\": true if you do not want IPv6."
+    echo "IPv6 configuration complete: ENABLE_IPV6=false"
+    sleep 2
+    return
   fi
 
-  # now write into mailcow.conf or export
+  docker_daemon_edit
+
   if [[ -n "$MAILCOW_CONF" && -f "$MAILCOW_CONF" ]]; then
-    LINE="ENABLE_IPV6=$DETECTED_IPV6"
     if grep -q '^ENABLE_IPV6=' "$MAILCOW_CONF"; then
-      sed -i "s/^ENABLE_IPV6=.*/$LINE/" "$MAILCOW_CONF"
+      sed -i 's/^ENABLE_IPV6=.*/ENABLE_IPV6=true/' "$MAILCOW_CONF"
     else
-      echo "$LINE" >> "$MAILCOW_CONF"
+      echo "ENABLE_IPV6=true" >> "$MAILCOW_CONF"
     fi
   else
-    export IPV6_BOOL="$DETECTED_IPV6"
+    export IPV6_BOOL=true
   fi
 
-  echo "IPv6 configuration complete: ENABLE_IPV6=$DETECTED_IPV6"
+  echo "IPv6 configuration complete: ENABLE_IPV6=true"
 }

+ 1 - 1
data/Dockerfiles/clamd/clamd.sh

@@ -8,7 +8,7 @@ fi
 
 # Cleaning up garbage
 echo "Cleaning up tmp files..."
-rm -rf /var/lib/clamav/clamav-*.tmp
+rm -rf /var/lib/clamav/tmp.*
 
 # Prepare whitelist
 

+ 2 - 2
data/Dockerfiles/dovecot/imapsync_runner.pl

@@ -132,8 +132,8 @@ while ($row = $sth->fetchrow_arrayref()) {
   "--tmpdir", "/tmp",
   "--nofoldersizes",
   "--addheader",
-  ($timeout1 gt "0" ? () : ('--timeout1', $timeout1)),
-  ($timeout2 gt "0" ? () : ('--timeout2', $timeout2)),
+  ($timeout1 le "0" ? () : ('--timeout1', $timeout1)),
+  ($timeout2 le "0" ? () : ('--timeout2', $timeout2)),
   ($exclude eq "" ? () : ("--exclude", $exclude)),
   ($subfolder2 eq "" ? () : ('--subfolder2', $subfolder2)),
   ($maxage eq "0" ? () : ('--maxage', $maxage)),

+ 1 - 0
data/Dockerfiles/postfix-tlspol/Dockerfile

@@ -3,6 +3,7 @@ WORKDIR /src
 
 ENV CGO_ENABLED=0 \
     GO111MODULE=on \
+		NOOPT=1 \
     VERSION=1.8.14
 
 RUN git clone --branch v${VERSION} https://github.com/Zuplu/postfix-tlspol && \

+ 3 - 1
data/Dockerfiles/rspamd/docker-entrypoint.sh

@@ -86,7 +86,8 @@ if [[ "${SKIP_OLEFY}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
     rm /etc/rspamd/local.d/external_services.conf
   fi
 else
-  cat <<EOF > /etc/rspamd/local.d/external_services.conf
+  if [[ ! -f /etc/rspamd/local.d/external_services.conf ]]; then
+    cat <<EOF > /etc/rspamd/local.d/external_services.conf
 oletools {
   # default olefy settings
   servers = "olefy:10055";
@@ -100,6 +101,7 @@ oletools {
   retransmits = 1;
 }
 EOF
+  fi
 fi
 
 # Provide additional lua modules

+ 3 - 2
data/Dockerfiles/watchdog/Dockerfile

@@ -16,7 +16,6 @@ RUN apk add --update \
   fcgi \
   openssl \
   nagios-plugins-mysql \
-  nagios-plugins-dns \
   nagios-plugins-disk \
   bind-tools \
   redis \
@@ -32,9 +31,11 @@ RUN apk add --update \
   tzdata \
   whois \
   && curl https://raw.githubusercontent.com/mludvig/smtp-cli/v3.10/smtp-cli -o /smtp-cli \
-  && chmod +x smtp-cli
+  && chmod +x smtp-cli \
+  && mkdir /usr/lib/mailcow
 
 COPY watchdog.sh /watchdog.sh
 COPY check_mysql_slavestatus.sh /usr/lib/nagios/plugins/check_mysql_slavestatus.sh
+COPY check_dns.sh /usr/lib/mailcow/check_dns.sh
 
 CMD ["/watchdog.sh"]

+ 39 - 0
data/Dockerfiles/watchdog/check_dns.sh

@@ -0,0 +1,39 @@
+#!/bin/sh
+
+while getopts "H:s:" opt; do
+  case "$opt" in
+    H) HOST="$OPTARG" ;;
+    s) SERVER="$OPTARG" ;;
+    *) echo "Usage: $0 -H host -s server"; exit 3 ;;
+  esac
+done
+
+if [ -z "$SERVER" ]; then
+  echo "No DNS Server provided"
+  exit 3
+fi
+
+if [ -z "$HOST" ]; then
+  echo "No host to test provided"
+  exit 3
+fi
+
+# run dig and measure the time it takes to run
+START_TIME=$(date +%s%3N)
+dig_output=$(dig +short +timeout=2 +tries=1 "$HOST" @"$SERVER" 2>/dev/null)
+dig_rc=$?
+dig_output_ips=$(echo "$dig_output" | grep -E '^[0-9.]+$' | sort | paste -sd ',' -)
+END_TIME=$(date +%s%3N)
+ELAPSED_TIME=$((END_TIME - START_TIME))
+
+# validate and perform nagios like output and exit codes
+if [ $dig_rc -ne 0 ] || [ -z "$dig_output" ]; then
+  echo "Domain $HOST was not found by the server"
+  exit 2
+elif [ $dig_rc -eq 0 ]; then
+  echo "DNS OK: $ELAPSED_TIME ms response time. $HOST returns $dig_output_ips"
+  exit 0
+else
+  echo "Unknown error"
+  exit 3
+fi

+ 43 - 1
data/Dockerfiles/watchdog/watchdog.sh

@@ -1,5 +1,10 @@
 #!/bin/bash
 
+if [ "${DEV_MODE}" != "n" ]; then
+  echo -e "\e[31mEnabled Debug Mode\e[0m"
+  set -x
+fi
+
 trap "exit" INT TERM
 trap "kill 0" EXIT
 
@@ -297,7 +302,7 @@ unbound_checks() {
     touch /tmp/unbound-mailcow; echo "$(tail -50 /tmp/unbound-mailcow)" > /tmp/unbound-mailcow
     host_ip=$(get_container_ip unbound-mailcow)
     err_c_cur=${err_count}
-    /usr/lib/nagios/plugins/check_dns -s ${host_ip} -H stackoverflow.com 2>> /tmp/unbound-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
+    /usr/lib/mailcow/check_dns.sh -s ${host_ip} -H stackoverflow.com 2>> /tmp/unbound-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     DNSSEC=$(dig com +dnssec | egrep 'flags:.+ad')
     if [[ -z ${DNSSEC} ]]; then
       echo "DNSSEC failure" 2>> /tmp/unbound-mailcow 1>&2
@@ -445,6 +450,31 @@ postfix_checks() {
   return 1
 }
 
+postfix-tlspol_checks() {
+  err_count=0
+  diff_c=0
+  THRESHOLD=${POSTFIX_TLSPOL_THRESHOLD}
+  # Reduce error count by 2 after restarting an unhealthy container
+  trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
+  while [ ${err_count} -lt ${THRESHOLD} ]; do
+    touch /tmp/postfix-tlspol-mailcow; echo "$(tail -50 /tmp/postfix-tlspol-mailcow)" > /tmp/postfix-tlspol-mailcow
+    host_ip=$(get_container_ip postfix-tlspol-mailcow)
+    err_c_cur=${err_count}
+    /usr/lib/nagios/plugins/check_tcp -4 -H ${host_ip} -p 8642 2>> /tmp/postfix-tlspol-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
+    [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
+    [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
+    progress "Postfix TLS Policy companion" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
+    if [[ $? == 10 ]]; then
+      diff_c=0
+      sleep 1
+    else
+      diff_c=0
+      sleep $(( ( RANDOM % 60 ) + 20 ))
+    fi
+  done
+  return 1
+}
+
 clamd_checks() {
   err_count=0
   diff_c=0
@@ -922,6 +952,18 @@ PID=$!
 echo "Spawned mailq_checks with PID ${PID}"
 BACKGROUND_TASKS+=(${PID})
 
+(
+while true; do
+  if ! postfix-tlspol_checks; then
+    log_msg "Postfix TLS Policy hit error limit"
+    echo postfix-tlspol-mailcow > /tmp/com_pipe
+  fi
+done
+) &
+PID=$!
+echo "Spawned postfix-tlspol_checks with PID ${PID}"
+BACKGROUND_TASKS+=(${PID})
+
 (
 while true; do
   if ! dovecot_checks; then

+ 4 - 4
data/conf/dovecot/auth/mailcowauth.php

@@ -86,7 +86,7 @@ if ($result === false){
     'remote_addr' => $post['real_rip']
   ));
   if ($result) {
-    error_log('MAILCOWAUTH: App auth for user ' . $post['username']);
+    error_log('MAILCOWAUTH: App auth for user ' . $post['username'] . " with service " . $post['service'] . " from IP " . $post['real_rip']);
     set_sasl_log($post['username'], $post['real_rip'], $post['service']);
   }
 }
@@ -94,9 +94,9 @@ if ($result === false){
   // Init Identity Provider
   $iam_provider = identity_provider('init');
   $iam_settings = identity_provider('get');
-  $result = user_login($post['username'], $post['password'], array('is_internal' => true));
+  $result = user_login($post['username'], $post['password'], array('is_internal' => true, 'service' => $post['service']));
   if ($result) {
-    error_log('MAILCOWAUTH: User auth for user ' . $post['username']);
+    error_log('MAILCOWAUTH: User auth for user ' . $post['username'] . " with service " . $post['service'] . " from IP " . $post['real_rip']);
     set_sasl_log($post['username'], $post['real_rip'], $post['service']);
   }
 }
@@ -105,7 +105,7 @@ if ($result) {
   http_response_code(200); // OK
   $return['success'] = true;
 } else {
-  error_log("MAILCOWAUTH: Login failed for user " . $post['username']);
+  error_log("MAILCOWAUTH: Login failed for user " . $post['username'] . " with service " . $post['service'] . " from IP " . $post['real_rip']);
   http_response_code(401); // Unauthorized
 }
 

+ 75 - 20
data/conf/postfix/postscreen_access.cidr

@@ -1,13 +1,25 @@
-# Whitelist generated by Postwhite v3.4 on Fri Aug  1 00:24:14 UTC 2025
+# Whitelist generated by Postwhite v3.4 on Mon Sep  1 00:23:07 UTC 2025
 # https://github.com/stevejenkins/postwhite/
-# 2166 total rules
+# 2165 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:8000::/51	permit
-2a01:111:f403::/49	permit
 2a01:111:f403:c000::/51	permit
 2a01:111:f403:f000::/52	permit
+2a01:238:20a:202:5370::1	permit
+2a01:238:20a:202:5372::1	permit
+2a01:238:20a:202:5373::1	permit
+2a01:238:400:101:53::1	permit
+2a01:238:400:102:53::1	permit
+2a01:238:400:103:53::1	permit
+2a01:238:400:301:53::1	permit
+2a01:238:400:302:53::1	permit
+2a01:238:400:303:53::1	permit
+2a01:238:400:470:53::1	permit
+2a01:238:400:471:53::1	permit
+2a01:238:400:472:53::1	permit
 2a01:b747:3000:200::/56	permit
 2a01:b747:3001:200::/56	permit
 2a01:b747:3002:200::/56	permit
@@ -17,16 +29,17 @@
 2a01:b747:3006:200::/56	permit
 2a02:a60:0:5::/64	permit
 2c0f:fb50:4000::/36	permit
-2.207.151.53	permit
 2.207.217.30	permit
 3.64.237.68	permit
 3.65.3.180	permit
 3.70.123.177	permit
 3.72.182.33	permit
 3.74.81.189	permit
+3.74.125.228	permit
 3.75.33.185	permit
 3.93.157.0/24	permit
 3.94.40.108	permit
+3.121.107.214	permit
 3.129.120.190	permit
 3.210.190.0/24	permit
 3.211.80.218	permit
@@ -42,7 +55,7 @@
 8.40.222.0/23	permit
 8.40.222.250/31	permit
 12.130.86.238	permit
-13.107.253.40	permit
+13.107.246.40	permit
 13.110.208.0/21	permit
 13.110.209.0/24	permit
 13.110.216.0/22	permit
@@ -64,6 +77,8 @@
 18.97.2.64/26	permit
 18.156.89.250	permit
 18.156.205.64	permit
+18.157.70.148	permit
+18.157.114.255	permit
 18.157.243.190	permit
 18.158.153.154	permit
 18.194.95.56	permit
@@ -75,9 +90,7 @@
 18.216.232.154	permit
 18.235.27.253	permit
 18.236.40.242	permit
-18.236.56.161	permit
 20.51.6.32/30	permit
-20.51.98.61	permit
 20.52.52.2	permit
 20.52.128.133	permit
 20.59.80.4/30	permit
@@ -153,7 +166,6 @@
 34.212.163.75	permit
 34.215.104.144	permit
 34.218.115.239	permit
-34.218.116.3	permit
 34.225.212.172	permit
 34.241.242.183	permit
 35.83.148.184	permit
@@ -171,6 +183,7 @@
 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
@@ -178,6 +191,7 @@
 40.233.64.216	permit
 40.233.83.78	permit
 40.233.88.28	permit
+43.239.212.33	permit
 44.206.138.57	permit
 44.210.169.44	permit
 44.217.45.156	permit
@@ -188,7 +202,10 @@
 44.246.68.102	permit
 44.246.77.92	permit
 45.14.148.0/22	permit
-46.19.170.16	permit
+45.143.132.0/24	permit
+45.143.133.0/24	permit
+45.143.134.0/24	permit
+45.143.135.0/24	permit
 46.226.48.0/21	permit
 46.228.36.37	permit
 46.228.36.38/31	permit
@@ -254,6 +271,9 @@
 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
@@ -304,6 +324,8 @@
 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
@@ -324,6 +346,7 @@
 54.255.61.23	permit
 56.124.6.228	permit
 57.103.64.0/18	permit
+57.129.93.249	permit
 62.13.128.0/24	permit
 62.13.129.128/25	permit
 62.13.136.0/21	permit
@@ -643,6 +666,11 @@
 77.238.189.142	permit
 77.238.189.146/31	permit
 77.238.189.148/30	permit
+79.135.106.0/24	permit
+79.135.107.0/24	permit
+81.169.146.243	permit
+81.169.146.245	permit
+81.169.146.246	permit
 81.223.46.0/27	permit
 82.165.159.2	permit
 82.165.159.3	permit
@@ -659,6 +687,14 @@
 82.165.159.130	permit
 82.165.159.131	permit
 85.158.136.0/21	permit
+85.215.255.39	permit
+85.215.255.40	permit
+85.215.255.41	permit
+85.215.255.45	permit
+85.215.255.46	permit
+85.215.255.47	permit
+85.215.255.48	permit
+85.215.255.49	permit
 86.61.88.25	permit
 87.238.80.0/21	permit
 87.248.103.12	permit
@@ -1342,9 +1378,9 @@
 108.174.6.215	permit
 108.175.18.45	permit
 108.175.30.45	permit
-108.177.8.0/22	permit
-108.177.96.0/19	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
 111.221.23.128/25	permit
 111.221.26.0/27	permit
@@ -1508,7 +1544,6 @@
 148.105.0.0/16	permit
 148.105.8.0/21	permit
 149.72.0.0/16	permit
-149.72.223.204	permit
 149.72.248.236	permit
 149.97.173.180	permit
 150.230.98.160	permit
@@ -1623,7 +1658,6 @@
 169.148.144.0/25	permit
 169.148.144.10	permit
 169.148.146.0/23	permit
-169.148.174.33	permit
 169.148.175.3	permit
 169.148.188.0/24	permit
 169.148.188.182	permit
@@ -1632,7 +1666,7 @@
 170.10.132.56/29	permit
 170.10.132.64/29	permit
 170.10.133.0/24	permit
-172.217.0.0/19	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
@@ -1671,6 +1705,9 @@
 185.12.80.0/22	permit
 185.28.196.0/22	permit
 185.58.84.93	permit
+185.70.40.0/24	permit
+185.70.41.0/24	permit
+185.70.43.0/24	permit
 185.80.93.204	permit
 185.80.93.227	permit
 185.80.95.31	permit
@@ -1732,6 +1769,7 @@
 188.125.85.234/31	permit
 188.125.85.236/31	permit
 188.125.85.238	permit
+188.165.51.139	permit
 188.172.128.0/20	permit
 192.0.64.0/18	permit
 192.18.139.154	permit
@@ -1758,6 +1796,8 @@
 193.142.157.191	permit
 193.142.157.198	permit
 194.19.134.0/25	permit
+194.25.134.16/28	permit
+194.25.134.80/28	permit
 194.64.234.129	permit
 194.97.196.0/24	permit
 194.97.196.3	permit
@@ -1957,8 +1997,6 @@
 208.71.42.212/31	permit
 208.71.42.214	permit
 208.72.249.240/29	permit
-208.74.204.5	permit
-208.74.204.9	permit
 208.75.120.0/22	permit
 208.76.62.0/24	permit
 208.76.63.0/24	permit
@@ -2022,6 +2060,8 @@
 212.227.15.4	permit
 212.227.15.5	permit
 212.227.15.6	permit
+212.227.15.7	permit
+212.227.15.8	permit
 212.227.15.14	permit
 212.227.15.15	permit
 212.227.15.18	permit
@@ -2038,16 +2078,30 @@
 212.227.15.53	permit
 212.227.15.54	permit
 212.227.15.55	permit
+212.227.17.1	permit
+212.227.17.2	permit
+212.227.17.7	permit
 212.227.17.11	permit
 212.227.17.12	permit
+212.227.17.16	permit
+212.227.17.17	permit
 212.227.17.18	permit
 212.227.17.19	permit
 212.227.17.20	permit
 212.227.17.21	permit
 212.227.17.22	permit
 212.227.17.26	permit
+212.227.17.27	permit
 212.227.17.28	permit
 212.227.17.29	permit
+212.227.126.206	permit
+212.227.126.207	permit
+212.227.126.208	permit
+212.227.126.209	permit
+212.227.126.220	permit
+212.227.126.221	permit
+212.227.126.222	permit
+212.227.126.223	permit
 212.227.126.224	permit
 212.227.126.225	permit
 212.227.126.226	permit
@@ -2155,16 +2209,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::/64	permit
 2620:109:c003:104::215	permit
-2620:109:c006:104::/64	permit
+2620:109:c003:104::/64	permit
 2620:109:c006:104::215	permit
+2620:109:c006:104::/64	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::/64	permit
 2620:119:50c0:207::215	permit
+2620:119:50c0:207::/64	permit
 2800:3f0:4000::/36	permit
-194.25.134.0/24 permit # t-online.de
+49.12.4.251 permit # checks.mailcow.email
+2a01:4f8:c17:7906::10 permit # checks.mailcow.email

+ 35 - 3
data/conf/rspamd/dynmaps/settings.php

@@ -56,7 +56,7 @@ function normalize_email($email) {
     $email = explode('@', $email);
     $email[0] = str_replace('.', '', $email[0]);
     $email = implode('@', $email);
-  } 
+  }
   $gm_alt = "@googlemail.com";
   if (substr_compare($email, $gm_alt, -strlen($gm_alt)) == 0) {
     $email = explode('@', $email);
@@ -114,7 +114,7 @@ function ucl_rcpts($object, $type) {
       $rcpt[] = str_replace('/', '\/', $row['address']);
     }
     // Aliases by alias domains
-    $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox` 
+    $stmt = $pdo->prepare("SELECT CONCAT(`local_part`, '@', `alias_domain`.`alias_domain`) AS `alias` FROM `mailbox`
       LEFT OUTER JOIN `alias_domain` ON `mailbox`.`domain` = `alias_domain`.`target_domain`
       WHERE `mailbox`.`username` = :object");
     $stmt->execute(array(
@@ -184,7 +184,7 @@ while ($row = array_shift($rows)) {
     rcpt = <?=json_encode($rcpt, JSON_UNESCAPED_SLASHES);?>;
 <?php
   }
-  $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf` 
+  $stmt = $pdo->prepare("SELECT `option`, `value` FROM `filterconf`
     WHERE (`option` = 'highspamlevel' OR `option` = 'lowspamlevel')
       AND `object`= :object");
   $stmt->execute(array(':object' => $row['object']));
@@ -468,4 +468,36 @@ while ($row = array_shift($rows)) {
 <?php
 }
 ?>
+
+<?php
+// Start internal aliases
+
+$stmt = $pdo->query("SELECT `id`, `address`, `domain` FROM `alias` WHERE `active` = '1' AND `internal` = '1'");
+$aliases = $stmt->fetchAll(PDO::FETCH_ASSOC);
+while ($alias = array_shift($aliases)) {
+  // build allowed_domains regex and add target domain and alias domains
+  $stmt = $pdo->prepare("SELECT `alias_domain` FROM `alias_domain` WHERE `active` = '1' AND `target_domain` = :target_domain");
+  $stmt->execute(array(':target_domain' => $alias['domain']));
+  $allowed_domains = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  $allowed_domains = array_map(function($item) {
+    return str_replace('.', '\.', $item['alias_domain']);
+  }, $allowed_domains);
+  $allowed_domains[] = str_replace('.', '\.', $alias['domain']);
+  $allowed_domains = implode('|', $allowed_domains);
+?>
+  internal_alias_<?=$alias['id'];?> {
+    priority = 10;
+    rcpt = "<?=$alias['address'];?>";
+    from = "/^((?!.*@(<?=$allowed_domains;?>)).)*$/";
+    apply "default" {
+      MAILCOW_INTERNAL_ALIAS = 9999.0;
+    }
+    symbols [
+      "MAILCOW_INTERNAL_ALIAS"
+    ]
+  }
+<?php
+}
+?>
+
 }

+ 24 - 14
data/conf/rspamd/lua/rspamd.local.lua

@@ -454,12 +454,18 @@ rspamd_config:register_symbol({
     local redis_params = rspamd_parse_redis_server('dyn_rl')
     local rspamd_logger = require "rspamd_logger"
     local envfrom = task:get_from(1)
+    local envrcpt = task:get_recipients(1) or {}
     local uname = task:get_user()
     if not envfrom or not uname then
       return false
     end
+
     local uname = uname:lower()
 
+    if #envrcpt == 1 and envrcpt[1].addr:lower() == uname then
+      return false
+    end
+
     local env_from_domain = envfrom[1].domain:lower() -- get smtp from domain in lower case
 
     local function redis_cb_user(err, data)
@@ -544,13 +550,13 @@ rspamd_config:register_symbol({
     -- determine newline type
     local function newline(task)
       local t = task:get_newlines_type()
-    
+
       if t == 'cr' then
         return '\r'
       elseif t == 'lf' then
         return '\n'
       end
-    
+
       return '\r\n'
     end
     -- retrieve footer
@@ -558,7 +564,7 @@ rspamd_config:register_symbol({
       if err or type(data) ~= 'string' then
         rspamd_logger.infox(rspamd_config, "domain wide footer request for user %s returned invalid or empty data (\"%s\") or error (\"%s\")", uname, data, err)
       else
-        
+
         -- parse json string
         local footer = cjson.decode(data)
         if not footer then
@@ -607,26 +613,30 @@ rspamd_config:register_symbol({
             if footer.plain and footer.plain ~= "" then
               footer.plain = lua_util.jinja_template(footer.plain, replacements, true)
             end
-  
+
             -- add footer
             local out = {}
             local rewrite = lua_mime.add_text_footer(task, footer.html, footer.plain) or {}
-        
+
             local seen_cte
             local newline_s = newline(task)
-        
+
             local function rewrite_ct_cb(name, hdr)
               if rewrite.need_rewrite_ct then
                 if name:lower() == 'content-type' then
-                  local nct = string.format('%s: %s/%s; charset=utf-8',
-                      'Content-Type', rewrite.new_ct.type, rewrite.new_ct.subtype)
+                  -- include boundary if present
+                  local boundary_part = rewrite.new_ct.boundary and
+                    string.format('; boundary="%s"', rewrite.new_ct.boundary) or ''
+                  local nct = string.format('%s: %s/%s; charset=utf-8%s',
+                      'Content-Type', rewrite.new_ct.type, rewrite.new_ct.subtype, boundary_part)
                   out[#out + 1] = nct
-                  -- update Content-Type header
+                  -- update Content-Type header (include boundary if present)
                   task:set_milter_reply({
                     remove_headers = {['Content-Type'] = 0},
                   })
                   task:set_milter_reply({
-                    add_headers = {['Content-Type'] = string.format('%s/%s; charset=utf-8', rewrite.new_ct.type, rewrite.new_ct.subtype)}
+                    add_headers = {['Content-Type'] = string.format('%s/%s; charset=utf-8%s',
+                      rewrite.new_ct.type, rewrite.new_ct.subtype, boundary_part)}
                   })
                   return
                 elseif name:lower() == 'content-transfer-encoding' then
@@ -645,16 +655,16 @@ rspamd_config:register_symbol({
               end
               out[#out + 1] = hdr.raw:gsub('\r?\n?$', '')
             end
-        
+
             task:headers_foreach(rewrite_ct_cb, {full = true})
-        
+
             if not seen_cte and rewrite.need_rewrite_ct then
               out[#out + 1] = string.format('%s: %s', 'Content-Transfer-Encoding', 'quoted-printable')
             end
-        
+
             -- End of headers
             out[#out + 1] = newline_s
-        
+
             if rewrite.out then
               for _,o in ipairs(rewrite.out) do
                 out[#out + 1] = o

+ 19 - 17
data/web/inc/footer.inc.php

@@ -26,23 +26,25 @@ if (is_array($alertbox_log_parser)) {
 
 // map tfa details for twig
 $pending_tfa_authmechs = [];
-foreach($_SESSION['pending_tfa_methods'] as $authdata){
-  $pending_tfa_authmechs[$authdata['authmech']] = false;
-}
-if (isset($pending_tfa_authmechs['webauthn'])) {
-  $pending_tfa_authmechs['webauthn'] = true;
-}
-if (!isset($pending_tfa_authmechs['webauthn']) 
-    && isset($pending_tfa_authmechs['yubi_otp'])) {
-  $pending_tfa_authmechs['yubi_otp'] = true;
-}
-if (!isset($pending_tfa_authmechs['webauthn']) 
-    && !isset($pending_tfa_authmechs['yubi_otp'])
-    && isset($pending_tfa_authmechs['totp'])) {
-  $pending_tfa_authmechs['totp'] = true;
-}
-if (isset($pending_tfa_authmechs['u2f'])) {
-  $pending_tfa_authmechs['u2f'] = true;
+if (array_key_exists('pending_tfa_methods', $_SESSION)) {
+  foreach($_SESSION['pending_tfa_methods'] as $authdata){
+    $pending_tfa_authmechs[$authdata['authmech']] = false;
+  }
+  if (isset($pending_tfa_authmechs['webauthn'])) {
+    $pending_tfa_authmechs['webauthn'] = true;
+  }
+  if (!isset($pending_tfa_authmechs['webauthn']) 
+      && isset($pending_tfa_authmechs['yubi_otp'])) {
+    $pending_tfa_authmechs['yubi_otp'] = true;
+  }
+  if (!isset($pending_tfa_authmechs['webauthn']) 
+      && !isset($pending_tfa_authmechs['yubi_otp'])
+      && isset($pending_tfa_authmechs['totp'])) {
+    $pending_tfa_authmechs['totp'] = true;
+  }
+  if (isset($pending_tfa_authmechs['u2f'])) {
+    $pending_tfa_authmechs['u2f'] = true;
+  }
 }
 
 // globals

+ 16 - 0
data/web/inc/functions.auth.inc.php

@@ -193,6 +193,7 @@ function user_login($user, $pass, $extra = null){
   global $iam_settings;
 
   $is_internal = $extra['is_internal'];
+  $service = $extra['service'];
 
   if (!filter_var($user, FILTER_VALIDATE_EMAIL) && !ctype_alnum(str_replace(array('_', '.', '-'), '', $user))) {
     if (!$is_internal){
@@ -235,6 +236,14 @@ function user_login($user, $pass, $extra = null){
       $row = $stmt->fetch(PDO::FETCH_ASSOC);
 
       if (!empty($row)) {
+        // check if user has access to service (imap, smtp, pop3, sieve) if service is set
+        $row['attributes'] = json_decode($row['attributes'], true);
+        if (isset($service)) {
+          $key = strtolower($service) . "_access";
+          if (isset($row['attributes'][$key]) && $row['attributes'][$key] != '1') {
+            return false;
+          }
+        }
         return true;
       }
     }
@@ -242,7 +251,14 @@ function user_login($user, $pass, $extra = null){
     return false;
   }
 
+  // check if user has access to service (imap, smtp, pop3, sieve) if service is set
   $row['attributes'] = json_decode($row['attributes'], true);
+  if (isset($service)) {
+    $key = strtolower($service) . "_access";
+    if (isset($row['attributes'][$key]) && $row['attributes'][$key] != '1') {
+      return false;
+    }
+  }
   switch ($row['authsource']) {
     case 'keycloak':
       // user authsource is keycloak, try using via rest flow

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

@@ -293,7 +293,7 @@ function customize($_action, $_item, $_data = null) {
           }
 
           if (empty($app_links)){
-            return false;
+            return [];
           }
 
           // convert from old style

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

@@ -2221,7 +2221,7 @@ function cors($action, $data = null) {
       $cors_settings['allowed_origins'] = $allowed_origins[0];
       if (in_array('*', $allowed_origins)){
         $cors_settings['allowed_origins'] = '*';
-      } else if (in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)) {
+      } else if (array_key_exists('HTTP_ORIGIN', $_SERVER) && in_array($_SERVER['HTTP_ORIGIN'], $allowed_origins)) {
         $cors_settings['allowed_origins'] = $_SERVER['HTTP_ORIGIN'];
       }
       // always allow OPTIONS for preflight request

+ 18 - 10
data/web/inc/functions.mailbox.inc.php

@@ -685,15 +685,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           return true;
         break;
         case 'alias':
-          $addresses  = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
-          $gotos      = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
-          $active = intval($_data['active']);
-          $sogo_visible = intval($_data['sogo_visible']);
-          $goto_null = intval($_data['goto_null']);
-          $goto_spam = intval($_data['goto_spam']);
-          $goto_ham = intval($_data['goto_ham']);
+          $addresses       = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['address']));
+          $gotos           = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['goto']));
+          $internal        = intval($_data['internal']);
+          $active          = intval($_data['active']);
+          $sogo_visible    = intval($_data['sogo_visible']);
+          $goto_null       = intval($_data['goto_null']);
+          $goto_spam       = intval($_data['goto_spam']);
+          $goto_ham        = intval($_data['goto_ham']);
           $private_comment = $_data['private_comment'];
-          $public_comment = $_data['public_comment'];
+          $public_comment  = $_data['public_comment'];
           if (strlen($private_comment) > 160 | strlen($public_comment) > 160){
             $_SESSION['return'][] = array(
               'type' => 'danger',
@@ -843,8 +844,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
               );
               continue;
             }
-            $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `active`)
-              VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :active)");
+            $stmt = $pdo->prepare("INSERT INTO `alias` (`address`, `public_comment`, `private_comment`, `goto`, `domain`, `sogo_visible`, `internal`, `active`)
+              VALUES (:address, :public_comment, :private_comment, :goto, :domain, :sogo_visible, :internal, :active)");
             if (!filter_var($address, FILTER_VALIDATE_EMAIL) === true) {
               $stmt->execute(array(
                 ':address' => '@'.$domain,
@@ -854,6 +855,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':goto' => $goto,
                 ':domain' => $domain,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active
               ));
             }
@@ -865,6 +867,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':goto' => $goto,
                 ':domain' => $domain,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active
               ));
             }
@@ -2482,6 +2485,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           foreach ($ids as $id) {
             $is_now = mailbox('get', 'alias_details', $id);
             if (!empty($is_now)) {
+              $internal = (isset($_data['internal'])) ? intval($_data['internal']) : $is_now['internal'];
               $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
               $sogo_visible = (isset($_data['sogo_visible'])) ? intval($_data['sogo_visible']) : $is_now['sogo_visible'];
               $goto_null = (isset($_data['goto_null'])) ? intval($_data['goto_null']) : 0;
@@ -2667,6 +2671,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 `domain` = :domain,
                 `goto` = :goto,
                 `sogo_visible`= :sogo_visible,
+                `internal`= :internal,
                 `active`= :active
                   WHERE `id` = :id");
               $stmt->execute(array(
@@ -2676,6 +2681,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
                 ':domain' => $domain,
                 ':goto' => $goto,
                 ':sogo_visible' => $sogo_visible,
+                ':internal' => $internal,
                 ':active' => $active,
                 ':id' => $is_now['id']
               ));
@@ -4701,6 +4707,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
             `address`,
             `public_comment`,
             `private_comment`,
+            `internal`,
             `active`,
             `sogo_visible`,
             `created`,
@@ -4731,6 +4738,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           $aliasdata['goto'] = $row['goto'];
           $aliasdata['address'] = $row['address'];
           (!filter_var($aliasdata['address'], FILTER_VALIDATE_EMAIL)) ? $aliasdata['is_catch_all'] = 1 : $aliasdata['is_catch_all'] = 0;
+          $aliasdata['internal'] = $row['internal'];
           $aliasdata['active'] = $row['active'];
           $aliasdata['active_int'] = $row['active'];
           $aliasdata['sogo_visible'] = $row['sogo_visible'];

+ 2 - 1
data/web/inc/init_db.inc.php

@@ -4,7 +4,7 @@ function init_db_schema()
   try {
     global $pdo;
 
-    $db_version = "19082025_1436";
+    $db_version = "11092025_1026";
 
     $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
     $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -184,6 +184,7 @@ function init_db_schema()
           "private_comment" => "TEXT",
           "public_comment" => "TEXT",
           "sogo_visible" => "TINYINT(1) NOT NULL DEFAULT '1'",
+          "internal" => "TINYINT(1) NOT NULL DEFAULT '0'",
           "active" => "TINYINT(1) NOT NULL DEFAULT '1'"
         ),
         "keys" => array(

+ 9 - 0
data/web/js/site/mailbox.js

@@ -1972,6 +1972,15 @@ jQuery(function($){
           data: 'private_comment',
           defaultContent: ''
         },
+        {
+          title: lang.internal,
+          data: 'internal',
+          defaultContent: '',
+          responsivePriority: 6,
+          render: function (data, type) {
+            return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
+          }
+        },
         {
           title: lang.active,
           data: 'active',

+ 9 - 2
data/web/lang/lang.de-de.json

@@ -71,6 +71,8 @@
         "goto_spam": "Nachrichten als <span class=\"text-danger\"><b>Spam</b></span> lernen",
         "hostname": "Host",
         "inactive": "Inaktiv",
+        "internal": "Intern",
+        "internal_info": "Interne Aliasse sind nur von der eigenen Domäne oder Alias-Domänen erreichbar.",
         "kind": "Art",
         "mailbox_quota_def": "Standard-Quota einer Mailbox",
         "mailbox_quota_m": "Max. Speicherplatz pro Mailbox (MiB)",
@@ -408,7 +410,8 @@
         "allowed_origins": "Access-Control-Allow-Origin",
         "logo_dark_label": "Invertiert für den Darkmode",
         "logo_normal_label": "Normal",
-        "user_link": "Nutzer-Link"
+        "user_link": "Nutzer-Link",
+        "filter": "Filter"
     },
     "danger": {
         "access_denied": "Zugriff verweigert oder unvollständige/ungültige Daten",
@@ -689,6 +692,8 @@
         "grant_types": "Grant-types",
         "hostname": "Servername",
         "inactive": "Inaktiv",
+        "internal": "Intern",
+        "internal_info": "Interne Aliasse sind nur von der eigenen Domäne oder Alias-Domänen erreichbar.",
         "kind": "Art",
         "last_modified": "Zuletzt geändert",
         "lookup_mx": "Ziel mit MX vergleichen (Regex, etwa <code>.*\\.google\\.com</code>, um alle Ziele mit MX *google.com zu routen)",
@@ -846,7 +851,8 @@
         "password": "Passwort",
         "reset_password": "Passwort zurücksetzen",
         "request_reset_password": "Passwortänderung anfordern",
-        "username": "Benutzername"
+        "username": "Benutzername",
+        "email": "E-Mail-Adresse"
     },
     "mailbox": {
         "action": "Aktion",
@@ -921,6 +927,7 @@
         "in_use": "Prozentualer Gebrauch",
         "inactive": "Inaktiv",
         "insert_preset": "Beispiel \"%s\" laden",
+        "internal": "Intern",
         "kind": "Art",
         "last_mail_login": "Letzter Mail-Login",
         "last_modified": "Zuletzt geändert",

+ 8 - 2
data/web/lang/lang.en-gb.json

@@ -71,6 +71,8 @@
         "goto_spam": "Learn as <span class=\"text-danger\"><b>spam</b></span>",
         "hostname": "Host",
         "inactive": "Inactive",
+        "internal": "Internal",
+        "internal_info": "Internal aliases are only accessible from the own domain or alias domains.",
         "kind": "Kind",
         "mailbox_quota_def": "Default mailbox quota",
         "mailbox_quota_m": "Max. quota per mailbox (MiB)",
@@ -690,6 +692,8 @@
         "grant_types": "Grant types",
         "hostname": "Hostname",
         "inactive": "Inactive",
+        "internal": "Internal",
+        "internal_info": "Internal aliases are only accessible from the own domain or alias domains.",
         "kind": "Kind",
         "last_modified": "Last modified",
         "lookup_mx": "Destination is a regular expression to match against MX name (<code>.*\\.google\\.com</code> to route all mail targeted to a MX ending in google.com over this hop)",
@@ -711,7 +715,7 @@
         "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> is a standard that enforces email delivery between mail servers to use TLS with valid certificates. <br>It is used when <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a> is not possible due to missing or unsupported DNSSEC.<br><b>Note</b>: If the receiving domain supports DANE with DNSSEC, DANE is <b>always</b> preferred – MTA-STS only acts as a fallback.",
         "mta_sts_version": "Version",
-        "mta_sts_version_info": "Defines the version of the MTA-STS standard – currently only <code>STSv1</code> is valid." ,
+        "mta_sts_version_info": "Defines the version of the MTA-STS standard – currently only <code>STSv1</code> is valid.",
         "mta_sts_mode": "Mode",
         "mta_sts_mode_info": "There are three modes to choose from:<ul><li><em>testing</em> – policy is only monitored, violations have no impact.</li><li><em>enforce</em> – policy is strictly enforced, connections without valid TLS are rejected.</li><li><em>none</em> – policy is published but not applied.</li></ul>",
         "mta_sts_max_age": "Max age",
@@ -847,7 +851,8 @@
         "password": "Password",
         "reset_password": "Reset Password",
         "request_reset_password": "Request password change",
-        "username": "Username"
+        "username": "Username",
+        "email": "Email address"
     },
     "mailbox": {
         "action": "Action",
@@ -927,6 +932,7 @@
         "in_use": "In use (%)",
         "inactive": "Inactive",
         "insert_preset": "Insert example preset \"%s\"",
+        "internal": "Internal",
         "kind": "Kind",
         "last_mail_login": "Last mail login",
         "last_modified": "Last modified",

+ 590 - 38
data/web/lang/lang.hu-hu.json

@@ -9,11 +9,11 @@
         "source": "Forrás",
         "spamfilter": "Spam szűrő",
         "subject": "Tárgy",
-        "sys_mails": "Rendszer-üzenetek",
+        "sys_mails": "Rendszer e-mailek",
         "text": "Szöveg",
         "time": "Idő",
         "title": "Cím",
-        "title_name": "\"mailcow UI\" website címe",
+        "title_name": "\"mailcow UI\" weboldal címe",
         "to_top": "Vissza a tetejére",
         "transport_dest_format": "Szintaxis: pelda.hu, .pelda.hu, *, fiok@pelda.hu (több érték esetén vesszővel elválasztva)",
         "upload": "Feltöltés",
@@ -29,14 +29,14 @@
         "logo_dark_label": "Sötét üzemmódhoz invertálva",
         "f2b_regex_info": "Figyelembe vett naplók: SOGo, Postfix, Dovecot, PHP-FPM.",
         "f2b_retry_window": "Újrapróbálkozási ablak (s) a maximális próbálkozásokhoz",
-        "f2b_whitelist": "Fehérlistás hálózatok/hostok",
+        "f2b_whitelist": "Engedélyezési listás hálózatok/hostok",
         "filter_table": "Szűrő táblázat",
         "forwarding_hosts": "Továbbító hostok",
-        "forwarding_hosts_add_hint": "Megadhat IPv4/IPv6 címeket, hálózatokat CIDR jelölésben, állomásneveket (amelyek IP-címekre lesznek feloldva) vagy tartományneveket (amelyek IP-címekre lesznek feloldva az SPF rekordok vagy ezek hiányában az MX rekordok lekérdezésével).",
+        "forwarding_hosts_add_hint": "Megadhat IPv4/IPv6 címeket, hálózatokat CIDR jelölésben, állomásneveket (amelyek IP címekre lesznek feloldva) vagy tartományneveket (amelyek IP címekre lesznek feloldva az SPF rekordok vagy ezek hiányában az MX rekordok lekérdezésével).",
         "from": "A címről",
         "copy_to_clipboard": "Szöveg másolva a vágólapra!",
         "f2b_manage_external": "A Fail2Ban külső kezelése",
-        "f2b_manage_external_info": "A Fail2ban továbbra is karbantartja a tiltólistát, de nem állít be aktívan szabályokat a forgalom blokkolására. Használja az alábbi generált tiltólistát a forgalom külső blokkolásához.",
+        "f2b_manage_external_info": "A Fail2ban továbbra is karbantartja a tiltólistát, de nem állít be aktívan szabályokat a forgalom blokkolásához. Használja az alábbi generált tiltólistát a forgalom külső blokkolásához.",
         "f2b_max_ban_time": "Maximális tiltási idő (s)",
         "f2b_netban_ipv4": "IPv4 alhálózat mérete, amelyre tilalmat kell alkalmazni (8-32)",
         "f2b_netban_ipv6": "IPv6 alhálózat mérete, amelyre tilalmat kell alkalmazni (8-128)",
@@ -47,13 +47,13 @@
         "html": "HTML",
         "import": "Import",
         "ip_check": "IP ellenőrzés",
-        "ip_check_disabled": "Az IP-ellenőrzés le van tiltva. Bekapcsolhatja a következő menüpont alatt<br> <strong>Rendszer > Beállítások > Opciók > Személyreszabás</strong>",
+        "ip_check_disabled": "Az IP ellenőrzés le van tiltva. Bekapcsolhatja a következő menüpont alatt<br> <strong>Rendszer > Beállítások > Opciók > Személyreszabás</strong>",
         "is_mx_based": "MX alapú",
         "last_applied": "Utoljára alkalmazott",
         "link": "Link",
         "loading": "Kérjük, várj...",
         "login_time": "Bejelentkezési idő",
-        "f2b_list_info": "Egy feketelistán szereplő állomás vagy hálózat mindig nagyobb súlyú, mint egy fehérlistás entitás. <b>A lista frissítései néhány másodpercig tartanak.</b>",
+        "f2b_list_info": "Egy tiltólistán szereplő állomás vagy hálózat mindig nagyobb súlyú, mint egy engedélyezési listás elem. <b>A lista frissítései néhány másodpercig tartanak.</b>",
         "f2b_ban_time_increment": "A tiltási idő minden egyes tiltással növekszik",
         "additional_rows": " - további sorokat adtak hozzá",
         "admin": "Adminisztrátor",
@@ -68,7 +68,7 @@
         "api_key": "API-kulcs",
         "api_read_only": "Csak olvasható hozzáférés",
         "api_read_write": "Olvasás-írás hozzáférés",
-        "api_skip_ip_check": "IP-ellenőrzés kihagyása az API esetében",
+        "api_skip_ip_check": "IP ellenőrzés kihagyása az API esetében",
         "cors_settings": "CORS beállítások",
         "guid": "GUID - egyedi példányazonosító",
         "dkim_to": "A címre",
@@ -82,8 +82,8 @@
         "edit": "Szerkesztés",
         "empty": "Nincs eredmény",
         "excludes": "Kizárja ezeket a kedvezményezetteket",
-        "f2b_ban_time": "Tilalmi idő (s)",
-        "f2b_blacklist": "Feketelistás hálózatok/hostok",
+        "f2b_ban_time": "Tiltás időtartam (s)",
+        "f2b_blacklist": "Tiltólistás címek",
         "f2b_filter": "Regex szűrők",
         "logo_info": "A képed 40px magasságúra lesz méretezve a felső navigációs sávhoz és max. 250px szélességűre a kezdőlaphoz. A skálázható grafika használata erősen ajánlott.",
         "dkim_add_key": "ARC/DKIM kulcs hozzáadása",
@@ -122,21 +122,187 @@
         "arrival_time": "Érkezési idő (szerveridő)",
         "authed_user": "Azonosított felhasználó",
         "ays": "Biztos, hogy folytatni akarod?",
-        "ban_list_info": "A tiltott IP-címek listáját lásd alább: <b>hálózat (fennmaradó tiltási idő) - [akciók]</b>.<br />A tiltás feloldására várakozó IP-ket néhány másodpercen belül eltávolítjuk az aktív tiltási listáról.<br />A piros címkék a feketelistán szereplő aktív állandó tiltásokat jelzik.",
+        "ban_list_info": "A tiltott IP címek listáját lásd alább: <b>hálózat (fennmaradó tiltási idő) - [akciók]</b>.<br />A tiltás feloldására várakozó IP-ket néhány másodpercen belül eltávolítjuk az aktív tiltási listáról.<br />A piros címkék a tiltólistán szereplő aktív állandó tiltásokat jelzik.",
         "configuration": "Konfiguráció",
         "convert_html_to_text": "HTML átalakítása egyszerű szöveggé",
         "credentials_transport_warning": "<b>Figyelmeztetés</b>: Egy új közlekedési térképbejegyzés hozzáadása frissíti a hitelesítő adatokat minden olyan bejegyzéshez, amelynek a következő ugrás oszlopa megegyezik.",
         "customize": "Testreszabás",
         "destination": "Célállomás",
         "customer_id": "Ügyfél azonosító",
-        "apps_name": "\"mailcow Apps\" név"
+        "apps_name": "\"mailcow Apps\" név",
+        "admin_quicklink": "Gyorshivatkozás elrejtése az Adminisztrátori bejelentkezési oldalra",
+        "app_hide": "Elrejtés a bejelentkezéshez",
+        "domainadmin_quicklink": "Gyorshivatkozás elrejtése a Domain adminisztrátori bejelentkezési oldalra",
+        "filter": "Szűrő",
+        "force_sso_text": "Ha egy külső OIDC-szolgáltató van beállítva, ez az opció elrejti az alapértelmezett mailcow bejelentkezési űrlapokat, és csak az egységes bejelentkezési (Single Sign-On) gombot jeleníti meg",
+        "force_sso": "A mailcow bejelentkezés letiltása és csak az egységes bejelentkezés megjelenítése",
+        "hash_remove_info": "Egy arányszám-korlát hash eltávolítása (ha még létezik) teljesen visszaállítja a számlálóját.<br>\r\n  Minden hash-t egyedi szín jelöl.",
+        "iam": "Azonosítási szolgáltató",
+        "iam_attribute_field": "Attribútum mező",
+        "iam_authorize_url": "Engedélyezési végpont",
+        "iam_auth_flow": "Azonosítási folyamat",
+        "iam_auth_flow_info": "Az engedélyezési kód áramláson (Authorization Code Flow) kívül, amelyet az egységes bejelentkezéshez (Single-Sign On) használnak (ez a standard áramlás Keycloak-ban), a mailcow támogatja a közvetlen hitelesítő adatokkal történő hitelesítési áramlást is. A Jelszóáramlás (Mailpassword Flow) megpróbálja érvényesíteni a felhasználó hitelesítő adatait a Keycloak Admin REST API használatával. A mailcow a <code>mailcow_password</code> attribútumból olvassa be a hash-elt jelszót, amely a Keycloak-ban van leképezve.",
+        "iam_basedn": "Bázis DN",
+        "iam_client_id": "Kliens azonosító",
+        "iam_client_secret": "Kliens titok",
+        "iam_client_scopes": "Kliens hatókörök",
+        "iam_default_template": "Alapértelmezett sablon",
+        "iam_default_template_description": "Ha nincs sablon hozzárendelve egy felhasználóhoz, az alapértelmezett sablon lesz felhasználva a postafiók létrehozásához, de a postafiók frissítéséhez nem.",
+        "iam_description": "Külső azonosítási szolgáltató konfigurálása.<br>A felhasználók postafiókjai automatikusan létrejönnek az első bejelentkezéskor, feltéve, hogy van attribútum-hozzárendelés beállítva.",
+        "iam_extra_permission": "A következő beállításokhoz a Keycloak-ban lévő mailcow kliensnek szüksége van egy <code>Service account</code>-ra és a <code>view-users</code> engedélyre.",
+        "iam_host": "Házigazda",
+        "iam_host_info": "Adjon meg egy vagy több LDAP állomást, vesszővel elválasztva.",
+        "iam_import_users": "Felhasználók importálása",
+        "iam_login_provisioning": "Felhasználók automatikus létrehozása bejelentkezéskor",
+        "iam_mapping": "Attribútum-hozzárendelés",
+        "iam_bindpass": "Bind jelszó",
+        "iam_periodic_full_sync": "Időszakos teljes szinkronizálás",
+        "iam_port": "Port",
+        "iam_realm": "Tartomány",
+        "iam_redirect_url": "Átirányítási URL",
+        "iam_rest_flow": "Mailpassword Flow",
+        "iam_server_url": "Szerver URL",
+        "iam_sso": "Egységes bejelentkezés",
+        "iam_sync_interval": "Szinkronizálási / importálási időtartam (perc)",
+        "iam_test_connection": "Kapcsolat tesztelése",
+        "iam_token_url": "Token végpont",
+        "iam_userinfo_url": "Felhasználói információ végpont",
+        "iam_username_field": "Felhasználónév mező",
+        "iam_binddn": "Bind DN",
+        "iam_use_ssl": "SSL használata",
+        "iam_use_ssl_info": "Ha az SSL-t engedélyezi, és a port 389-re van állítva, az automatikusan felülíródik 636-ra.",
+        "iam_use_tls": "StartTLS használata",
+        "iam_use_tls_info": "Ha a TLS-t engedélyezi, az LDAP szerver alapértelmezett portját kell használnia (389). Az SSL portok nem használhatók.",
+        "iam_version": "Verzió",
+        "ignore_ssl_error": "SSL hibák figyelmen kívül hagyása",
+        "ip_check_opt_in": "Választás a harmadik féltől származó <strong>ipv4.mailcow.email</strong> és <strong>ipv6.mailcow.email</strong> szolgáltatás használatára a külső IP címek feloldásához.",
+        "license_info": "A licensz nem kötelező, de segít a további fejlesztésben.<br><a href=\"https://www.servercow.de/mailcow?lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Regisztrálja a GUID-ját itt</a> vagy <a href=\"https://www.servercow.de/mailcow?lang=en#support\" target=\"_blank\" alt=\"Support order\">vásároljon támogatást a mailcow telepítéséhez.</a>",
+        "lookup_mx": "A cél egy reguláris kifejezés, amely illeszkedik az MX névre (<code>.*\\.google\\.com</code>, hogy a google.com-ra végződő MX-en keresztül továbbítsa az összes levelet)",
+        "main_name": "\"mailcow UI\" név",
+        "merged_vars_hint": "A szürkével jelölt sorok a <code>vars.(local.)inc.php</code> fájlból lettek összevonva, és nem módosíthatók.",
+        "message": "Üzenet",
+        "message_size": "Üzenet mérete",
+        "nexthop": "Következő ugrás",
+        "no": "&#10005;",
+        "no_active_bans": "Nincs aktív tiltás",
+        "no_new_rows": "Nincs több sor elérhető",
+        "no_record": "Nincs bejegyzés",
+        "oauth2_apps": "OAuth2 alkalmazások",
+        "oauth2_add_client": "OAuth2 kliens hozzáadása",
+        "oauth2_client_id": "Kliens azonosító",
+        "oauth2_client_secret": "Kliens titok",
+        "oauth2_info": "Az OAuth2 implementáció támogatja az \"Authorization Code\" engedélyezési típust és frissítési tokeneket ad ki.<br>\r\nA szerver automatikusan új frissítési tokeneket is kiad, miután egy frissítési token fel lett használva.<br><br>\r\n&#8226; Az alapértelmezett hatókör a <i>profile</i>. Csak postafiók-felhasználók hitelesíthetők az OAuth2-vel szemben. Ha a scope paraméter elmarad, az visszaesik a <i>profile</i>-ra.<br>\r\n&#8226; A <i>state</i> paramétert a kliensnek kötelező elküldenie az engedélyezési kérelem részeként.<br><br>\r\nAz OAuth2 API-hoz intézett kérések útvonalai: <br>\r\n<ul>\r\n  <li>Engedélyezési végpont: <code>/oauth/authorize</code></li>\r\n  <li>Token végpont: <code>/oauth/token</code></li>\r\n  <li>Erőforrás oldal:  <code>/oauth/profile</code></li>\r\n</ul>\r\nA kliens titok újragenerálása nem jár le a meglévő engedélyezési kódok lejáratával, de azok nem tudják megújítani a tokenjüket.<br><br>\r\nA kliens tokenek visszavonása az összes aktív munkamenet azonnali leállítását okozza. Minden kliensnek újra kell hitelesítenie magát.",
+        "oauth2_redirect_uri": "Átirányítási URI",
+        "oauth2_renew_secret": "Új kliens titok generálása",
+        "oauth2_revoke_tokens": "Minden kliens token visszavonása",
+        "optional": "opcionális",
+        "options": "Opciók",
+        "password": "Jelszó",
+        "password_length": "Jelszó hossza",
+        "password_policy": "Jelszó házirend",
+        "password_policy_chars": "Legalább egy betűkaraktert kell tartalmaznia",
+        "password_policy_length": "A jelszó minimális hossza %d",
+        "password_policy_lowerupper": "Kis- és nagybetűket kell tartalmaznia",
+        "password_policy_numbers": "Legalább egy számot kell tartalmaznia",
+        "password_policy_special_chars": "Speciális karaktereket kell tartalmaznia",
+        "password_repeat": "Megerősítő jelszó (ismétlés)",
+        "password_reset_info": "Ha nincs megadva helyreállítási e-mail cím, ez a funkció nem használható.",
+        "password_reset_settings": "Jelszó-helyreállítási beállítások",
+        "password_reset_tmpl_html": "HTML sablon",
+        "password_reset_tmpl_text": "Szöveges sablon",
+        "password_settings": "Jelszó beállítások",
+        "priority": "Prioritás",
+        "private_key": "Privát kulcs",
+        "quarantine": "Karantén",
+        "quarantine_bcc": "Az összes értesítés másolatának elküldése (BCC) erre a címzettnek:<br><small>Hagyja üresen a letiltáshoz. <b>Aláíratlan, nem ellenőrzött levél. Csak belső kézbesítésre alkalmas.</b></small>",
+        "quarantine_exclude_domains": "Tartományok és alias-tartományok kizárása",
+        "quarantine_max_age": "Maximális életkor napokban<br><small>Az értéknek legalább 1 napnak kell lennie.</small>",
+        "quarantine_max_score": "Az értesítés elvetése, ha egy levél spam pontszáma magasabb ennél az értéknél:<br><small>Alapértelmezett értéke 9999.0</small>",
+        "quarantine_max_size": "Maximális méret MiB-ban (a nagyobb elemeket elveti):<br><small>A 0 <b>nem</b> jelent korlátlant.</small>",
+        "quarantine_notification_html": "Értesítő e-mail sablon:<br><small>Hagyja üresen az alapértelmezett sablon visszaállításához.</small>",
+        "quarantine_notification_sender": "Értesítő e-mail feladója",
+        "quarantine_notification_subject": "Értesítő e-mail tárgya",
+        "quarantine_redirect": "<b>Az összes értesítés átirányítása</b> erre a címzettnek:<br><small>Hagyja üresen a letiltáshoz. <b>Aláíratlan, nem ellenőrzött levél. Csak belső kézbesítésre alkalmas.</b></small>",
+        "quarantine_release_format": "A feloldott elemek formátuma",
+        "quarantine_release_format_att": "Csatolmányként",
+        "quarantine_release_format_raw": "Eredeti, módosítatlan formában",
+        "quarantine_retention_size": "Megőrzések postafiókonként:<br><small>A 0 <b>inaktívat</b> jelent.</small>",
+        "quicklink_text": "A gyorshivatkozások megjelenítése vagy elrejtése a bejelentkezési űrlap alatt",
+        "quota_notification_html": "Értesítő e-mail sablon:<br><small>Hagyja üresen az alapértelmezett sablon visszaállításához.</small>",
+        "quota_notification_sender": "Kvóta értesítő e-mail feladója",
+        "quota_notification_subject": "Kvóta értesítő e-mail tárgya",
+        "quota_notifications": "Kvóta értesítések",
+        "quota_notifications_info": "A kvóta értesítéseket a felhasználók egyszer kapják meg, amikor a 80%-os határt, majd a 95%-os határt átlépik.",
+        "quota_notifications_vars": "{{percent}} a felhasználó aktuális kvótáját jelenti<br>{{username}} a postafiók neve",
+        "queue_unban": "tiltás feloldása",
+        "r_active": "Aktív korlátozások",
+        "r_inactive": "Inaktív korlátozások",
+        "r_info": "A szürkével/letiltva jelölt elemek az aktív korlátozások listáján a mailcow számára nem érvényes korlátozások, és nem mozgathatók. Az ismeretlen korlátozások a megjelenési sorrendben lesznek beállítva. <br>Új elemeket adhat hozzá a <code>inc/vars.local.inc.php</code> fájlban, hogy váltani tudja őket.",
+        "rate_name": "Arányszám neve",
+        "recipients": "Címzettek",
+        "refresh": "Frissítés",
+        "regen_api_key": "API kulcs újragenerálása",
+        "regex_maps": "Regex térképek",
+        "relay_from": "\"Feladó:\" cím",
+        "relay_rcpt": "\"Címzett:\" cím",
+        "relay_run": "Teszt futtatása",
+        "relayhosts": "Feladófüggő szállítások",
+        "relayhosts_hint": "Határozzon meg feladófüggő szállításokat, hogy kiválaszthassa őket egy tartomány konfigurációs párbeszédpanelén.<br>\r\n  A szállítási szolgáltatás mindig \"smtp:\" és ezért megpróbálja a TLS-t, ha felajánlják. A becsomagolt TLS (SMTPS) nem támogatott. A felhasználók egyéni kimenő TLS-szabályzati beállításai figyelembe vételre kerülnek.<br>\r\n  Érintik a kiválasztott tartományokat, beleértve az alias tartományokat is.",
+        "remove": "Eltávolítás",
+        "remove_row": "Sor eltávolítása",
+        "reset_default": "Visszaállítás alapértelmezettre",
+        "reset_limit": "Hash eltávolítása",
+        "reset_password_vars": "<code>{{link}}</code> A generált jelszó-helyreállítási link<br><code>{{username}}</code> A jelszó-helyreállítást kérő felhasználó postafiók neve<br><code>{{username2}}</code> A helyreállítási postafiók neve<br><code>{{date}}</code> A jelszó-helyreállítási kérelem dátuma<br><code>{{token_lifetime}}</code> A token élettartama percekben<br><code>{{hostname}}</code> A mailcow hosztnév",
+        "restore_template": "Hagyja üresen az alapértelmezett sablon visszaállításához.",
+        "routing": "Útválasztás",
+        "rsetting_add_rule": "Szabály hozzáadása",
+        "rsetting_content": "Szabály tartalma",
+        "rsetting_desc": "Rövid leírás",
+        "rsetting_no_selection": "Kérjük, válasszon egy szabályt",
+        "rsetting_none": "Nincsenek elérhető szabályok",
+        "rsettings_insert_preset": "Példa előre beállított \"%s\" beillesztése",
+        "rsettings_preset_1": "Minden letiltása, kivéve a DKIM és az arányszám-korlátot a hitelesített felhasználók számára",
+        "rsettings_preset_2": "A Postmasterek spamet akarnak",
+        "rsettings_preset_3": "Csak bizonyos feladókat engedélyezzen egy postafiók számára (pl. csak belső postafiókként használva)",
+        "rsettings_preset_4": "Rspamd letiltása egy tartomány számára",
+        "rspamd_com_settings": "A beállítás neve automatikusan generálódik, kérjük, nézze meg a lenti példa-előrebeállításokat. További részletekért lásd a <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Rspamd dokumentációját</a>",
+        "rspamd_global_filters": "Globális szűrőtérképek",
+        "rspamd_global_filters_agree": "Óvatos leszek!",
+        "rspamd_global_filters_info": "A globális szűrőtérképek különböző típusú globális tiltó- és engedélyezési listákat tartalmaznak.",
+        "rspamd_global_filters_regex": "A nevük elmagyarázza a céljukat. Minden tartalomnak érvényes reguláris kifejezést kell tartalmaznia \"/pattern/options\" formátumban (pl. <code>/.+@domain\\.tld/i</code>).<br>\r\n  Bár alapvető ellenőrzések történnek minden regex soron, az Rspamd funkcionalitása megszakadhat, ha nem sikerül helyesen értelmeznie a szintaxist.<br>\r\n  Az Rspamd megpróbálja elolvasni a térkép tartalmát, amikor az megváltozik. Ha problémákat tapasztal, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">indítsa újra az Rspamd-et</a>, hogy kikényszerítse a térkép újratöltését.<br>A tiltólistára került elemek ki vannak zárva a karanténból.",
+        "rspamd_settings_map": "Rspamd beállítási térkép",
+        "sal_level": "Moo szint",
+        "service": "Szolgáltatás",
+        "service_id": "Szolgáltatás azonosító",
+        "task": "Feladat",
+        "transport_maps": "Szállítási térképek",
+        "transport_test_rcpt_info": "&#8226; Használja a null@hosted.mailcow.de címet a külföldi célra történő továbbítás teszteléséhez.",
+        "transports_hint": "&#8226; Egy szállítási térkép bejegyzés <b>felülírja</b> a feladófüggő szállítási térképet</b>.<br>\r\n&#8226; Az MX-alapú szállítások előnyben részesítettek.<br>\r\n&#8226; A felhasználónkénti kimenő TLS-szabályzati beállítások figyelmen kívül hagyódnak, és csak a TLS-szabályzati térkép bejegyzései kényszeríthetik ki őket.<br>\r\n&#8226; A definiált szállításokhoz a szállítási szolgáltatás mindig \"smtp:\" és ezért megpróbálja a TLS-t, ha felajánlják. A becsomagolt TLS (SMTPS) nem támogatott.<br>\r\n&#8226; A \"/localhost$/\"-nek megfelelő címek mindig \"local:\"-on keresztül lesznek szállítva, ezért a \"*\" cél nem vonatkozik ezekre a címekre.<br>\r\n&#8226; A hitelesítő adatok meghatározásához egy példa következő ugráshoz \"[host]:25\", a Postfix <b>mindig</b> lekérdezi a \"host\"-ot, mielőtt a \"[host]:25\"-re keresne. Ez a viselkedés lehetetlenné teszi a \"host\" és a \"[host]:25\" egyidejű használatát.",
+        "ui_footer": "Lábléc (HTML engedélyezett)",
+        "ui_header_announcement": "Közlemények",
+        "ui_header_announcement_active": "Közlemény beállítása aktívra",
+        "ui_header_announcement_content": "Szöveg (HTML engedélyezett)",
+        "ui_header_announcement_help": "A közlemény minden bejelentkezett felhasználó számára látható, valamint a felhasználói felület bejelentkezési képernyőjén.",
+        "ui_header_announcement_select": "Válassza ki a közlemény típusát",
+        "ui_header_announcement_type": "Típus",
+        "ui_header_announcement_type_danger": "Nagyon fontos",
+        "ui_header_announcement_type_info": "Információ",
+        "ui_header_announcement_type_warning": "Fontos",
+        "ui_texts": "Felhasználói felület címkéi és szövegei",
+        "unban_pending": "tiltás feloldása függőben",
+        "unchanged_if_empty": "Ha nem változik, hagyja üresen",
+        "user_link": "Felhasználói-link",
+        "user_quicklink": "Gyorshivatkozás elrejtése a Felhasználói bejelentkezési oldalra",
+        "validate_license_now": "GUID érvényesítése a licenszszerverrel szemben",
+        "yes": "&#10003;",
+        "success": "Siker"
     },
     "edit": {
         "active": "Aktív",
         "advanced_settings": "Haladó beállítások",
         "alias": "Alias szerkesztése",
-        "allow_from_smtp": "Kizárólag ezen IP-címek használhatnak <b>SMTP</b>-t",
-        "allow_from_smtp_info": "Leave empty to allow all senders.<br>IPv4/IPv6 addresses and networks.",
+        "allow_from_smtp": "Kizárólag ezen IP címek használhatnak <b>SMTP</b>-t",
+        "allow_from_smtp_info": "Hagyja üresen minden feladó engedélyezéséhez.<br>IPv4/IPv6 címek és hálózatok.",
         "allowed_protocols": "Engedélyezett protokollok",
         "app_name": "Applikáció neve",
         "app_passwd": "Applikáció jelszava",
@@ -146,7 +312,127 @@
         "description": "Leírás",
         "domain_quota": "Domain kvóta",
         "domains": "Domainek",
-        "edit_alias_domain": "Alias domain szerkesztése"
+        "edit_alias_domain": "Alias domain szerkesztése",
+        "acl": "ACL (Engedélyek)",
+        "admin": "Adminisztrátor szerkesztése",
+        "app_passwd_protocols": "Engedélyezett protokollok az alkalmazás jelszavához",
+        "automap": "Próbálja automatikusan feltérképezni a mappákat (\"Elküldött elemek\", \"Elküldött\" => \"Elküldött\" stb.)",
+        "bcc_dest_format": "A BCC-célpontnak egyetlen érvényes e-mail címnek kell lennie.<br>Ha több címre kell másolatot küldenie, hozzon létre egy aliast, és használja azt itt.",
+        "comment_info": "A privát megjegyzés nem látható a felhasználó számára, míg a nyilvános megjegyzés tooltip-ként jelenik meg, amikor a felhasználó áttekintésében a megjegyzésre mutat.",
+        "created_on": "Létrehozva",
+        "custom_attributes": "Egyéni attribútumok",
+        "delete1": "Törlés a forrásból, ha befejeződött",
+        "delete2": "Üzenetek törlése a célállomáson, amelyek nincsenek a forráson",
+        "delete2duplicates": "Duplikáltak törlése a célállomáson",
+        "delete_ays": "Erősítse meg a törlési folyamatot.",
+        "disable_login": "Bejelentkezés letiltása (a bejövő leveleket továbbra is elfogadja)",
+        "domain": "Domain szerkesztése",
+        "domain_admin": "Domain adminisztrátor szerkesztése",
+        "domain_footer": "Tartományszintű lábléc",
+        "domain_footer_html": "HTML lábléc",
+        "domain_footer_info": "A tartományszintű lábléceket a tartományon belüli címmel társított összes kimenő e-mailhez hozzáadják. <br> A következő változók használhatók a lábléchez:",
+        "domain_footer_info_vars": {
+            "auth_user": "{= auth_user =}   - Hitelesített felhasználónév az MTA által megadott",
+            "from_user": "{= from_user =}   - A boríték feladójának felhasználói része, pl. a \"moo@mailcow.tld\" esetén \"moo\"-t ad vissza",
+            "from_name": "{= from_name =}   - A boríték feladójának neve, pl. a \"Mailcow &lt;moo@mailcow.tld&gt;\" esetén \"Mailcow\"-t ad vissza",
+            "from_addr": "{= from_addr =}   - A boríték feladójának címe",
+            "from_domain": "{= from_domain =} - A boríték feladójának tartománya",
+            "custom": "{= foo =}         - Ha a postafiók rendelkezik a \"foo\" egyéni attribútummal, amelynek értéke \"bar\", akkor \"bar\"-t ad vissza"
+        },
+        "domain_footer_plain": "Egyszerű szöveges lábléc",
+        "domain_footer_skip_replies": "Lábléc figyelmen kívül hagyása válasz e-maileknél",
+        "dont_check_sender_acl": "Küldő ellenőrzés letiltása a(z) %s tartományhoz (+ alias tartományok)",
+        "encryption": "Titkosítás",
+        "exclude": "Objektumok kizárása (regex)",
+        "extended_sender_acl": "Külső feladói címek",
+        "extended_sender_acl_info": "Importálni kell egy DKIM tartomány kulcsot, ha elérhető.<br>\r\n  Ne felejtse el hozzáadni ezt a szervert a megfelelő SPF TXT rekordhoz.<br>\r\n  Amikor egy tartományt vagy alias tartományt ad hozzá ehhez a szerverhez, amely átfedésben van egy külső címmel, a külső cím eltávolításra kerül.<br>\r\n  Használja a @domain.tld címet, hogy engedélyezze a küldést *@domain.tld néven.",
+        "force_pw_update": "Jelszófrissítés kényszerítése a következő bejelentkezéskor",
+        "force_pw_update_info": "Ez a felhasználó csak a(z) %s címre tud bejelentkezni. Az alkalmazás jelszavak használhatóak maradnak.",
+        "footer_exclude": "Kizárás a láblécből",
+        "full_name": "Teljes név",
+        "gal": "Globális címlista",
+        "gal_info": "A GAL tartalmazza a tartomány összes objektumát, és egyetlen felhasználó sem szerkesztheti. A Szabad/Foglalt információ a SOGo-ban hiányzik, ha le van tiltva! <b>Indítsa újra a SOGo-t a változások alkalmazásához.</b>",
+        "generate": "generál",
+        "grant_types": "Engedélyezési típusok",
+        "hostname": "Hosztnév",
+        "inactive": "Inaktív",
+        "kind": "Típus",
+        "last_modified": "Utoljára módosítva",
+        "lookup_mx": "A cél egy reguláris kifejezés, amely illeszkedik az MX névre (<code>.*\\.google\\.com</code>, hogy a google.com-ra végződő MX-en keresztül továbbítsa az összes levelet)",
+        "mailbox": "Postafiók szerkesztése",
+        "mailbox_quota_def": "Alapértelmezett postafiók kvóta",
+        "mailbox_relayhost_info": "A postafiókra és csak a közvetlen aliasokra vonatkozik, felülírja a tartományi továbbító hostot.",
+        "mailbox_rename": "Postafiók átnevezése",
+        "mailbox_rename_agree": "Készítettem biztonsági másolatot.",
+        "mailbox_rename_warning": "FONTOS! Hozzon létre biztonsági másolatot a postafiók átnevezése előtt.",
+        "mailbox_rename_alias": "Alias automatikus létrehozása",
+        "mailbox_rename_title": "Új helyi postafiók neve",
+        "max_aliases": "Max. aliasok",
+        "max_mailboxes": "Max. lehetséges postafiókok",
+        "max_quota": "Max. kvóta postafiókonként (MiB)",
+        "maxage": "Üzenetek maximális életkora napokban, amelyek lekérdezésre kerülnek a távolról<br><small>(0 = figyelmen kívül hagyás)</small>",
+        "maxbytespersecond": "Max. bájt/másodperc <br><small>(0 = korlátlan)</small>",
+        "mbox_rl_info": "Ez a sebességkorlátozás a SASL bejelentkezési névre vonatkozik, és illeszkedik minden, a bejelentkezett felhasználó által használt \"from\" címre. Egy postafiók sebességkorlátozása felülírja a tartományszintű sebességkorlátozást.",
+        "mins_interval": "Időköz (perc)",
+        "multiple_bookings": "Több foglalás",
+        "none_inherit": "Nincs / Örökölt",
+        "nexthop": "Következő ugrás",
+        "password": "Jelszó",
+        "password_recovery_email": "Jelszó-helyreállítási e-mail",
+        "password_repeat": "Megerősítő jelszó (ismétlés)",
+        "previous": "Előző oldal",
+        "private_comment": "Privát megjegyzés",
+        "public_comment": "Nyilvános megjegyzés",
+        "pushover": "Pushover",
+        "pushover_evaluate_x_prio": "Magas prioritású levelek továbbítása [<code>X-Priority: 1</code>]",
+        "pushover_info": "A push értesítési beállítások az összes tiszta (nem-spam) levélre vonatkoznak, amelyeket a <b>%s</b> címre kézbesítettek, beleértve az aliasokat is (megosztott, nem megosztott, címkézett).",
+        "pushover_only_x_prio": "Csak a magas prioritású leveleket vegye figyelembe [<code>X-Priority: 1</code>]",
+        "pushover_sender_array": "Csak a következő feladói e-mail címeket vegye figyelembe <small>(vesszővel elválasztva)</small>",
+        "pushover_sender_regex": "Feladók egyeztetése a következő regex-szel",
+        "pushover_text": "Értesítési szöveg",
+        "pushover_title": "Értesítési cím",
+        "pushover_sound": "Hang",
+        "pushover_vars": "Ha nincs feladói szűrő meghatározva, minden e-mail figyelembe vételre kerül.<br>A Regex szűrők, valamint a pontos feladói ellenőrzések egyénileg definiálhatók, és sorban lesznek figyelembe véve. Nem függenek egymástól.<br>Használható változók a szöveghez és a címhez (kérjük, vegye figyelembe az adatvédelmi szabályzatokat)",
+        "pushover_verify": "Hitelesítő adatok ellenőrzése",
+        "quota_mb": "Kvóta (MiB)",
+        "quota_warning_bcc": "Kvóta figyelmeztetés BCC",
+        "quota_warning_bcc_info": "A figyelmeztetések külön másolatként lesznek elküldve a következő címzetteknek. A tárgyat a megfelelő felhasználónévvel egészítik ki zárójelben, például: <code>Quota warning (user@example.com)</code>.",
+        "ratelimit": "Arányszám-korlát",
+        "redirect_uri": "Átirányítási/Visszahívási URL",
+        "relay_all": "Az összes címzett továbbítása",
+        "relay_all_info": "↪ Ha úgy döntesz, hogy <b>nem</b> továbbítod az összes címzettet, akkor minden egyes címzett számára, akit továbbítani kell, létre kell hoznod egy (\"vak\") postafiókot.",
+        "relay_domain": "Továbbítsa ezt a tartományt",
+        "relay_transport_info": "<div class=\"badge fs-6 bg-info\">Információ</div> Definiálhatsz szállítási térképeket ehhez a tartományhoz egyedi célállomásra. Ha nincs beállítva, egy MX lekérdezés történik.",
+        "relay_unknown_only": "Csak a nem létező postafiókok továbbítása. A létező postafiókok helyben lesznek kézbesítve.",
+        "relayhost": "Feladófüggő szállítások",
+        "remove": "Eltávolítás",
+        "resource": "Erőforrás",
+        "save": "Módosítások mentése",
+        "scope": "Hatókör",
+        "sender_acl": "Engedélyezés küldésre mint",
+        "sender_acl_disabled": "<span class=\"badge fs-6 bg-danger\">A küldő ellenőrzése le van tiltva</span>",
+        "sender_acl_info": "Ha az A postafiók felhasználója küldhet a B postafiók felhasználójaként, a feladói cím nem jelenik meg automatikusan választható \"from\" mezőként a SOGo-ban.<br>\r\n  A B postafiók felhasználójának delegálást kell létrehoznia a SOGo-ban, hogy az A postafiók felhasználója kiválaszthassa a címét feladóként. A SOGo-ban egy postafiók delegálásához használja a menüt (három pont) a postafiók neve jobb oldalán a bal felső sarokban, a levélnézetben. Ez a viselkedés nem vonatkozik az alias címekre.",
+        "sieve_desc": "Rövid leírás",
+        "sieve_type": "Szűrő típusa",
+        "skipcrossduplicates": "Átugrani a duplikált üzeneteket a mappák között (aki előbb jön, előbb kapja)",
+        "sogo_access": "Közvetlen továbbítás a SOGo-ra",
+        "sogo_access_info": "A bejelentkezés után a felhasználó automatikusan átirányításra kerül a SOGo-ra.",
+        "sogo_visible": "Alias látható a SOGo-ban",
+        "sogo_visible_info": "Ez az opció csak azokra az objektumokra vonatkozik, amelyek megjeleníthetők a SOGo-ban (megosztott vagy nem megosztott alias címek, amelyek legalább egy helyi postafiókra mutatnak). Ha el van rejtve, egy alias nem jelenik meg választható feladóként a SOGo-ban.",
+        "spam_alias": "Időkorlátos alias címek létrehozása vagy módosítása",
+        "spam_filter": "Spam szűrő",
+        "spam_policy": "Elemek hozzáadása vagy eltávolítása a tiltó- vagy engedélyezési listán",
+        "spam_score": "Egyéni spam pontszám beállítása",
+        "subfolder2": "Szinkronizálás a célállomáson egy almappába<br><small>(üres = ne használjon almappát)</small>",
+        "syncjob": "Szinkronizálási feladat szerkesztése",
+        "target_address": "Célcím(ek) <small>(vesszővel elválasztva)</small>",
+        "target_domain": "Cél domain",
+        "timeout1": "Időtúllépés a távoli állomáshoz való csatlakozáskor",
+        "timeout2": "Időtúllépés a helyi állomáshoz való csatlakozáskor",
+        "title": "Objektum szerkesztése",
+        "unchanged_if_empty": "Ha nem változik, hagyja üresen",
+        "username": "Felhasználónév",
+        "validate_save": "Érvényesítés és mentés"
     },
     "footer": {
         "cancel": "Mégse",
@@ -159,7 +445,9 @@
         "restart_container": "Konténer újraindítása",
         "restart_container_info": "<b>Fontos:</b> A teljes újraindulás eltarthat egy ideig, kérjük várjon, amíg befejeződik!",
         "restart_now": "Újraindítás most",
-        "restarting_container": "Konténer újraindítása. Ez eltarthat egy darabig."
+        "restarting_container": "Konténer újraindítása. Ez eltarthat egy darabig.",
+        "hibp_check": "Ellenőrzés a haveibeenpwned.com-on",
+        "nothing_selected": "Nincs semmi kiválasztva"
     },
     "header": {
         "administration": "Beállítások és részletek",
@@ -170,7 +458,8 @@
         "quarantine": "Karantén",
         "restart_netfilter": "Netfilter újraindítása",
         "restart_sogo": "SOGo újraindítása",
-        "user_settings": "Felhasználó beállításai"
+        "user_settings": "Felhasználó beállításai",
+        "mailcow_system": "Rendszer"
     },
     "info": {
         "awaiting_tfa_confirmation": "TFA megerősítésre várakozás",
@@ -182,7 +471,23 @@
         "login": "Bejelentkezés",
         "mobileconfig_info": "A kért Apple kapcsolat profil letöltéséhez jelentkezzen be, mint postafiók-felhasználó.",
         "password": "Jelszó",
-        "username": "Felhasználónév"
+        "username": "Felhasználónév",
+        "back_to_mailcow": "Vissza a mailcow-hoz",
+        "fido2_webauthn": "FIDO2/WebAuthn bejelentkezés",
+        "forgot_password": "> Elfelejtett jelszó?",
+        "invalid_pass_reset_token": "A jelszó-helyreállítási token érvénytelen vagy lejárt.<br>Kérjen új jelszó-helyreállítási linket.",
+        "login_linkstext": "Nem a megfelelő bejelentkezés?",
+        "login_usertext": "Bejelentkezés felhasználóként",
+        "login_domainadmintext": "Bejelentkezés domain adminisztrátorként",
+        "login_admintext": "Bejelentkezés adminisztrátorként",
+        "login_user": "Felhasználói bejelentkezés",
+        "login_dadmin": "Domain-adminisztrátori bejelentkezés",
+        "login_admin": "Adminisztrátori bejelentkezés",
+        "new_password": "Új jelszó",
+        "new_password_confirm": "Új jelszó megerősítése",
+        "other_logins": "vagy bejelentkezés",
+        "reset_password": "Jelszó visszaállítása",
+        "request_reset_password": "Jelszó módosítás kérése"
     },
     "mailbox": {
         "action": "Művelet",
@@ -200,10 +505,10 @@
         "add_resource": "Erőforrás hozzáadása",
         "add_tls_policy_map": "TLS irányelv-térkép hozzáadása",
         "address_rewriting": "Címátírás",
-        "alias": "Alias",
+        "alias": "Álnév",
         "alias_domain_backupmx": "Alias domain inaktív a továbbító domain részére",
-        "aliases": "Alias-ok",
-        "allow_from_smtp": "Kizárólag ezek az IP-címek használhatják az <b>SMTP</b>-t",
+        "aliases": "Álnevek",
+        "allow_from_smtp": "Kizárólag ezek az IP címek használhatják az <b>SMTP</b>-t",
         "allow_from_smtp_info": "Hagyja üresen minden feladó engedélyezéséhez.<br>IPv4/IPv6 címek és hálózatok.",
         "allowed_protocols": "Engedélyezett protokollok",
         "backup_mx": "Továbbító domain",
@@ -221,7 +526,7 @@
         "domain_admins": "Domain adminisztrátorok",
         "domain_aliases": "Domain alias-ok",
         "domain_quota": "Kvóta",
-        "domains": "Domain-ek",
+        "domains": "Domainek",
         "edit": "Szerkesztés",
         "empty": "Nincs találat",
         "enable_x": "Engedélyezés",
@@ -277,7 +582,87 @@
         "toggle_all": "Összes átváltása",
         "username": "Felhasználónév",
         "waiting": "Várakozás",
-        "weekly": "Hetente"
+        "weekly": "Hetente",
+        "add_alias_expand": "Alias kiterjesztése alias tartományokra",
+        "alias_domain_alias_hint": "Az aliasok <b>nem</b> vonatkoznak automatikusan a domain aliasokra. Egy <code>my-alias@domain</code> alias cím <b>nem</b> fedezi a <code>my-alias@alias-domain</code> címet (ahol az \"alias-domain\" a \"domain\" képzeletbeli alias tartománya).<br>Kérjük, használjon sieve szűrőt a levél külső postafiókba történő átirányításához (lásd a \"Szűrők\" fület vagy a SOGo -> Továbbító). Használja az \"Alias kiterjesztése alias tartományokra\" opciót a hiányzó aliasok automatikus hozzáadásához.",
+        "all_domains": "Minden tartomány",
+        "bcc_info": "A BCC térképek arra szolgálnak, hogy csendesen továbbítsák az összes üzenet másolatát egy másik címre. A címzett térkép típust akkor használják, ha a helyi célpont egy levél címzettjeként működik. A feladói térképek ugyanazon elv szerint működnek.<br/>\r\n  A helyi célpontot nem értesítik a sikertelen kézbesítésről.",
+        "bcc_map_type": "BCC típus",
+        "bcc_maps": "BCC térképek",
+        "bcc_rcpt_map": "Címzett térkép",
+        "bcc_sender_map": "Feladó térkép",
+        "bcc_to_rcpt": "Váltás címzett térkép típusra",
+        "bcc_to_sender": "Váltás feladó térkép típusra",
+        "bcc_type": "BCC típus",
+        "booking_null": "Mindig szabadként mutat",
+        "booking_0_short": "Mindig szabad",
+        "booking_custom": "Kemény korlát a foglalások egyéni számára",
+        "booking_custom_short": "Kemény korlát",
+        "booking_ltnull": "Korlátlan, de foglaltnak mutatja magát, ha le van foglalva",
+        "booking_lt0_short": "Lágy korlát",
+        "catch_all": "Catch-All",
+        "created_on": "Létrehozva",
+        "dkim_domains_selector": "Válogató",
+        "dkim_key_length": "DKIM kulcs hossza (bit)",
+        "domain_templates": "Domain sablonok",
+        "domain_quota_total": "Teljes domain kvóta",
+        "gal": "Globális címlista",
+        "goto_ham": "Tanulás <b>ham</b>-ként",
+        "goto_spam": "Tanulás <b>spam</b>-ként",
+        "iam": "Azonosítási szolgáltató",
+        "last_modified": "Utoljára módosítva",
+        "last_pw_change": "Utolsó jelszócsere",
+        "mailbox_defaults": "Alapértelmezett beállítások",
+        "mailbox_defaults_info": "Alapértelmezett beállítások meghatározása az új postafiókokhoz.",
+        "mailbox_templates": "Postafiók sablonok",
+        "max_aliases": "Max. aliasok",
+        "max_mailboxes": "Max. lehetséges postafiókok",
+        "max_quota": "Max. kvóta postafiókonként",
+        "no": "&#10005;",
+        "open_logs": "Naplók megnyitása",
+        "q_add_header": "amikor a levélszemét mappába kerül",
+        "q_all": " amikor a levélszemét mappába kerül és elutasításkor",
+        "q_reject": "elutasításkor",
+        "quarantine_category": "Karantén értesítési kategória",
+        "recipient": "Címzett",
+        "recipient_map_info": "A címzett térképeket arra használják, hogy egy üzenet célcímét kicseréljék, mielőtt azt kézbesítenék.",
+        "recipient_map_new_info": "A címzett térkép célja érvényes e-mail címnek vagy tartománynévnek kell lennie.",
+        "recipient_map_old_info": "Egy címzett térkép eredeti céljának érvényes e-mail címnek vagy tartománynévnek kell lennie.",
+        "relay_all": "Az összes címzett továbbítása",
+        "relay_unknown": "Ismeretlen postafiókok továbbítása",
+        "sender": "Feladó",
+        "set_postfilter": "Megjelölés poszt-szűrőként",
+        "set_prefilter": "Megjelölés pre-szűrőként",
+        "sieve_info": "Több szűrőt is tárolhatsz felhasználónként, de egyszerre csak egy pre-szűrő és egy poszt-szűrő lehet aktív.<br>\r\nMinden szűrő a leírt sorrendben lesz feldolgozva. Sem a sikertelen szkript, sem a kiadott \"keep;\" parancs nem állítja le a további szkriptek feldolgozását. A globális sieve szkriptek változásai a Dovecot újraindítását váltják ki.<br><br>Globális sieve pre-szűrő &#8226; Pre-szűrő &#8226; Felhasználói szkriptek &#8226; Poszt-szűrő &#8226; Globális sieve poszt-szűrő",
+        "sieve_preset_1": "Levél eldobása valószínűleg veszélyes fájltípusokkal",
+        "sieve_preset_2": "Egy adott feladó e-mailjét mindig olvasottként jelölje meg",
+        "sieve_preset_3": "Csendesen elvetni, leállítani minden további sieve feldolgozást",
+        "sieve_preset_4": "Fájl az INBOX-ba, kihagyni a további feldolgozást a sieve szűrőkkel",
+        "sieve_preset_5": "Auto válaszadó (szabadság)",
+        "sieve_preset_6": "Levél elutasítása válasszal",
+        "sieve_preset_7": "Átirányítás és megtartás/eldobás",
+        "sieve_preset_8": "E-mail átirányítása egy adott feladótól, olvasottként jelölés és almappába rendezés",
+        "sieve_preset_header": "Kérjük, nézze meg az alábbi példa-előrebeállításokat. További részletekért lásd a <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Wikipedia</a>-t.",
+        "sogo_visible": "Alias látható a SOGo-ban",
+        "sogo_visible_n": "Alias elrejtése a SOGo-ban",
+        "sogo_visible_y": "Alias megjelenítése a SOGo-ban",
+        "syncjob_check_log": "Napló ellenőrzése",
+        "syncjob_last_run_result": "Utolsó futás eredménye",
+        "syncjob_EX_OK": "Siker",
+        "syncjob_EXIT_CONNECTION_FAILURE": "Kapcsolati probléma",
+        "syncjob_EXIT_TLS_FAILURE": "Probléma a titkosított kapcsolattal",
+        "syncjob_EXIT_AUTHENTICATION_FAILURE": "Hitelesítési probléma",
+        "syncjob_EXIT_OVERQUOTA": "A cél postafiók túllépte a kvótát",
+        "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nem lehet csatlakozni a távoli szerverhez",
+        "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Hibás felhasználónév vagy jelszó",
+        "templates": "Sablonok",
+        "template": "Sablon",
+        "tls_map_policy": "Irányelv",
+        "tls_policy_maps": "TLS irányelv térképek",
+        "tls_policy_maps_enforced_tls": "Ezek az irányelvek felülírják a kimenő TLS szállítási szabályokat függetlenül a felhasználó TLS irányelvi beállításaitól. Ha nincs alább egyetlen irányelv sem, ezek a felhasználók az alapértelmezett értékeket alkalmazzák, amelyeket a <code>smtp_tls_mandatory_protocols</code> és a <code>smtp_tls_mandatory_ciphers</code> határoz meg.",
+        "tls_policy_maps_info": "Ez az irányelv térkép felülírja a kimenő TLS szállítási szabályokat függetlenül a felhasználó TLS irányelvi beállításaitól.<br>\r\n  Kérjük, ellenőrizze a <a href=\"http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps\" target=\"_blank\">\"smtp_tls_policy_maps\" dokumentációját</a> további információkért.",
+        "tls_policy_maps_long": "Kimenő TLS irányelv térkép felülírások",
+        "yes": "&#10003;"
     },
     "oauth2": {
         "access_denied": "Kérjük jelentkezzen be postafiók felhasználójával az OAuth2 használatához.",
@@ -301,7 +686,7 @@
         "medium_danger": "Közepes veszély",
         "neutral_danger": "Semleges",
         "notified": "Értesítve",
-        "qinfo": "A karantén-rendszer elmenti a visszautasított leveleket az adatbázisba, miközben a feladónak nem lesz az a benyomása, hogy a levelet kézbesítették.\r\n  <br>\"Spamnek jelölés és törlés\" spam-ként jegyzi meg az üzenetet a Bayes-tétel segítségével, illetve fuzzy hash-eket számít, hogy hasonló üzenetek is spam-be kerüljenek a jövőben.\r\n  <br>Több üzenet spamként való megjegyzése időigényes lehet.<br>Feketelistára vett levelek nem kerülnek karanténba.",
+        "qinfo": "A karantén-rendszer elmenti a visszautasított leveleket az adatbázisba, miközben a feladónak nem lesz az a benyomása, hogy a levelet kézbesítették.\r\n  <br>\"Spamnek jelölés és törlés\" spam-ként jegyzi meg az üzenetet a Bayes-tétel segítségével, illetve fuzzy hash-eket számít, hogy hasonló üzenetek is spam-be kerüljenek a jövőben.\r\n  <br>Több üzenet spamként való megjegyzése időigényes lehet.<br>Tiltólistára vett levelek nem kerülnek karanténba.",
         "qitem": "Tétel",
         "quarantine": "Karantén",
         "quick_actions": "Műveletek",
@@ -324,10 +709,38 @@
         "table_size_show_n": "%s tétel mutatása",
         "text_from_html_content": "Tartalom (konvertált html)",
         "text_plain_content": "Tartalom (sima szöveg)",
-        "toggle_all": "Összes átkapcsolása"
+        "toggle_all": "Összes átkapcsolása",
+        "check_hash": "Fájl hash keresése @ VT",
+        "confirm": "Megerősítés",
+        "deliver_inbox": "Kézbesítés a beérkező mappába",
+        "disabled_by_config": "A jelenlegi rendszerkonfiguráció letiltja a karantén funkcionalitást. Kérjük, állítsa be a \"megőrzéseket postafiókonként\" és a \"maximális méretet\" a karantén elemek számára.",
+        "info": "Információ",
+        "junk_folder": "Levélszemét mappa",
+        "qhandler_success": "A kérés sikeresen elküldve a rendszernek. Most már bezárhatja az ablakot.",
+        "qid": "Rspamd QID",
+        "rejected": "Elutasítva",
+        "release_body": "A levelét eml fájlként csatoltuk ehhez az üzenethez.",
+        "rewrite_subject": "Tárgy átírása",
+        "settings_info": "A karanténba helyezhető elemek maximális száma: %s<br>Maximális e-mail méret: %s MiB",
+        "spam": "Spam",
+        "quick_info_link": "Információs link megnyitása",
+        "type": "Típus"
     },
     "queue": {
-        "queue_manager": "Queue Manager"
+        "queue_manager": "Queue Manager",
+        "delete": "Összes törlése",
+        "flush": "Üzenetsor ürítése",
+        "info": "A levelezési üzenetsor tartalmazza az összes kézbesítésre váró e-mailt. Ha egy e-mail hosszú ideig ragad az üzenetsorban, a rendszer automatikusan törli.<br>A megfelelő levél hibaüzenete tájékoztatást ad arról, miért nem lehetett a levelet kézbesíteni.",
+        "legend": "A levelezési üzenetsor műveleti funkciói:",
+        "ays": "Kérjük, erősítse meg, hogy törölni szeretné az összes elemet az aktuális üzenetsorból.",
+        "deliver_mail": "Kézbesítés",
+        "deliver_mail_legend": "Megpróbálja újra kézbesíteni a kiválasztott leveleket.",
+        "hold_mail": "Visszatartás",
+        "hold_mail_legend": "Visszatartja a kiválasztott leveleket. (Megakadályozza a további kézbesítési kísérleteket)",
+        "show_message": "Üzenet megjelenítése",
+        "unban": "üzenetsor tiltás feloldása",
+        "unhold_mail": "Visszatartás feloldása",
+        "unhold_mail_legend": "Kiadja a kiválasztott leveleket a kézbesítéshez. (Előzetes visszatartás szükséges)"
     },
     "start": {
         "help": "Súgó panel megjelenítése/elrejtése",
@@ -380,7 +793,49 @@
         "resource_modified": "Postafiók %s módosításai mentve",
         "resource_removed": "Erőforrás %s eltávolítva",
         "saved_settings": "Beállítások mentve",
-        "upload_success": "File sikeresen feltöltve"
+        "upload_success": "File sikeresen feltöltve",
+        "acl_saved": "Az ACL a(z) %s objektumhoz mentve",
+        "bcc_deleted": "BCC térkép bejegyzések törölve: %s",
+        "bcc_edited": "BCC térkép bejegyzés %s szerkesztve",
+        "bcc_saved": "BCC térkép bejegyzés mentve",
+        "cors_headers_edited": "A CORS beállítások mentve",
+        "custom_login_modified": "A bejelentkezési testreszabás sikeresen mentve",
+        "domain_add_dkim_available": "Egy DKIM kulcs már létezett",
+        "dkim_duplicated": "A DKIM kulcs a(z) %s tartományhoz sikeresen átmásolva a(z) %s tartományba",
+        "domain_footer_modified": "A(z) %s tartományi lábléc módosításai mentve",
+        "f2b_banlist_refreshed": "A tiltólista azonosítója sikeresen frissítve.",
+        "f2b_modified": "A Fail2ban paraméterek módosításai mentve",
+        "forwarding_host_added": "A továbbító állomás %s hozzáadva",
+        "forwarding_host_removed": "A továbbító állomás %s eltávolítva",
+        "iam_test_connection": "Kapcsolat sikeres",
+        "ip_check_opt_in_modified": "Az IP ellenőrzés sikeresen mentve",
+        "nginx_reloaded": "Az Nginx újra lett töltve",
+        "password_policy_saved": "A jelszó házirend sikeresen mentve",
+        "password_changed_success": "A jelszó sikeresen megváltoztatva",
+        "pushover_settings_edited": "A Pushover beállítások sikeresen elmentve, kérjük, ellenőrizze a hitelesítő adatokat.",
+        "queue_command_success": "A sor parancs sikeresen befejeződött",
+        "recipient_map_entry_deleted": "A címzett térkép ID %s törölve",
+        "recipient_map_entry_saved": "A címzett térkép bejegyzés \"%s\" mentve",
+        "recovery_email_sent": "Helyreállítási e-mail elküldve a(z) %s címre",
+        "relayhost_added": "A térkép bejegyzés %s hozzáadva",
+        "relayhost_removed": "A térkép bejegyzés %s eltávolítva",
+        "reset_main_logo": "Visszaállítás alapértelmezett logóra",
+        "rl_saved": "Arányszám-korlát a(z) %s objektumhoz mentve",
+        "rspamd_ui_pw_set": "Rspamd UI jelszó sikeresen beállítva",
+        "settings_map_added": "Hozzáadott beállítási térkép bejegyzés",
+        "settings_map_removed": "Eltávolított beállítási térkép ID %s",
+        "sogo_profile_reset": "A SOGo profil a(z) %s felhasználóhoz visszaállítva",
+        "template_added": "Hozzáadott sablon %s",
+        "template_modified": "A(z) %s sablon módosításai mentve",
+        "template_removed": "A sablon ID %s törölve",
+        "tls_policy_map_entry_deleted": "TLS irányelv térkép ID %s törölve",
+        "tls_policy_map_entry_saved": "TLS irányelv térkép bejegyzés \"%s\" mentve",
+        "ui_texts": "A felhasználói felület szövegeinek módosításai mentve",
+        "verified_fido2_login": "FIDO2 bejelentkezés ellenőrizve",
+        "verified_totp_login": "TOTP bejelentkezés ellenőrizve",
+        "verified_webauthn_login": "WebAuthn bejelentkezés ellenőrizve",
+        "verified_yotp_login": "Yubico OTP bejelentkezés ellenőrizve",
+        "mailbox_renamed": "A postafiók átnevezve %s-ről %s-re"
     },
     "user": {
         "action": "Művelet",
@@ -449,15 +904,14 @@
         "spam_score_reset": "Szerver szerinti alapértelmezésre visszaállítás",
         "spamfilter": "Spam szűrő",
         "spamfilter_behavior": "Osztályozás",
-        "spamfilter_bl": "Feketelista",
-        "spamfilter_bl_desc": "A feketelistán szereplő email címek mindig spam-ként lesznek kezelve és vissza lesznek utasítva.  Joker karakter használható. A szűrő csak közvetlen aliasokra vonatkozik (alias egyetlen cél-postafiókkal), magára a postafiókra, illetve mindent elkapó aliasokra nem.",
+        "spamfilter_bl": "Tiltólista",
+        "spamfilter_bl_desc": "A tiltólistán szereplő email címek mindig spam-ként lesznek kezelve és vissza lesznek utasítva.  Joker karakter használható. A szűrő csak közvetlen aliasokra vonatkozik (alias egyetlen cél-postafiókkal), magára a postafiókra, illetve mindent elkapó aliasokra nem.",
         "spamfilter_default_score": "Alapértelmezett értékek",
         "spamfilter_green": "Zöld: ez az üzenet nem spam",
         "spamfilter_hint": "Az első érték az alacsony spam pontszámot, a második a magas spam pontszámot jelöli.",
         "spamfilter_red": "Vörös: Ez az üzenet spam, a szerver el fogja vetni.",
         "spamfilter_table_action": "Művelet",
         "spamfilter_table_add": "Tétel hozzáadása",
-        "spamfilter_table_empty": "Nincs megjeleníthető adat",
         "spamfilter_table_remove": "eltávolítás",
         "spamfilter_table_rule": "Szabály",
         "spamfilter_wl": "Engedélyezőlista",
@@ -482,15 +936,88 @@
         "waiting": "Várakozás",
         "week": "hét",
         "weekly": "heti",
-        "weeks": "hét"
+        "weeks": "hét",
+        "aliases_also_send_as": "Küldhet még mint felhasználó",
+        "aliases_send_as_all": "Ne ellenőrizze a küldő hozzáférését a következő tartomány(ok) és annak alias tartományai számára",
+        "app_hint": "Az alkalmazás jelszavak alternatív jelszavak az IMAP, SMTP, CalDAV, CardDAV és EAS bejelentkezéshez. A felhasználónév változatlan marad. A SOGo webmail nem érhető el az alkalmazás jelszavakon keresztül.",
+        "allowed_protocols": "Engedélyezett protokollok",
+        "apple_connection_profile_complete": "Ez a kapcsolati profil tartalmazza az IMAP és SMTP paramétereket, valamint a CalDAV (naptárak) és CardDAV (névjegyek) útvonalakat egy Apple eszközhöz.",
+        "apple_connection_profile_mailonly": "Ez a kapcsolati profil csak IMAP és SMTP konfigurációs paramétereket tartalmaz egy Apple eszközhöz.",
+        "apple_connection_profile_with_app_password": "Új alkalmazás jelszó generálódik és hozzáadódik a profilhoz, így nem kell jelszót megadni az eszköz beállításakor. Kérjük, ne ossza meg a fájlt, mivel teljes hozzáférést biztosít a postafiókjához.",
+        "attribute": "Attribútum",
+        "authentication": "Hitelesítés",
+        "change_password_hint_app_passwords": "Fiókodnak %d alkalmazás jelszava van, amelyek nem lesznek megváltoztatva. Ezek kezeléséhez menj az Alkalmazás jelszavak fülre.",
+        "clear_recent_successful_connections": "Sikeres kapcsolatok törlése",
+        "created_on": "Létrehozva",
+        "direct_aliases_desc": "A közvetlen alias címeket érintik a spam szűrő és a TLS irányelv beállításai.",
+        "direct_protocol_access": "Ennek a postafiók felhasználónak <b>közvetlen, külső hozzáférése</b> van a következő protokollokhoz és alkalmazásokhoz. Ezt a beállítást az adminisztrátor vezérli. Az alkalmazás jelszavak létrehozhatók, hogy hozzáférést biztosítsanak az egyedi protokollokhoz és alkalmazásokhoz.<br>A \"Webmail\" gomb egységes bejelentkezést biztosít a SOGo-ra, és mindig elérhető.",
+        "eas_reset_help": "Sok esetben a eszköz gyorsítótárának visszaállítása segít egy sérült ActiveSync profil helyreállításában.<br><b>Figyelem:</b> Minden elem újra letöltődik!",
+        "empty": "Nincs eredmény",
+        "from": "feladó",
+        "is_catch_all": "Catch-all a tartomány(ok)hoz",
+        "last_pw_change": "Utolsó jelszócsere",
+        "last_ui_login": "Utolsó UI bejelentkezés",
+        "login_history": "Bejelentkezési előzmények",
+        "mailbox": "Postafiók",
+        "mailbox_general": "Általános",
+        "mailbox_settings": "Beállítások",
+        "month": "hónap",
+        "months": "hónap",
+        "open_logs": "Naplók megnyitása",
+        "open_webmail_sso": "Webmail",
+        "overview": "Áttekintés",
+        "password_reset_info": "Ha nincs megadva e-mail a jelszó-helyreállításhoz, ez a funkció nem használható.",
+        "protocols": "Protokollok",
+        "pushover_evaluate_x_prio": "Magas prioritású levelek továbbítása [<code>X-Priority: 1</code>]",
+        "pushover_info": "A push értesítési beállítások az összes tiszta (nem-spam) levélre vonatkoznak, amelyeket a <b>%s</b> címre kézbesítettek, beleértve az aliasokat is (megosztott, nem megosztott, címkézett).",
+        "pushover_only_x_prio": "Csak a magas prioritású leveleket vegye figyelembe [<code>X-Priority: 1</code>]",
+        "pushover_sender_array": "A következő feladói e-mail címek figyelembe vétele <small>(vesszővel elválasztva)</small>",
+        "pushover_sender_regex": "Feladók egyeztetése a következő regex-szel",
+        "pushover_text": "Értesítési szöveg",
+        "pushover_title": "Értesítési cím",
+        "pushover_sound": "Hang",
+        "pushover_vars": "Ha nincs feladói szűrő meghatározva, minden e-mail figyelembe vételre kerül.<br>A Regex szűrők, valamint a pontos feladói ellenőrzések egyénileg definiálhatók, és sorban lesznek figyelembe véve. Nem függenek egymástól.<br>Használható változók a szöveghez és a címhez (kérjük, vegye figyelembe az adatvédelmi szabályzatokat)",
+        "pushover_verify": "Hitelesítő adatok ellenőrzése",
+        "pw_recovery_email": "Jelszó-helyreállítási e-mail",
+        "q_add_header": "Levélszemét mappa",
+        "q_all": "Összes kategória",
+        "q_reject": "Elutasítva",
+        "quarantine_category": "Karantén értesítési kategória",
+        "quarantine_category_info": "Az \"Elutasítva\" értesítési kategória magában foglalja azokat a leveleket, amelyeket elutasítottak, míg a \"Levélszemét mappa\" értesíti a felhasználót a levélszemét mappába helyezett levelekről.",
+        "recent_successful_connections": "Látott sikeres kapcsolatok",
+        "shared_aliases_desc": "A megosztott aliasokat nem érintik a felhasználóspecifikus beállítások, mint a spam szűrő vagy a titkosítási szabályzat. A megfelelő spam szűrőket csak egy adminisztrátor hozhatja létre tartományszintű szabályzatként.",
+        "sogo_profile_reset": "SOGo profil visszaállítása",
+        "sogo_profile_reset_help": "Ez tönkreteszi a felhasználó SOGo profilját, és <b>visszavonhatatlanul törli az összes névjegy- és naptáradatot</b>.",
+        "sogo_profile_reset_now": "Profil visszaállítása most",
+        "spamfilter_table_domain_policy": "n/a (tartományi szabályzat)",
+        "syncjob_check_log": "Napló ellenőrzése",
+        "syncjob_last_run_result": "Utolsó futás eredménye",
+        "syncjob_EX_OK": "Siker",
+        "syncjob_EXIT_CONNECTION_FAILURE": "Kapcsolati probléma",
+        "syncjob_EXIT_TLS_FAILURE": "Probléma a titkosított kapcsolattal",
+        "syncjob_EXIT_AUTHENTICATION_FAILURE": "Hitelesítési probléma",
+        "syncjob_EXIT_OVERQUOTA": "A cél postafiók túllépte a kvótát",
+        "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nem lehet csatlakozni a távoli szerverhez",
+        "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Hibás felhasználónév vagy jelszó",
+        "tfa_info": "A kétlépcsős hitelesítés segít megvédeni a fiókodat. Ha engedélyezed, alkalmazás jelszavakra lesz szükséged, hogy bejelentkezz olyan alkalmazásokba vagy szolgáltatásokba, amelyek nem támogatják a kétlépcsős hitelesítést (pl. levelező kliensek).",
+        "tls_policy_warning": "<strong>Figyelem:</strong> Ha titkosított levélátvitelt kényszerítesz ki, elveszíthetsz e-maileket.<br>Azok az üzenetek, amelyek nem felelnek meg a szabályzatnak, kemény hibával visszapattannak a levelezőrendszerből.<br>Ez az opció a fő e-mail címedre (bejelentkezési név), az alias tartományokból származó összes címre, valamint az alias címekre vonatkozik, amelyeknek <b>csak ez az egy postafiók</b> a célja.",
+        "value": "Érték",
+        "with_app_password": "alkalmazás jelszóval",
+        "year": "év",
+        "years": "év"
     },
     "warning": {
         "cannot_delete_self": "Bejelentkezett felhasználó nem törölhető.",
-        "ip_invalid": "Érvénytelen IP-cím átugorva: %s",
+        "ip_invalid": "Érvénytelen IP cím átugorva: %s",
         "no_active_admin": "Utolsó aktív admin felhasználó nem deaktiválható.",
         "quota_exceeded_scope": "Domain kvóta átlépve: csak korlátok nélküli postafiókok hozhatók létre ebben a domain-ben.",
-        "session_token": "Űrlap-token érvénytelen: Tokenek nem egyeznek",
-        "session_ua": "Űrlap-token érvénytelen: User-Agent hitelesítési probléma"
+        "session_token": "Űrlaptoken érvénytelen: Tokenek nem egyeznek",
+        "session_ua": "Űrlaptoken érvénytelen: User-Agent hitelesítési probléma",
+        "domain_added_sogo_failed": "A tartomány hozzáadva, de a SOGo újraindítása sikertelen, kérjük, ellenőrizze a szerver naplókat.",
+        "dovecot_restart_failed": "A Dovecot újraindítása sikertelen, kérjük, ellenőrizze a naplókat",
+        "fuzzy_learn_error": "Fuzzy hash tanulási hiba: %s",
+        "hash_not_found": "A hash nem található vagy már törölve lett",
+        "is_not_primary_alias": "Nem elsődleges alias %s kihagyva"
     },
     "acl": {
         "delimiter_action": "Elhatárolás",
@@ -516,15 +1043,24 @@
         "smtp_ip_access": "Az SMTP engedélyezett állomásainak módosítása",
         "sogo_profile_reset": "SOGo profil visszaállítása",
         "spam_alias": "Ideiglenes álnevek",
-        "spam_policy": "Fekete/Fehér lista",
+        "spam_policy": "Tiltó/engedélyezési lista",
         "spam_score": "Spam pontszám",
         "syncjobs": "Szinkronizálási feladatok",
         "tls_policy": "TLS szabályzat",
         "unlimited_quota": "Korlátlan kvóta a postafiókok számára",
-        "sogo_access": "A SOGo-hozzáférés kezelésének lehetővé tétele"
+        "sogo_access": "A SOGo-hozzáférés kezelésének lehetővé tétele",
+        "pw_reset": "Lehetővé teszi a mailcow felhasználói jelszavak visszaállítását"
     },
     "diagnostics": {
-        "dns_records": "DNS bejegyzések"
+        "dns_records": "DNS bejegyzések",
+        "cname_from_a": "Az A/AAAA rekordból származó érték. Ez addig támogatott, amíg a rekord a megfelelő erőforrásra mutat.",
+        "dns_records_24hours": "Kérjük, vegye figyelembe, hogy a DNS-ben végrehajtott változtatások akár 24 órát is igénybe vehetnek, amíg a jelenlegi állapotuk helyesen megjelenik ezen az oldalon. Ez a célja, hogy könnyen láthassa, hogyan kell konfigurálnia a DNS rekordokat, és ellenőrizze, hogy az összes rekordja helyesen van-e tárolva a DNS-ben.",
+        "dns_records_data": "Helyes adatok",
+        "dns_records_docs": "Kérjük, konzultáljon a <a target=\"_blank\" href=\"https://docs.mailcow.email/getstarted/prerequisite-dns\">dokumentációval</a> is.",
+        "dns_records_name": "Név",
+        "dns_records_status": "Jelenlegi állapot",
+        "dns_records_type": "Típus",
+        "optional": "Ez a rekord opcionális."
     },
     "add": {
         "username": "Felhasználónév",
@@ -588,6 +1124,22 @@
         "alias_domain": "Alias domain",
         "alias_domain_info": "<small>Csak érvényes tartománynevek (vesszővel elválasztva).</small>",
         "app_name": "Alkalmazás neve",
-        "app_passwd_protocols": "Engedélyezett protokollok az alkalmazás jelszavához"
+        "app_passwd_protocols": "Engedélyezett protokollok az alkalmazás jelszavához",
+        "automap": "Próbálja automatikusan feltérképezni a mappákat (\"Elküldött elemek\", \"Elküldött\" => \"Elküldött\" stb.)",
+        "multiple_bookings": "Több foglalás",
+        "quota_mb": "Kvóta (MiB)",
+        "relay_all": "Az összes címzett továbbítása",
+        "relay_all_info": "↪ Ha úgy döntesz, hogy <b>nem</b> továbbítod az összes címzettet, akkor minden egyes címzett számára, akit továbbítani kell, létre kell hoznod egy (\"vak\") postafiókot.",
+        "relay_domain": "Továbbítsa ezt a tartományt",
+        "relay_transport_info": "<div class=\"badge fs-6 bg-info\">Információ</div> Definiálhatsz szállítási térképeket ehhez a tartományhoz egyedi célállomásra. Ha nincs beállítva, egy MX lekérdezés történik.",
+        "relay_unknown_only": "Csak a nem létező postafiókok továbbítása. A létező postafiókok helyben lesznek kézbesítve.",
+        "relayhost_wrapped_tls_info": "Kérjük, <b>ne</b> használjon TLS-be csomagolt portokat (többnyire a 465-ös porton használatosak).<br>\r\nHasználjon bármilyen nem csomagolt portot és adjon ki STARTTLS-t. A TLS kikényszerítésére egy TLS irányelv hozható létre a \"TLS irányelv térképek\" alatt.",
+        "select": "Kérjük, válasszon...",
+        "select_domain": "Kérjük, először válasszon egy domaint",
+        "sieve_desc": "Rövid leírás",
+        "sieve_type": "Szűrő típusa",
+        "skipcrossduplicates": "Duplikált üzenetek átugrása mappák között (érkezési sorrendben)",
+        "subscribeall": "Feliratkozás minden mappára",
+        "syncjob": "Szinkronizálási feladat hozzáadása"
     }
 }

+ 19 - 3
data/web/lang/lang.si-si.json

@@ -550,7 +550,11 @@
         "recovery_email_failed": "E-poštnega sporočila za obnovitev ni bilo mogoče poslati. Obrnite se na skrbnika.",
         "required_data_missing": "Manjkajo zahtevani podatki %s",
         "reset_token_limit_exceeded": "Omejitev žetonov za ponastavitev je bila presežena. Poskusite znova pozneje.",
-        "to_invalid": "Polje za prejemnika ne sme biti prazno"
+        "to_invalid": "Polje za prejemnika ne sme biti prazno",
+        "max_age_invalid": "Najvišja starost %s je neveljavna",
+        "mode_invalid": "Način %s ni veljaven",
+        "mx_invalid": "Zapis MX %s je neveljaven",
+        "version_invalid": "Različica %s je neveljavna"
     },
     "debug": {
         "containers_info": "Informacije o vsebniku (containerju)",
@@ -761,7 +765,18 @@
         "mailbox_rename": "Preimenuj poštni predal",
         "mailbox_rename_agree": "Ustvaril/a sem varnostno kopijo.",
         "mailbox_rename_warning": "POMEMBNO! Pred preimenovanjem nabiralnika ustvarite varnostno kopijo.",
-        "sieve_desc": "Kratek opis"
+        "sieve_desc": "Kratek opis",
+        "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, ki vsiljuje dostavo e-pošte med poštnimi strežniki z uporabo TLS z veljavnimi potrdili. <br>Uporablja se, kadar <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a> ni mogoč zaradi manjkajočega ali nepodprtega DNSSEC.<br><b>Opomba</b>: Če prejemna domena podpira DANE z DNSSEC, je DANE <b>vedno</b> prednost – MTA-STS deluje le kot rezervna možnost.",
+        "mta_sts_version": "Različica",
+        "mta_sts_version_info": "Določa različico standarda MTA-STS – trenutno je veljavna samo različica <code>STSv1</code>.",
+        "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_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)."
     },
     "footer": {
         "restart_container_info": "<b>Pomembno:</b> Ugoden ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
@@ -799,7 +814,8 @@
         "other_logins": "ali se prijavite s/z",
         "reset_password": "Ponastavi geslo",
         "request_reset_password": "Zahteva za spremembo gesla",
-        "username": "Uporabniško ime"
+        "username": "Uporabniško ime",
+        "email": "E-poštni naslov"
     },
     "mailbox": {
         "last_mail_login": "Zadnja prijava v e-pošto",

+ 12 - 0
data/web/templates/base.twig

@@ -166,6 +166,7 @@
   var lang_danger = {{ lang_danger|raw }};
   var docker_timeout = {{ docker_timeout|raw }} * 1000;
   var mailcow_cc_role = '{{ mailcow_cc_role }}';
+  {% if mailcow_cc_username %}
   var mailcow_info = {
     version_tag: '{{ mailcow_info.version_tag }}',
     last_version_tag: '{{ mailcow_info.last_version_tag }}',
@@ -175,6 +176,17 @@
     project_repo: '{{ mailcow_info.git_repo }}',
     branch: '{{ mailcow_info.mailcow_branch }}'
   };
+  {% else %}
+  var mailcow_info = {
+    version_tag: '',
+    last_version_tag: '',
+    updatedAt: '',
+    project_url: '',
+    project_owner: '',
+    project_repo: '',
+    branch: ''
+  };
+  {% endif %}
 
 $(window).scroll(function() {
   sessionStorage.scrollTop = $(this).scrollTop();

+ 6 - 1
data/web/templates/edit/alias.twig

@@ -6,6 +6,7 @@
 <br>
 <form class="form-horizontal" data-id="editalias" role="form" method="post">
   <input type="hidden" value="0" name="active">
+  <input type="hidden" value="0" name="internal">
   {% if not skip_sogo %}
   <input type="hidden" value="0" name="sogo_visible">
   {% endif %}
@@ -33,8 +34,12 @@
       <div class="form-check">
         <label><input type="checkbox" class="form-check-input" value="1" name="sogo_visible"{% if result.sogo_visible == '1' %} checked{% endif %}> {{ lang.edit.sogo_visible }}</label>
       </div>
-      <p class="text-muted">{{ lang.edit.sogo_visible_info }}</p>
+      <small class="text-muted d-block mb-2">{{ lang.edit.sogo_visible_info }}</small>
       {% endif %}
+      <div class="form-check">
+        <label><input type="checkbox" class="form-check-input" value="1" name="internal"{% if result.internal == '1' %} checked{% endif %}> {{ lang.edit.internal }}</label>
+      </div>
+      <small class="text-muted d-block">{{ lang.edit.internal_info }}</small>
     </div>
   </div>
   <hr>

+ 7 - 2
data/web/templates/modals/mailbox.twig

@@ -777,6 +777,7 @@
       <div class="modal-body">
         <form class="form-horizontal" data-cached-form="true" role="form" data-id="add_alias">
           <input type="hidden" value="0" name="active">
+          <input type="hidden" value="0" name="internal">
           <div class="row mb-2">
             <label class="control-label col-sm-2 text-sm-end" for="address">{{ lang.add.alias_address }}</label>
             <div class="col-sm-10">
@@ -803,11 +804,15 @@
               <div class="form-check">
                 <label><input type="checkbox" class="form-check-input" value="1" name="sogo_visible" checked> {{ lang.edit.sogo_visible }}</label>
               </div>
-              <p class="text-muted">{{ lang.edit.sogo_visible_info }}</p>
+              <small class="text-muted d-block mb-2">{{ lang.edit.sogo_visible_info }}</small>
               {% endif %}
+              <div class="form-check">
+                <label><input type="checkbox" class="form-check-input" value="1" name="internal"> {{ lang.add.internal }}</label>
+              </div>
+              <small class="text-muted d-block">{{ lang.edit.internal_info }}</small>
             </div>
           </div>
-          <div class="row mb-2">
+          <div class="row mb-4">
             <div class="offset-sm-2 col-sm-10">
               <div class="form-check">
                 <label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.add.active }}</label>

+ 1 - 1
data/web/templates/user_index.twig

@@ -48,7 +48,7 @@
             <label class="visually-hidden" for="login_user">{{ lang.login.username }}</label>
             <div class="input-group">
               <div class="input-group-text"><i class="bi bi-person-fill"></i></div>
-              <input name="login_user" autocorrect="off" autocapitalize="none" type="{% if is_mobileconfig %}email{% else %}text{% endif %}" id="login_user" class="form-control" placeholder="{{ lang.login.username }}" required="" autofocus="" autocomplete="username">
+              <input name="login_user" autocorrect="off" autocapitalize="none" type="{% if is_mobileconfig %}email{% else %}text{% endif %}" id="login_user" class="form-control" placeholder="{{ lang.login.email }}" required="" autofocus="" autocomplete="username">
             </div>
           </div>
           <div class="d-flex mt-3">

+ 8 - 6
docker-compose.yml

@@ -65,7 +65,7 @@ services:
             - redis
 
     clamd-mailcow:
-      image: ghcr.io/mailcow/clamd:1.70
+      image: ghcr.io/mailcow/clamd:1.71
       restart: always
       depends_on:
         unbound-mailcow:
@@ -117,7 +117,7 @@ services:
             - rspamd
 
     php-fpm-mailcow:
-      image: ghcr.io/mailcow/phpfpm:nightly-29072025
+      image: ghcr.io/mailcow/phpfpm:nightly-11092025
       command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
       depends_on:
         - redis-mailcow
@@ -251,7 +251,7 @@ services:
             - sogo
 
     dovecot-mailcow:
-      image: ghcr.io/mailcow/dovecot:nightly-28082025
+      image: ghcr.io/mailcow/dovecot:nightly-11092025
       depends_on:
         - mysql-mailcow
         - netfilter-mailcow
@@ -418,7 +418,7 @@ services:
         - php-fpm-mailcow
         - sogo-mailcow
         - rspamd-mailcow
-      image: ghcr.io/mailcow/nginx:nightly-05082025
+      image: ghcr.io/mailcow/nginx:nightly-11092025
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
       environment:
@@ -465,7 +465,7 @@ services:
           condition: service_started
         unbound-mailcow:
           condition: service_healthy
-      image: ghcr.io/mailcow/acme:nightly-28082025
+      image: ghcr.io/mailcow/acme:nightly-11092025
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
       environment:
@@ -522,7 +522,7 @@ services:
         - /lib/modules:/lib/modules:ro
 
     watchdog-mailcow:
-      image: ghcr.io/mailcow/watchdog:nightly-29072025
+      image: ghcr.io/mailcow/watchdog:nightly-11092025
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
       tmpfs:
@@ -578,6 +578,7 @@ services:
         - MYSQL_REPLICATION_THRESHOLD=${MYSQL_REPLICATION_THRESHOLD:-1}
         - SOGO_THRESHOLD=${SOGO_THRESHOLD:-3}
         - POSTFIX_THRESHOLD=${POSTFIX_THRESHOLD:-8}
+        - POSTFIX_TLSPOL_THRESHOLD=${POSTFIX_TLSPOL_THRESHOLD:-8}
         - CLAMD_THRESHOLD=${CLAMD_THRESHOLD:-15}
         - DOVECOT_THRESHOLD=${DOVECOT_THRESHOLD:-12}
         - DOVECOT_REPL_THRESHOLD=${DOVECOT_REPL_THRESHOLD:-20}
@@ -589,6 +590,7 @@ services:
         - OLEFY_THRESHOLD=${OLEFY_THRESHOLD:-5}
         - MAILQ_THRESHOLD=${MAILQ_THRESHOLD:-20}
         - MAILQ_CRIT=${MAILQ_CRIT:-30}
+        - DEV_MODE=${DEV_MODE:-n}
       networks:
         mailcow-network:
           aliases:

+ 21 - 0
generate_config.sh

@@ -1,5 +1,26 @@
 #!/usr/bin/env bash
 
+# Ensure the script is run from the directory that contains a link of .env
+# Resolve the directory this script lives in for consistent behavior when invoked from elsewhere
+SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]:-$0}")" >/dev/null 2>&1 && pwd)"
+
+# Ensure script is executed in the mailcow installation directory by checking for a .env symlink that points to mailcow.conf
+if [ ! -L "${PWD}/.env" ]; then
+  echo -e "\e[33mPlease run this script from the mailcow installation directory.\e[0m"
+  echo -e "  \e[36mcd /path/to/mailcow && ./generate_config.sh\e[0m"
+  exit 1
+fi
+
+# Verify the .env symlink points to a mailcow.conf file
+env_target="$(readlink -f "${PWD}/.env" 2>/dev/null || true)"
+if [ -z "$env_target" ] || [ "$(basename "$env_target")" != "mailcow.conf" ]; then
+  echo -e "\e[31mThe found .env symlink does not point to a mailcow.conf file.\e[0m"
+  echo -e "\e[33mPlease create a symbolic link .env -> mailcow.conf inside the mailcow directory and run this script there.\e[0m"
+  echo -e "\e[33mNote: 'ln -s mailcow.conf .env' will create the symlink even if mailcow.conf does not yet exist.\e[0m"
+  echo -e "  \e[36mcd /path/to/mailcow && ln -s mailcow.conf .env && ./generate_config.sh\e[0m"
+  exit 1
+fi
+
 # Load mailcow Generic Scripts
 source _modules/scripts/core.sh
 source _modules/scripts/ipv6_controller.sh

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

@@ -293,7 +293,7 @@ if ! ssh -o StrictHostKeyChecking=no \
   -i "${REMOTE_SSH_KEY}" \
   ${REMOTE_SSH_HOST} \
   -p ${REMOTE_SSH_PORT} \
-  ${SCRIPT_DIR}/../update.sh -f --gc ; then
+  "cd \"${SCRIPT_DIR}/../\" && ./update.sh -f --gc" ; then
     >&2 echo -e "\e[31m[ERR]\e[0m - Could not cleanup old images on remote"
 fi
 

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

@@ -0,0 +1,18 @@
+services:
+    prometheus-exporter-mailcow:
+      image: ghcr.io/mailcow/prometheus-exporter:2
+      ports:
+        - "9099:9099"
+      restart: always
+      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)
+      dns:
+        - ${IPV4_NETWORK:-172.22.1}.254
+      networks:
+        mailcow-network:
+          ipv4_address: ${IPV4_NETWORK:-172.22.1}.209
+          aliases:
+            - prometheus-exporter

+ 3 - 2
helper-scripts/update_postscreen_whitelist.sh

@@ -6,9 +6,10 @@ SPFTOOLS_DIR=${WORKING_DIR}/spf-tools
 POSTWHITE_DIR=${WORKING_DIR}/postwhite
 POSTWHITE_CONF=${POSTWHITE_DIR}/postwhite.conf
 
-CUSTOM_HOSTS='"web.de gmx.net mail.de freenet.de arcor.de unity-mail.de"'
+CUSTOM_HOSTS='"web.de gmx.net mail.de freenet.de arcor.de unity-mail.de protonmail.ch ionos.com strato.com t-online.de"'
 STATIC_HOSTS=(
-    "194.25.134.0/24 permit # t-online.de"
+    "49.12.4.251 permit # checks.mailcow.email"
+    "2a01:4f8:c17:7906::10 permit # checks.mailcow.email"
 )
 
 mkdir ${SCRIPT_DIR}/postwhite_tmp

+ 14 - 2
update.sh

@@ -3,6 +3,20 @@
 ############## Begin Function Section ##############
 
 SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
+MAILCOW_CONF="${SCRIPT_DIR}/mailcow.conf"
+
+# Ensure the script is run from the directory that contains mailcow.conf
+if [ ! -f "${PWD}/mailcow.conf" ]; then
+  if [ -f "${SCRIPT_DIR}/mailcow.conf" ]; then
+    echo -e "\e[33mPlease run this script directly from the mailcow installation directory:\e[0m"
+    echo -e "  \e[36mcd ${SCRIPT_DIR} && ./update.sh\e[0m"
+    exit 1
+  else
+    echo -e "\e[31mmailcow.conf not found in current directory or script directory (\e[36m${SCRIPT_DIR}\e[31m).\e[0m"
+    echo -e "\e[33mRun this script directly from your mailcow installation directory.\e[0m"
+    exit 1
+  fi
+fi
 BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)"
 
 MODULE_DIR="${SCRIPT_DIR}/_modules"
@@ -27,8 +41,6 @@ if [ "$(id -u)" -ne "0" ]; then
   exit 1
 fi
 
-SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )"
-
 # Run pre-update-hook
 if [ -f "${SCRIPT_DIR}/pre_update_hook.sh" ]; then
   bash "${SCRIPT_DIR}/pre_update_hook.sh"