From 6dc90186f937ab9fa23db850abee0a3220641389 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 29 Aug 2025 16:22:28 +0000 Subject: [PATCH 001/109] chore(deps): update dependency krakjoe/apcu to v5.1.27 Signed-off-by: milkmaker --- data/Dockerfiles/phpfpm/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/phpfpm/Dockerfile b/data/Dockerfiles/phpfpm/Dockerfile index e7b43790b..262da24f4 100644 --- a/data/Dockerfiles/phpfpm/Dockerfile +++ b/data/Dockerfiles/phpfpm/Dockerfile @@ -3,7 +3,7 @@ FROM php:8.2-fpm-alpine3.21 LABEL maintainer = "The Infrastructure Company GmbH " # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?.*)$ -ARG APCU_PECL_VERSION=5.1.26 +ARG APCU_PECL_VERSION=5.1.27 # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?.*)$ ARG IMAGICK_PECL_VERSION=3.8.0 # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?.*)$ From 94c1a6c4e1f8901e38e4562dd208cc026277fab8 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 10 Sep 2025 16:20:58 +0200 Subject: [PATCH 002/109] scripts: ipv6_controller improvement + fix modules handling (#6722) * Fix subscript handling for modules * ipv6: detect case when link local is present * v6-controller: removed fixed-cidr for docker 28+ --- _modules/scripts/ipv6_controller.sh | 148 ++++++++++++++++++++-------- generate_config.sh | 21 ++++ helper-scripts/_cold-standby.sh | 2 +- update.sh | 16 ++- 4 files changed, 145 insertions(+), 42 deletions(-) diff --git a/_modules/scripts/ipv6_controller.sh b/_modules/scripts/ipv6_controller.sh index de5272048..1ff5eb198 100644 --- a/_modules/scripts/ipv6_controller.sh +++ b/_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" < "$DOCKER_DAEMON_CONFIG" <> "$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" } \ No newline at end of file diff --git a/generate_config.sh b/generate_config.sh index 9610bf18d..2dba91d51 100755 --- a/generate_config.sh +++ b/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 diff --git a/helper-scripts/_cold-standby.sh b/helper-scripts/_cold-standby.sh index bfda3ba94..f02436a95 100755 --- a/helper-scripts/_cold-standby.sh +++ b/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 diff --git a/update.sh b/update.sh index 89dec3e66..4ec0e7e40 100755 --- a/update.sh +++ b/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" From 4db1569c93ce41467f32a34007b081c179dc9645 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 10 Sep 2025 16:22:19 +0200 Subject: [PATCH 003/109] Squashed commit of the following: commit 94c1a6c4e1f8901e38e4562dd208cc026277fab8 Author: DerLinkman Date: Wed Sep 10 16:20:58 2025 +0200 scripts: ipv6_controller improvement + fix modules handling (#6722) * Fix subscript handling for modules * ipv6: detect case when link local is present * v6-controller: removed fixed-cidr for docker 28+ --- _modules/scripts/ipv6_controller.sh | 148 ++++++++++++++++++++-------- generate_config.sh | 21 ++++ helper-scripts/_cold-standby.sh | 2 +- update.sh | 16 ++- 4 files changed, 145 insertions(+), 42 deletions(-) diff --git a/_modules/scripts/ipv6_controller.sh b/_modules/scripts/ipv6_controller.sh index de5272048..1ff5eb198 100644 --- a/_modules/scripts/ipv6_controller.sh +++ b/_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" < "$DOCKER_DAEMON_CONFIG" <> "$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" } \ No newline at end of file diff --git a/generate_config.sh b/generate_config.sh index 9610bf18d..2dba91d51 100755 --- a/generate_config.sh +++ b/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 diff --git a/helper-scripts/_cold-standby.sh b/helper-scripts/_cold-standby.sh index bfda3ba94..f02436a95 100755 --- a/helper-scripts/_cold-standby.sh +++ b/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 diff --git a/update.sh b/update.sh index 89dec3e66..4ec0e7e40 100755 --- a/update.sh +++ b/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" From 642ac6d02cac69eec7c323ca4b582b72ff73416d Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu, 11 Sep 2025 10:34:35 +0200 Subject: [PATCH 004/109] [Web] remove unused bcc dest column from alias table --- data/web/js/site/mailbox.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/data/web/js/site/mailbox.js b/data/web/js/site/mailbox.js index 6a04eb241..df61f8720 100644 --- a/data/web/js/site/mailbox.js +++ b/data/web/js/site/mailbox.js @@ -1949,11 +1949,6 @@ jQuery(function($){ defaultContent: '', responsivePriority: 5, }, - { - title: lang.bcc_destinations, - data: 'bcc_dest', - defaultContent: '' - }, { title: lang.sogo_visible, data: 'sogo_visible', From 0d900d4fc8559072c5365f374f6025ebe1961638 Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu, 11 Sep 2025 11:01:50 +0200 Subject: [PATCH 005/109] [SOGo] Drop deprecated `sogo_update_password` sql trigger if it still exists --- data/Dockerfiles/sogo/bootstrap-sogo.sh | 4 ++++ docker-compose.yml | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index abd398b34..96d8a6919 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -24,6 +24,10 @@ while [[ "${DBV_NOW}" != "${DBV_NEW}" ]]; do done echo "DB schema is ${DBV_NOW}" +if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then + mariadb --skip-ssl --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password" +fi + # cat /dev/urandom seems to hang here occasionally and is not recommended anyway, better use openssl RAND_PASS=$(openssl rand -base64 16 | tr -dc _A-Z-a-z-0-9) diff --git a/docker-compose.yml b/docker-compose.yml index 874933bf0..215a196f9 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -200,7 +200,7 @@ services: - phpfpm sogo-mailcow: - image: ghcr.io/mailcow/sogo:1.134 + image: ghcr.io/mailcow/sogo:1.135 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} From 84e230de8f68705f8cf9b7ef20bc18525275bd35 Mon Sep 17 00:00:00 2001 From: patr_ <30580969+p-atr@users.noreply.github.com> Date: Fri, 12 Sep 2025 11:17:18 +0200 Subject: [PATCH 006/109] [Nginx] fix: Disable IPv6 support in Nginx configuration (#6736) Co-authored-by: patr_ --- data/conf/nginx/templates/nginx.conf.j2 | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/data/conf/nginx/templates/nginx.conf.j2 b/data/conf/nginx/templates/nginx.conf.j2 index d71d63e56..4b32ff15b 100644 --- a/data/conf/nginx/templates/nginx.conf.j2 +++ b/data/conf/nginx/templates/nginx.conf.j2 @@ -78,7 +78,7 @@ http { {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; - {% if not DISABLE_IPv6 %} + {% if ENABLE_IPV6 %} {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; {%endif%} @@ -105,7 +105,7 @@ http { {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; - {% if not DISABLE_IPv6 %} + {% if ENABLE_IPV6 %} {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; {%endif%} @@ -126,7 +126,7 @@ http { # rspamd dynmaps: server { listen 8081; - {% if not DISABLE_IPv6 %} + {% if ENABLE_IPV6 %} listen [::]:8081; {%endif%} index index.php index.html; @@ -199,7 +199,7 @@ http { {%endif%} listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; - {% if not DISABLE_IPv6 %} + {% if ENABLE_IPV6 %} {% if not HTTP_REDIRECT %} listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; {%endif%} From eb26bcbc9417c6d0d2fa35db7ea5e648b48e016f Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 13 Sep 2025 21:41:59 +0200 Subject: [PATCH 007/109] Translations update from Weblate (#6743) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.zh-cn.json Co-authored-by: Easton Man * [Web] Updated lang.si-si.json [Web] Updated lang.si-si.json Co-authored-by: Matjaž Tekavec Co-authored-by: milkmaker --------- Co-authored-by: Easton Man Co-authored-by: Matjaž Tekavec --- data/web/lang/lang.si-si.json | 15 ++++++++++----- data/web/lang/lang.zh-cn.json | 23 ++++++++++++++++++----- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 56da00f74..95e23a5cb 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -109,7 +109,9 @@ "relay_transport_info": "
Info
Definirate lahko preslikave transportov za cilj po meri za to domeno. Če ni nastavljena, se ustvari MX poizvedba.", "syncjob_hint": "Pozor! Gesla se morajo shraniti v golo besedilo!", "timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja", - "dry": "Simuliraj sinhronizacijo" + "dry": "Simuliraj sinhronizacijo", + "internal": "Notranje", + "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen." }, "admin": { "access": "Dostop", @@ -776,7 +778,9 @@ "mta_sts_max_age_info": "Čas v sekundah, ki ga lahko prejemni poštni strežniki shranijo v predpomnilnik, dokler se ne ponovno naloži.", "mta_sts_mx": "MX strežnik", "mta_sts_mx_info": "Omogoča pošiljanje samo na izrecno navedena imena gostiteljskih strežnikov poštnih strežnikov; pošiljajoči MTA preveri, ali se ime gostitelja DNS MX ujema s seznamom pravilnikov, in dovoljuje dostavo le z veljavnim potrdilom TLS (zaščita pred MITM).", - "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami)." + "mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami).", + "internal": "Notranje", + "internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen." }, "footer": { "restart_container_info": "Pomembno: Ugoden ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.", @@ -991,7 +995,8 @@ "yes": "✓", "weekly": "Tedensko", "sieve_info": "Na uporabnika lahko shranite več filtrov, vendar je lahko hkrati aktiven le en predfilter in en postfilter.
\nVsak filter bo obdelan v opisanem vrstnem redu. Niti neuspešen skript niti izdan ukaz »keep;« ne bosta ustavila obdelave nadaljnjih skript. Spremembe globalnih skriptov sita bodo sprožile ponovni zagon Dovecota.

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

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

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

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

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

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

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

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

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

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

Ngoài ra, cấu hình DNS của tên miền cần được xem xét. Khi cấu hình DNS được phê duyệt, khởi động lại \\\"acme-mailcow\\\" để tự động tạo chứng chỉ cho tên miền mới của bạn (autoconfig.<domain>, autodiscover.<domain>).
Bước này là tùy chọn và sẽ được thử lại sau mỗi 24 giờ.", + "private_comment": "Bình luận riêng tư", + "public_comment": "Bình luận công khai", + "quota_mb": "Hạn ngạch (MiB)", + "relay_all": "Chuyển tiếp tất cả người nhận", + "relay_all_info": "↪ Nếu bạn chọn không chuyển tiếp tất cả người nhận, bạn sẽ cần thêm một hộp thư (\"ẩn\") cho từng người nhận cần được chuyển tiếp.", + "relay_domain": "Chuyển tiếp tên miền này", + "relay_transport_info": "
Thông tin
Bạn có thể định nghĩa ánh xạ vận chuyển cho đích tùy chỉnh cho tên miền này. Nếu không được đặt, tra cứu MX sẽ được thực hiện.", + "relay_unknown_only": "Chỉ chuyển tiếp hộp thư không tồn tại. Hộp thư hiện có sẽ được gửi cục bộ.", + "relayhost_wrapped_tls_info": "Vui lòng không sử dụng các cổng được bọc TLS (thường được sử dụng trên cổng 465).
\nSử dụng bất kỳ cổng không được bọc nào và sử dụng STARTTLS. Chính sách TLS để thực thi TLS có thể được tạo trong \"Ánh xạ chính sách TLS\".", + "select": "Vui lòng chọn...", + "select_domain": "Vui lòng chọn tên miền trước", + "sieve_desc": "Mô tả ngắn", + "sieve_type": "Loại bộ lọc", + "skipcrossduplicates": "Bỏ qua tin nhắn trùng lặp giữa các thư mục (ai đến trước được phục vụ trước)", + "subscribeall": "Đăng ký tất cả thư mục", + "syncjob": "Thêm công việc đồng bộ", + "syncjob_hint": "Lưu ý rằng mật khẩu cần được lưu dưới dạng văn bản thuần!", + "tags": "Thẻ", + "target_address": "Địa chỉ chuyển tiếp", + "target_address_info": "Địa chỉ email đầy đủ (phân cách bằng dấu phẩy).", + "target_domain": "Tên miền đích", + "timeout1": "Thời gian chờ kết nối đến máy chủ từ xa", + "timeout2": "Thời gian chờ kết nối đến máy chủ cục bộ", + "username": "Tên người dùng", + "validate": "Xác thực", + "validation_success": "Xác thực thành công" + }, + "admin": { + "access": "Truy cập", + "action": "Hành động", + "activate_api": "Kích hoạt API", + "activate_send": "Kích hoạt nút gửi", + "active": "Đang hoạt động", + "active_rspamd_settings_map": "Ánh xạ cài đặt đang hoạt động", + "add": "Thêm", + "add_admin": "Thêm quản trị viên", + "add_domain_admin": "Thêm quản trị viên tên miền", + "add_forwarding_host": "Thêm máy chủ chuyển tiếp", + "add_relayhost": "Thêm vận chuyển phụ thuộc người gửi", + "add_relayhost_hint": "Vui lòng lưu ý rằng dữ liệu xác thực, nếu có, sẽ được lưu trữ dưới dạng văn bản thuần.", + "add_row": "Thêm hàng", + "add_settings_rule": "Thêm quy tắc cài đặt", + "add_transport": "Thêm vận chuyển", + "add_transports_hint": "Vui lòng lưu ý rằng dữ liệu xác thực, nếu có, sẽ được lưu trữ dưới dạng văn bản thuần.", + "additional_rows": " hàng bổ sung đã được thêm", + "admin": "Quản trị viên", + "admin_details": "Chỉnh sửa chi tiết quản trị viên", + "admin_domains": "Gán tên miền", + "admins": "Những quản trị viên", + "admins_ldap": "Quản trị viên LDAP", + "admin_quicklink": "Ẩn liên kết nhanh đến trang đăng nhập quản trị", + "advanced_settings": "Cài đặt nâng cao", + "allowed_methods": "Phương thức cho phép kiểm soát truy cập", + "allowed_origins": "Nguồn gốc cho phép kiểm soát truy cập", + "api_allow_from": "Cho phép truy cập API từ các IP/ký hiệu mạng CIDR này", + "api_info": "API đang được phát triển. Tài liệu có thể được tìm thấy tại /api", + "api_key": "Khóa API", + "api_read_only": "Truy cập chỉ đọc", + "api_read_write": "Truy cập đọc-ghi", + "api_skip_ip_check": "Bỏ qua kiểm tra IP cho API", + "app_hide": "Ẩn khi đăng nhập", + "app_links": "Liên kết ứng dụng", + "app_name": "Tên ứng dụng", + "apps_name": "Tên \"Ứng dụng mailcow\"", + "arrival_time": "Thời gian đến (giờ máy chủ)", + "authed_user": "Người dùng đã xác thực", + "ays": "Bạn có chắc chắn muốn tiếp tục không?", + "ban_list_info": "Xem danh sách IP bị cấm bên dưới: mạng (thời gian cấm còn lại) - [hành động].
IP trong hàng đợi bỏ cấm sẽ được xóa khỏi danh sách cấm hoạt động trong vài giây.
Nhãn đỏ cho biết lệnh cấm vĩnh viễn đang hoạt động bởi danh sách từ chối.", + "change_logo": "Thay đổi logo", + "logo_normal_label": "Bình thường", + "logo_dark_label": "Đảo ngược cho chế độ tối", + "configuration": "Cấu hình", + "convert_html_to_text": "Chuyển đổi HTML thành văn bản thuần", + "copy_to_clipboard": "Văn bản đã được sao chép vào bộ nhớ tạm!", + "cors_settings": "Cài đặt CORS", + "credentials_transport_warning": "Cảnh báo: Thêm một mục ánh xạ vận chuyển mới sẽ cập nhật thông tin xác thực cho tất cả các mục có cột bước nhảy tiếp theo khớp.", + "customer_id": "ID Khách hàng", + "customize": "Tùy chỉnh", + "login_page": "Trang đăng nhập", + "destination": "Đích đến", + "dkim_add_key": "Thêm khóa ARC/DKIM", + "dkim_domains_selector": "Bộ chọn", + "dkim_domains_wo_keys": "Chọn tên miền thiếu khóa", + "dkim_from": "Từ", + "dkim_from_title": "Tên miền nguồn để sao chép dữ liệu", + "dkim_key_length": "Độ dài khóa DKIM (bits)", + "dkim_key_missing": "Thiếu khóa", + "dkim_key_unused": "Khóa không được sử dụng", + "dkim_key_valid": "Khóa hợp lệ", + "dkim_keys": "Khóa ARC/DKIM", + "dkim_overwrite_key": "Ghi đè khóa DKIM hiện có", + "dkim_private_key": "Khóa riêng tư", + "dkim_to": "Đến", + "dkim_to_title": "Tên miền đích - sẽ bị ghi đè", + "domain": "Tên miền", + "domain_admin": "Quản trị viên tên miền", + "domain_admins": "Các quản trị viên tên miền", + "domainadmin_quicklink": "Ẩn liên kết nhanh đến trang đăng nhập quản trị viên tên miền", + "domain_s": "Tên miền/s", + "duplicate": "Nhân bản", + "duplicate_dkim": "Nhân bản bản ghi DKIM", + "edit": "Chỉnh sửa", + "empty": "Không có kết quả", + "excludes": "Loại trừ những người nhận này", + "f2b_ban_time": "Thời gian cấm (giây)", + "f2b_ban_time_increment": "Thời gian cấm tăng dần với mỗi lần cấm", + "f2b_blacklist": "Mạng/máy chủ bị từ chối", + "f2b_filter": "Bộ lọc biểu thức chính quy", + "f2b_list_info": "Một máy chủ hoặc mạng bị từ chối sẽ luôn có quyền ưu tiên cao hơn một thực thể trong danh sách cho phép. Cập nhật danh sách sẽ mất vài giây để được áp dụng.", + "f2b_manage_external": "Quản lý Fail2Ban từ bên ngoài", + "f2b_manage_external_info": "Fail2ban sẽ vẫn duy trì danh sách cấm, nhưng sẽ không chủ động đặt quy tắc để chặn lưu lượng. Sử dụng danh sách cấm được tạo bên dưới để chặn lưu lượng từ bên ngoài.", + "f2b_max_attempts": "Số lần thử tối đa", + "f2b_max_ban_time": "Thời gian cấm tối đa (giây)", + "f2b_netban_ipv4": "Kích thước mạng con IPv4 để áp dụng lệnh cấm (8-32)", + "f2b_netban_ipv6": "Kích thước mạng con IPv6 để áp dụng lệnh cấm (8-128", + "f2b_parameters": "Tham số Fail2ban", + "f2b_regex_info": "Nhật ký được xem xét: SOGo, Postfix, Dovecot, PHP-FPM.", + "f2b_retry_window": "Cửa sổ thử lại (giây) cho số lần thử tối đa", + "f2b_whitelist": "Mạng/máy chủ được cho phép", + "filter": "Bộ lọc", + "filter_table": "Bảng bộ lọc", + "force_sso_text": "Nếu nhà cung cấp OIDC bên ngoài được cấu hình, tùy chọn này sẽ ẩn biểu mẫu đăng nhập mailcow mặc định và chỉ hiển thị nút Đăng nhập một lần", + "force_sso": "Vô hiệu hóa đăng nhập mailcow và chỉ hiển thị Đăng nhập một lần", + "forwarding_hosts": "Máy chủ chuyển tiếp", + "forwarding_hosts_add_hint": "Bạn có thể chỉ định địa chỉ IPv4/IPv6, mạng theo ký hiệu CIDR, tên máy chủ (sẽ được phân giải thành địa chỉ IP), hoặc tên miền (sẽ được phân giải thành địa chỉ IP bằng cách truy vấn bản ghi SPF hoặc, nếu không có, bản ghi MX).", + "forwarding_hosts_hint": "Tin nhắn đến được chấp nhận vô điều kiện từ bất kỳ máy chủ nào được liệt kê ở đây. Các máy chủ này sau đó không bị kiểm tra với DNSBL hoặc danh sách xám. Thư rác nhận từ chúng không bao giờ bị từ chối, nhưng có thể được chuyển vào thư mục Rác. Công dụng phổ biến nhất cho việc này là chỉ định các máy chủ thư mà bạn đã thiết lập quy tắc chuyển tiếp email đến cho máy chủ mailcow của bạn.", + "from": "Từ", + "generate": "tạo", + "guid": "GUID - ID phiên bản duy nhất", + "guid_and_license": "GUID & Giấy phép", + "hash_remove_info": "Xóa một giá trị băm giới hạn tốc độ (nếu vẫn tồn tại) sẽ đặt lại hoàn toàn bộ đếm của nó.mailcow_password, được ánh xạ trong Keycloak.", + "iam_basedn": "DN cơ sở", + "iam_client_id": "ID khách hàng", + "iam_client_secret": "Bí mật khách hàng", + "iam_client_scopes": "Phạm vi khách hàng", + "iam_default_template": "Mẫu mặc định", + "iam_default_template_description": "Nếu không có mẫu nào được gán cho người dùng, mẫu mặc định sẽ được sử dụng để tạo hộp thư, nhưng không dùng để cập nhật hộp thư.", + "iam_description": "Cấu hình Nhà cung cấp bên ngoài cho Xác thực
Hộp thư của người dùng sẽ được tự động tạo khi họ đăng nhập lần đầu, với điều kiện ánh xạ thuộc tính đã được thiết lập.", + "iam_extra_permission": "Để các cài đặt sau hoạt động, ứng dụng khách mailcow trong Keycloak cần một Tài khoản dịch vụ và quyền xem người dùng.", + "iam_host": "Máy chủ", + "iam_host_info": "Nhập một hoặc nhiều máy chủ LDAP, phân cách bằng dấu phẩy.", + "iam_import_users": "Nhập người dùng", + "iam_login_provisioning": "Tự động tạo người dùng khi đăng nhập", + "iam_mapping": "Ánh xạ thuộc tính", + "iam_bindpass": "Mật khẩu ràng buộc", + "iam_periodic_full_sync": "Đồng bộ hóa đầy đủ định kỳ", + "iam_port": "Cổng", + "iam_realm": "Vùng", + "iam_redirect_url": "URL chuyển hướng", + "iam_rest_flow": "Luồng mật khẩu thư", + "iam_server_url": "URL máy chủ", + "iam_sso": "Đăng nhập một lần", + "iam_sync_interval": "Khoảng thời gian đồng bộ / nhập (phút)", + "iam_test_connection": "Kiểm tra kết nối", + "iam_token_url": "Điểm cuối token", + "iam_userinfo_url": "Điểm cuối thông tin người dùng", + "iam_username_field": "Trường tên người dùng", + "iam_binddn": "DN ràng buộc", + "iam_use_ssl": "Sử dụng SSL", + "iam_use_ssl_info": "Nếu bật SSL và cổng được đặt là 389, nó sẽ tự động được ghi đè để sử dụng cổng 636.", + "iam_use_tls": "Sử dụng StartTLS", + "iam_use_tls_info": "Nếu bật TLS, bạn phải sử dụng cổng mặc định cho máy chủ LDAP của bạn (389). Không thể sử dụng các cổng SSL.", + "iam_version": "Phiên bản", + "ignore_ssl_error": "Bỏ qua lỗi SSL", + "import": "Nhập", + "import_private_key": "Nhập khóa riêng tư", + "in_use_by": "Đang được sử dụng bởi", + "inactive": "Không hoạt động", + "include_exclude": "Bao gồm/Loại trừ", + "include_exclude_info": "Mặc định - khi không có lựa chọn - tất cả hộp thư được đề cập", + "includes": "Bao gồm những người nhận này", + "ip_check": "Kiểm tra IP", + "ip_check_disabled": "Kiểm tra IP đã bị vô hiệu hóa. Bạn có thể bật nó trong
Hệ thống > Cấu hình > Tùy chọn > Tùy chỉnh", + "ip_check_opt_in": "Chọn tham gia sử dụng dịch vụ bên thứ ba ipv4.mailcow.emailipv6.mailcow.email để phân giải địa chỉ IP bên ngoài.", + "is_mx_based": "Dựa trên MX", + "last_applied": "Áp dụng lần cuối", + "license_info": "Giấy phép không bắt buộc nhưng giúp phát triển thêm.
Đăng ký GUID của bạn tại đây hoặc mua hỗ trợ cho cài đặt mailcow của bạn.", + "link": "Liên kết", + "loading": "Vui lòng đợi...", + "login_time": "Thời gian đăng nhập", + "logo_info": "Hình ảnh của bạn sẽ được điều chỉnh theo chiều cao 40px cho thanh điều hướng trên cùng và chiều rộng tối đa 250px cho trang bắt đầu. Khuyến nghị sử dụng đồ họa có thể thay đổi kích thước.", + "lookup_mx": "Đích đến là một biểu thức chính quy để so khớp với tên MX (.*.google.com để định tuyến tất cả thư nhắm đến MX kết thúc bằng google.com qua bước nhảy này)", + "main_name": "Tên \"Giao diện mailcow\"", + "merged_vars_hint": "Các hàng bị mờ đã được hợp nhất từ vars.(local.)inc.php và không thể sửa đổi.", + "message": "Tin nhắn", + "message_size": "Kích thước tin nhắn", + "nexthop": "Bước nhảy tiếp theo", + "needs_restart": "cần khởi động lại", + "no_active_bans": "Không có lệnh cấm đang hoạt động", + "no_new_rows": "Không có hàng nào khác", + "no_record": "Không có bản ghi", + "oauth2_apps": "Ứng dụng OAuth2", + "oauth2_add_client": "Thêm ứng dụng khách OAuth2", + "oauth2_client_id": "ID ứng dụng khách", + "oauth2_client_secret": "Bí mật ứng dụng khách", + "oauth2_info": "Triển khai OAuth2 hỗ trợ loại cấp phép \"Mã ủy quyền\" và cấp token làm mới.
\nMáy chủ cũng tự động cấp token làm mới mới sau khi token làm mới đã được sử dụng.

\n• Phạm vi mặc định là profile. Chỉ người dùng hộp thư mới có thể được xác thực qua OAuth2. Nếu tham số phạm vi bị bỏ qua, nó sẽ trở về profile.
\n• Tham số state phải được gửi bởi ứng dụng khách như một phần của yêu cầu ủy quyền.

\nĐường dẫn cho các yêu cầu đến API OAuth2:
\n
    \n
  • Điểm cuối ủy quyền: /oauth/authorize
  • \n
  • Điểm cuối token: /oauth/token
  • \n
  • Trang tài nguyên: /oauth/profile
  • \n
\nTạo lại bí mật ứng dụng khách sẽ không làm hết hạn các mã ủy quyền hiện có, nhưng chúng sẽ không thể làm mới token của họ.

\nThu hồi token ứng dụng khách sẽ gây ra việc chấm dứt ngay lập tức tất cả các phiên hoạt động. Tất cả ứng dụng khách cần xác thực lại.", + "oauth2_redirect_uri": "URI chuyển hướng", + "oauth2_renew_secret": "Tạo bí mật ứng dụng khách mới", + "oauth2_revoke_tokens": "Thu hồi tất cả token ứng dụng khách", + "optional": "tùy chọn", + "options": "Các tùy chọn", + "password": "Mật khẩu", + "password_length": "Độ dài mật khẩu", + "password_policy": "Chính sách mật khẩu", + "password_policy_chars": "Phải chứa ít nhất một ký tự chữ cái", + "password_policy_length": "Độ dài mật khẩu tối thiểu là %d", + "password_policy_lowerupper": "Phải chứa ký tự viết thường và viết hoa", + "password_policy_numbers": "Phải chứa ít nhất một số", + "password_policy_special_chars": "Phải chứa ký tự đặc biệt", + "password_repeat": "Xác nhận mật khẩu (nhập lại)", + "password_reset_info": "Nếu không cung cấp email khôi phục, chức năng này không thể được sử dụng.", + "password_reset_settings": "Cài đặt khôi phục mật khẩu", + "password_reset_tmpl_html": "Mẫu HTML", + "password_reset_tmpl_text": "Mẫu văn bản", + "password_settings": "Cài đặt mật khẩu", + "priority": "Độ ưu tiên", + "private_key": "Khóa riêng tư", + "quarantine": "Cách ly", + "quarantine_bcc": "Gửi một bản sao của tất cả thông báo (BCC) đến người nhận này:
Để trống để vô hiệu hóa. Thư không ký, không kiểm tra. Chỉ nên gửi nội bộ.", + "quarantine_exclude_domains": "Loại trừ tên miền và tên miền bí danh", + "quarantine_max_age": "Tuổi tối đa theo ngày
Giá trị phải bằng hoặc lớn hơn 1 ngày.", + "quarantine_max_score": "Bỏ thông báo nếu điểm thư rác của một thư cao hơn giá trị này:
Mặc định là 9999.0", + "quarantine_max_size": "Kích thước tối đa tính bằng MiB (các phần tử lớn hơn sẽ bị loại bỏ):
0 không có nghĩa là không giới hạn.", + "quarantine_notification_html": "Mẫu email thông báo:
Để trống để khôi phục mẫu mặc định.", + "quarantine_notification_sender": "Người gửi email thông báo", + "quarantine_notification_subject": "Chủ đề email thông báo", + "quarantine_redirect": "Chuyển hướng tất cả thông báo đến người nhận này:
Để trống để vô hiệu hóa. Thư không ký, không kiểm tra. Chỉ nên gửi nội bộ.", + "quarantine_release_format": "Định dạng của các mục được phát hành", + "quarantine_release_format_att": "Dưới dạng tệp đính kèm", + "quarantine_release_format_raw": "Bản gốc không sửa đổi", + "quarantine_retention_size": "ưu giữ cho mỗi hộp thư:
0 có nghĩa là không hoạt động.", + "quicklink_text": "Hiển thị hoặc ẩn liên kết nhanh đến các trang đăng nhập khác dưới biểu mẫu đăng nhập", + "quota_notification_html": "Mẫu email thông báo:
Để trống để khôi phục mẫu mặc định.", + "quota_notification_sender": "Người gửi email thông báo", + "quota_notification_subject": "Chủ đề email thông báo", + "quota_notifications": "Thông báo hạn ngạch", + "quota_notifications_info": "Thông báo hạn ngạch được gửi cho người dùng một lần khi vượt quá 80% và một lần khi vượt quá 95% mức sử dụng.", + "quota_notifications_vars": "{{percent}} bằng hạn ngạch hiện tại của người dùng
{{username}} là tên hộp thư", + "queue_unban": "bỏ cấm", + "r_active": "Hạn chế đang hoạt động", + "r_inactive": "Hạn chế không hoạt động", + "r_info": "Các phần tử bị mờ/vô hiệu hóa trong danh sách hạn chế đang hoạt động không được mailcow công nhận là hạn chế hợp lệ và không thể di chuyển. Các hạn chế không xác định sẽ vẫn được đặt theo thứ tự xuất hiện.
Bạn có thể thêm phần tử mới trong inc/vars.local.inc.php để có thể bật/tắt chúng.", + "rate_name": "Tên tỷ lệ", + "recipients": "Người nhận", + "refresh": "Làm mới", + "regen_api_key": "Tạo lại khóa API", + "regex_maps": "Ánh xạ biểu thức chính quy", + "relay_from": "Địa chỉ \"Từ:\"", + "relay_rcpt": "Địa chỉ \"Đến:\"", + "relay_run": "Chạy thử", + "relayhosts": "Vận chuyển phụ thuộc người gửi", + "relayhosts_hint": "Xác định vận chuyển phụ thuộc người gửi để có thể chọn chúng trong hộp thoại cấu hình tên miền.
\nDịch vụ vận chuyển luôn là \"smtp:\" và do đó sẽ thử TLS khi được cung cấp. TLS được bọc (SMTPS) không được hỗ trợ. Cài đặt chính sách TLS gửi đi riêng của người dùng được tính đến.
\nẢnh hưởng đến các tên miền được chọn bao gồm cả tên miền bí danh.", + "remove": "Xóa", + "remove_row": "Xóa hàng", + "reset_default": "Đặt lại về mặc định", + "reset_limit": "Xóa giá trị băm", + "reset_password_vars": "{{link}} Liên kết đặt lại mật khẩu đã tạo
{{username}} Tên hộp thư của người dùng yêu cầu đặt lại mật khẩu
{{username2}} Tên hộp thư khôi phục
{{date}} Ngày yêu cầu đặt lại mật khẩu được thực hiện
{{token_lifetime}} Thời gian sống của token tính bằng phút
{{hostname}} Tên máy chủ mailcow", + "restore_template": "Để trống để khôi phục mẫu mặc định.", + "routing": "Định tuyến", + "rsetting_add_rule": "Thêm quy tắc", + "rsetting_content": "Nội dung quy tắc", + "rsetting_desc": "Mô tả ngắn", + "rsetting_no_selection": "Vui lòng chọn một quy tắc", + "rsetting_none": "Không có quy tắc nào", + "rsettings_insert_preset": "Chèn mẫu ví dụ \"%s\"", + "rsettings_preset_1": "Vô hiệu hóa tất cả trừ DKIM và giới hạn tốc độ cho người dùng đã xác thực", + "rsettings_preset_2": "Quản trị viên bưu điện muốn thư rác", + "rsettings_preset_3": "Chỉ cho phép người gửi cụ thể cho một hộp thư (ví dụ: sử dụng như hộp thư nội bộ)", + "rsettings_preset_4": "Vô hiệu hóa Rspamd cho một tên miền", + "rspamd_com_settings": "Tên cài đặt sẽ được tự động tạo, vui lòng xem các mẫu ví dụ bên dưới. Để biết thêm chi tiết, xem Tài liệu Rspamd", + "rspamd_global_filters": "Ánh xạ bộ lọc toàn cục", + "rspamd_global_filters_agree": "Tôi sẽ cẩn thận!", + "rspamd_global_filters_info": "Ánh xạ bộ lọc toàn cục chứa các loại danh sách từ chối và cho phép toàn cục khác nhau.", + "rspamd_global_filters_regex": "Tên của chúng giải thích mục đích sử dụng. Tất cả nội dung phải chứa biểu thức chính quy hợp lệ theo định dạng \"/mẫu/tùy chọn\" (ví dụ: /.+@domain.tld/i).
\nMặc dù kiểm tra cơ bản được thực hiện trên mỗi dòng của regex, chức năng của Rspamd có thể bị hỏng nếu nó không đọc được cú pháp chính xác.
\nRspamd sẽ cố gắng đọc nội dung ánh xạ khi thay đổi. Nếu bạn gặp vấn đề, khởi động lại Rspamd để bắt buộc tải lại ánh xạ.
Các phần tử trong danh sách từ chối được loại trừ khỏi cách ly.", + "rspamd_settings_map": "Ánh xạ cài đặt Rspamd", + "sal_level": "Cấp độ Moo", + "save": "Lưu thay đổi", + "search_domain_da": "Tìm kiếm tên miền", + "send": "Gửi", + "sender": "Người gửi", + "service": "Dịch vụ", + "service_id": "ID Dịch vụ", + "source": "Nguồn", + "spamfilter": "Bộ lọc thư rác", + "subject": "Chủ đề", + "success": "Thành công", + "sys_mails": "Thư hệ thống", + "task": "Nhiệm vụ", + "text": "Văn bản", + "time": "Thời gian", + "title": "Tiêu đề", + "title_name": "Tiêu đề trang web \"Giao diện mailcow\"", + "to_top": "Về đầu trang", + "transport_dest_format": "Regex hoặc cú pháp: example.org, .example.org, *, box@example.org (nhiều giá trị có thể được phân cách bằng dấu phẩy)", + "transport_maps": "Ánh xạ vận chuyển", + "transport_test_rcpt_info": "• Sử dụng null@hosted.mailcow.de để kiểm tra chuyển tiếp đến đích nước ngoài.", + "transports_hint": "• Một mục ánh xạ vận chuyển ghi đè một ánh xạ vận chuyển phụ thuộc người gửi.
\n• Vận chuyển dựa trên MX được ưu tiên sử dụng.
\n• Cài đặt chính sách TLS gửi đi cho từng người dùng bị bỏ qua và chỉ có thể được thực thi bởi các mục ánh xạ chính sách TLS.
\n• Dịch vụ vận chuyển cho các vận chuyển đã định nghĩa luôn là \"smtp:\" và do đó sẽ thử TLS khi được cung cấp. TLS được bọc (SMTPS) không được hỗ trợ.
\n• Địa chỉ khớp với \"/localhost$/\" sẽ luôn được vận chuyển qua \"local:\", do đó đích \"*\" sẽ không áp dụng cho những địa chỉ đó.
\n• Để xác định thông tin xác thực cho bước nhảy tiếp theo ví dụ \"[host]:25\", Postfix luôn truy vấn \"host\" trước khi tìm kiếm \"[host]:25\". Hành vi này khiến không thể sử dụng \"host\" và \"[host]:25\" cùng một lúc.", + "ui_footer": "Chân trang (cho phép HTML)", + "ui_header_announcement": "Thông báo", + "ui_header_announcement_active": "Đặt thông báo hoạt động", + "ui_header_announcement_content": "Văn bản (cho phép HTML)", + "ui_header_announcement_help": "Thông báo hiển thị cho tất cả người dùng đã đăng nhập và trên màn hình đăng nhập của giao diện người dùng.", + "ui_header_announcement_select": "Chọn loại thông báo", + "ui_header_announcement_type": "Loại", + "ui_header_announcement_type_danger": "Rất quan trọng", + "ui_header_announcement_type_info": "Thông tin", + "ui_header_announcement_type_warning": "Quan trọng", + "ui_texts": "Nhãn và văn bản giao diện người dùng", + "unban_pending": "đang chờ bỏ cấm", + "unchanged_if_empty": "Nếu không thay đổi hãy để trống", + "upload": "Tải lên", + "username": "Tên người dùng", + "user_link": "Liên kết người dùng", + "user_quicklink": "Ẩn liên kết nhanh đến trang đăng nhập người dùng", + "validate_license_now": "Xác thực GUID với máy chủ giấy phép", + "verify": "Xác minh", + "yes": "✓" + }, + "danger": { + "access_denied": "Truy cập bị từ chối hoặc dữ liệu biểu mẫu không hợp lệ", + "alias_domain_invalid": "Tên miền bí danh %s không hợp lệ", + "alias_empty": "Địa chỉ bí danh không được để trống", + "alias_goto_identical": "Địa chỉ bí danh và địa chỉ chuyển tiếp không được giống nhau", + "alias_invalid": "Địa chỉ bí danh %s không hợp lệ", + "aliasd_targetd_identical": "Tên miền bí danh không được giống với tên miền đích: %s", + "aliases_in_use": "Số bí danh tối đa phải lớn hơn hoặc bằng %d", + "app_name_empty": "Tên ứng dụng không được để trống", + "app_passwd_id_invalid": "ID mật khẩu ứng dụng %s không hợp lệ", + "authsource_in_use": "Nhà cung cấp danh tính không thể thay đổi hoặc xóa vì hiện đang được sử dụng bởi một hoặc nhiều người dùng.", + "bcc_empty": "Đích BCC không được để trống", + "bcc_exists": "Một ánh xạ BCC %s đã tồn tại cho loại %s", + "bcc_must_be_email": "Đích BCC %s không phải là địa chỉ email hợp lệ", + "comment_too_long": "Bình luận quá dài, cho phép tối đa 160 ký tự", + "cors_invalid_method": "Phương thức Allow-Method được chỉ định không hợp lệ", + "cors_invalid_origin": "Allow-Origin được chỉ định không hợp lệ", + "defquota_empty": "Hạn ngạch mặc định cho mỗi hộp thư không được là 0.", + "demo_mode_enabled": "Chế độ Demo đang được bật", + "description_invalid": "Mô tả tài nguyên cho %s không hợp lệ" + } +} From 0338a36ecfb8ba33fe8c811afe7107c99093890c Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Tue, 21 Oct 2025 18:03:02 +0200 Subject: [PATCH 071/109] chore(deps): update alpine docker tag to v3.22 (#6417) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml b/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml index 5e0e98f44..a0b63b3a6 100644 --- a/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml +++ b/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml @@ -25,6 +25,6 @@ services: - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock mysql-mailcow: - image: alpine:3.20 + image: alpine:3.22 command: /bin/true restart: "no" From fbcb8cbeb9cd86ce07ed2776a5a377d4b2c2961c Mon Sep 17 00:00:00 2001 From: milkmaker Date: Tue, 21 Oct 2025 18:03:22 +0200 Subject: [PATCH 072/109] [Web] Updated lang.vi-vn.json (#6861) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Co-authored-by: Nguyễn Thái Dũng --- data/web/lang/lang.vi-vn.json | 262 +++++++++++++++++++++++++++++++++- 1 file changed, 261 insertions(+), 1 deletion(-) diff --git a/data/web/lang/lang.vi-vn.json b/data/web/lang/lang.vi-vn.json index d492ac08a..54e0b99b2 100644 --- a/data/web/lang/lang.vi-vn.json +++ b/data/web/lang/lang.vi-vn.json @@ -431,6 +431,266 @@ "cors_invalid_origin": "Allow-Origin được chỉ định không hợp lệ", "defquota_empty": "Hạn ngạch mặc định cho mỗi hộp thư không được là 0.", "demo_mode_enabled": "Chế độ Demo đang được bật", - "description_invalid": "Mô tả tài nguyên cho %s không hợp lệ" + "description_invalid": "Mô tả tài nguyên cho %s không hợp lệ", + "dkim_domain_or_sel_exists": "Một khóa DKIM cho \"%s\" đã tồn tại và sẽ không bị ghi đè", + "dkim_domain_or_sel_invalid": "Tên miền hoặc bộ chọn DKIM không hợp lệ: %s", + "domain_cannot_match_hostname": "Tên miền không thể trùng với tên máy chủ", + "domain_exists": "Tên miền %s đã tồn tại", + "domain_invalid": "Tên miền trống hoặc không hợp lệ", + "domain_not_empty": "Không thể xóa tên miền %s không trống", + "domain_not_found": "Không tìm thấy tên miền %s", + "domain_quota_m_in_use": "Hạn ngạch tên miền phải lớn hơn hoặc bằng %s MiB", + "extended_sender_acl_denied": "thiếu ACL để đặt địa chỉ người gửi bên ngoài", + "extra_acl_invalid": "Địa chỉ người gửi bên ngoài \"%s\" không hợp lệ", + "extra_acl_invalid_domain": "Người gửi bên ngoài \"%s\" sử dụng tên miền không hợp lệ", + "fido2_verification_failed": "Xác minh FIDO2 thất bại: %s", + "file_open_error": "Không thể mở tệp để ghi", + "filter_type": "Loại bộ lọc không đúng", + "from_invalid": "Người gửi không được để trống", + "generic_server_error": "Đã xảy ra lỗi máy chủ không mong đợi. Vui lòng liên hệ quản trị viên của bạn.", + "global_filter_write_error": "Không thể ghi tệp bộ lọc: %s", + "global_map_invalid": "ID ánh xạ toàn cục %s không hợp lệ", + "global_map_write_error": "Không thể ghi ID ánh xạ toàn cục %s: %s", + "goto_empty": "Một địa chỉ bí danh phải chứa ít nhất một địa chỉ chuyển tiếp hợp lệ", + "goto_invalid": "Địa chỉ chuyển tiếp %s không hợp lệ", + "ham_learn_error": "Lỗi học thư hợp lệ: %s", + "iam_test_connection": "Kết nối thất bại", + "imagick_exception": "Lỗi: Ngoại lệ Imagick khi đọc hình ảnh", + "img_dimensions_exceeded": "Hình ảnh vượt quá kích thước tối đa cho phép", + "img_invalid": "Không thể xác thực tệp hình ảnh", + "img_size_exceeded": "Hình ảnh vượt quá kích thước tệp tối đa", + "img_tmp_missing": "Không thể xác thực tệp hình ảnh: Không tìm thấy tệp tạm thời", + "invalid_bcc_map_type": "Loại ánh xạ BCC không hợp lệ", + "invalid_destination": "Định dạng đích \"%s\" không hợp lệ", + "invalid_filter_type": "Loại bộ lọc không hợp lệ", + "invalid_host": "Máy chủ được chỉ định không hợp lệ: %s", + "invalid_mime_type": "Kiểu MIME không hợp lệ", + "invalid_nexthop": "Định dạng bước nhảy tiếp theo không hợp lệ", + "invalid_nexthop_authenticated": "Bước nhảy tiếp theo tồn tại với thông tin xác thực khác, vui lòng cập nhật thông tin xác thực hiện có cho bước nhảy này trước.", + "invalid_recipient_map_new": "Người nhận mới được chỉ định không hợp lệ: %s", + "invalid_recipient_map_old": "Người nhận gốc được chỉ định không hợp lệ: %s", + "invalid_reset_token": "Token đặt lại không hợp lệ", + "ip_list_empty": "Danh sách IP được phép không được để trống", + "is_alias": "%s đã được biết đến như một địa chỉ bí danh", + "is_alias_or_mailbox": "%s đã được biết đến như một bí danh, một hộp thư hoặc một địa chỉ bí danh được mở rộng từ một tên miền bí danh.", + "is_spam_alias": "%s đã được biết đến như một địa chỉ bí danh tạm thời (địa chỉ bí danh thư rác)", + "last_key": "Không thể xóa khóa cuối cùng, vui lòng vô hiệu hóa TFA thay thế.", + "login_failed": "Đăng nhập không thành công", + "mailbox_defquota_exceeds_mailbox_maxquota": "Hạn ngạch mặc định vượt quá giới hạn hạn ngạch tối đa", + "mailbox_invalid": "Tên hộp thư không hợp lệ", + "mailbox_quota_exceeded": "Hạn ngạch vượt quá giới hạn tên miền (tối đa %d MiB)", + "mailbox_quota_exceeds_domain_quota": "Hạn ngạch tối đa vượt quá giới hạn hạn ngạch tên miền", + "mailbox_quota_left_exceeded": "Không đủ dung lượng còn lại (dung lượng còn lại: %d MiB)", + "mailboxes_in_use": "Số hộp thư tối đa phải lớn hơn hoặc bằng %d", + "malformed_username": "Tên người dùng không đúng định dạng", + "map_content_empty": "Nội dung ánh xạ không được để trống", + "max_age_invalid": "Tuổi tối đa %s không hợp lệ", + "max_alias_exceeded": "Vượt quá số bí danh tối đa", + "max_mailbox_exceeded": "Vượt quá số hộp thư tối đa (%d trên %d)", + "max_quota_in_use": "Hạn ngạch hộp thư phải lớn hơn hoặc bằng %d MiB", + "maxquota_empty": "Hạn ngạch tối đa cho mỗi hộp thư không được là 0.", + "mode_invalid": "Chế độ %s không hợp lệ", + "mx_invalid": "Bản ghi MX %s không hợp lệ", + "mysql_error": "Lỗi MySQL: %s", + "network_host_invalid": "Mạng hoặc máy chủ không hợp lệ: %s", + "next_hop_interferes": "%s xung đột với bước nhảy tiếp theo %s", + "next_hop_interferes_any": "Một bước nhảy tiếp theo hiện có xung đột với %s", + "nginx_reload_failed": "Tải lại Nginx thất bại: %s", + "no_user_defined": "Không có người dùng được định nghĩa", + "object_exists": "Đối tượng %s đã tồn tại", + "object_is_not_numeric": "Giá trị %s không phải là số", + "password_complexity": "Mật khẩu không đáp ứng chính sách", + "password_empty": "Mật khẩu không được để trống", + "password_mismatch": "Mật khẩu xác nhận không khớp", + "password_reset_invalid_user": "Không tìm thấy hộp thư hoặc không có email khôi phục được thiết lập", + "password_reset_na": "Tính năng khôi phục mật khẩu hiện không khả dụng. Vui lòng liên hệ quản trị viên của bạn.", + "policy_list_from_exists": "Một bản ghi với tên đã cho tồn tại", + "policy_list_from_invalid": "Bản ghi có định dạng không hợp lệ", + "private_key_error": "Lỗi khóa riêng tư: %s", + "pushover_credentials_missing": "Thiếu token hoặc khóa Pushover", + "pushover_key": "Khóa Pushover có định dạng không đúng", + "pushover_token": "Token Pushover có định dạng không đúng", + "quota_not_0_not_numeric": "Hạn ngạch phải là số và >= 0", + "recipient_map_entry_exists": "Mục ánh xạ người nhận \"%s\" đã tồn tại", + "recovery_email_failed": "Không thể gửi email khôi phục. Vui lòng liên hệ quản trị viên của bạn.", + "redis_error": "Lỗi Redis: %s", + "relayhost_invalid": "Mục ánh xạ %s không hợp lệ", + "release_send_failed": "Không thể phát hành thư: %s", + "required_data_missing": "Thiếu dữ liệu bắt buộc %s", + "reset_f2b_regex": "Không thể đặt lại bộ lọc biểu thức chính quy kịp thời, vui lòng thử lại hoặc đợi thêm vài giây và tải lại trang web.", + "reset_token_limit_exceeded": "Đã vượt quá giới hạn token đặt lại. Vui lòng thử lại sau.", + "resource_invalid": "Tên tài nguyên %s không hợp lệ", + "rl_timeframe": "Khung thời gian giới hạn tốc độ không chính xác", + "rspamd_ui_pw_length": "Mật khẩu giao diện Rspamd phải có ít nhất 6 ký tự", + "script_empty": "Tập lệnh không được để trống", + "sender_acl_invalid": "Giá trị ACL người gửi %s không hợp lệ", + "set_acl_failed": "Không thể thiết lập ACL", + "settings_map_invalid": "ID ánh xạ cài đặt %s không hợp lệ", + "sieve_error": "Lỗi phân tích cú pháp Sieve: %s", + "spam_learn_error": "Lỗi học thư rác: %s", + "subject_empty": "Tiêu đề không được để trống", + "target_domain_invalid": "Tên miền đích %s không hợp lệ", + "targetd_not_found": "Không tìm thấy tên miền đích %s", + "targetd_relay_domain": "Tên miền đích %s là tên miền chuyển tiếp", + "template_exists": "Mẫu %s đã tồn tại", + "template_id_invalid": "ID mẫu %s không hợp lệ", + "template_name_invalid": "Tên mẫu không hợp lệ", + "temp_error": "Lỗi tạm thời", + "text_empty": "Văn bản không được để trống", + "tfa_token_invalid": "Token xác thực hai yếu tố không hợp lệ", + "tls_policy_map_dest_invalid": "Đích chính sách TLS không hợp lệ", + "tls_policy_map_entry_exists": "Mục ánh xạ chính sách TLS \"%s\" đã tồn tại", + "tls_policy_map_parameter_invalid": "Tham số chính sách không hợp lệ", + "to_invalid": "Người nhận không được để trống", + "totp_verification_failed": "Xác thực TOTP thất bại", + "transport_dest_exists": "Đích vận chuyển \"%s\" đã tồn tại", + "webauthn_verification_failed": "Xác thực WebAuthn thất bại: %s", + "webauthn_authenticator_failed": "Không tìm thấy trình xác thực đã chọn", + "webauthn_publickey_failed": "Không có khóa công khai nào được lưu cho trình xác thực đã chọn", + "webauthn_username_failed": "Trình xác thực đã chọn thuộc về tài khoản khác", + "unknown": "Đã xảy ra lỗi không xác định", + "unknown_tfa_method": "Phương thức xác thực hai yếu tố không xác định", + "unlimited_quota_acl": "Hạn ngạch không giới hạn bị cấm bởi ACL", + "username_invalid": "Tên người dùng %s không thể sử dụng được", + "validity_missing": "Vui lòng gán thời hạn hiệu lực", + "value_missing": "Vui lòng cung cấp tất cả các giá trị", + "version_invalid": "Phiên bản %s không hợp lệ", + "yotp_verification_failed": "Xác thực Yubico OTP thất bại: %s" + }, + "datatables": { + "collapse_all": "Thu gọn tất cả", + "emptyTable": "Không có dữ liệu trong bảng", + "expand_all": "Mở rộng tất cả", + "info": "Hiển thị từ _START_ đến _END_ của _TOTAL_ mục", + "infoEmpty": "Hiển thị 0 đến 0 của 0 mục", + "infoFiltered": "(được lọc từ tổng số _MAX_ mục)", + "lengthMenu": "Hiển thị _MENU_ mục", + "loadingRecords": "Đang tải...", + "processing": "Vui lòng đợi...", + "search": "Tìm kiếm:", + "zeroRecords": "Không tìm thấy bản ghi phù hợp", + "paginate": { + "first": "Đầu", + "last": "Cuối", + "next": "Tiếp", + "previous": "Trước" + }, + "aria": { + "sortAscending": ": kích hoạt để sắp xếp cột tăng dần", + "sortDescending": ": kích hoạt để sắp xếp cột giảm dần" + } + }, + "debug": { + "architecture": "Kiến trúc", + "chart_this_server": "Biểu đồ (máy chủ này)", + "containers_info": "Thông tin container", + "container_running": "Đang chạy", + "container_disabled": "Container đã dừng hoặc bị vô hiệu hóa", + "container_stopped": "Đã dừng", + "cores": "Nhân CPU", + "current_time": "Thời gian hệ thống", + "disk_usage": "Sử dụng ổ đĩa", + "docs": "Tài liệu", + "error_show_ip": "Không thể phân giải địa chỉ IP công khai", + "external_logs": "Nhật ký ngoài", + "history_all_servers": "Lịch sử (tất cả máy chủ)", + "in_memory_logs": "Nhật ký trong bộ nhớ", + "last_modified": "Sửa đổi lần cuối", + "log_info": "

mailcow nhật ký trong bộ nhớ được thu thập trong danh sách Redis và được cắt giảm xuống LOG_LINES (%d) mỗi phút để giảm tải.\n
Nhật ký trong bộ nhớ không nhằm mục đích lưu trữ lâu dài. Tất cả các ứng dụng ghi nhật ký trong bộ nhớ cũng ghi vào Docker daemon và do đó vào trình điều khiển ghi nhật ký mặc định.r\n
Loại nhật ký trong bộ nhớ nên được sử dụng để gỡ lỗi các vấn đề nhỏ với các container.

\n

Nhật ký bên ngoài được thu thập thông qua API của ứng dụng đã cho.

\n

Nhật ký tĩnh chủ yếu là nhật ký hoạt động, không được ghi vào Dockerd nhưng vẫn cần được lưu trữ lâu dài (ngoại trừ nhật ký API).

", + "login_time": "Thời gian", + "logs": "Nhật ký", + "memory": "Bộ nhớ", + "online_users": "Người dùng trực tuyến", + "restart_container": "Khởi động lại", + "service": "Dịch vụ", + "show_ip": "Hiển thị IP công khai", + "size": "Kích thước", + "started_at": "Bắt đầu lúc", + "started_on": "Bắt đầu vào", + "static_logs": "Nhật ký tĩnh", + "success": "Thành công", + "system_containers": "Hệ thống & Container", + "timezone": "Múi giờ", + "uptime": "Thời gian hoạt động", + "update_available": "Có bản cập nhật mới", + "no_update_available": "Hệ thống đang ở phiên bản mới nhất", + "update_failed": "Không thể kiểm tra cập nhật", + "username": "Tên người dùng", + "wip": "Đang trong quá trình phát triển" + }, + "diagnostics": { + "cname_from_a": "Giá trị được lấy từ bản ghi A/AAAA. Điều này được hỗ trợ miễn là bản ghi trỏ đến tài nguyên chính xác.", + "dns_records": "Bản ghi DNS", + "dns_records_24hours": "Xin lưu ý rằng các thay đổi được thực hiện đối với DNS có thể mất tới 24 giờ để phản ánh chính xác trạng thái hiện tại của chúng trên trang này. Trang này nhằm giúp bạn dễ dàng xem cách cấu hình bản ghi DNS và kiểm tra xem tất cả bản ghi của bạn có được lưu trữ chính xác trong DNS hay không.", + "dns_records_data": "Dữ liệu chính xác", + "dns_records_docs": "Vui lòng tham khảo thêm tài liệu hướng dẫn.", + "dns_records_name": "Tên", + "dns_records_status": "Trạng thái hiện tại", + "dns_records_type": "Loại", + "optional": "Bản ghi này là tùy chọn." + }, + "edit": { + "acl": "ACL (Quyền hạn)", + "active": "Hoạt động", + "admin": "Chỉnh sửa quản trị viên", + "advanced_settings": "Cài đặt nâng cao", + "alias": "Chỉnh sửa bí danh", + "allow_from_smtp": "Chỉ cho phép các IP sau sử dụng SMTP", + "allow_from_smtp_info": "Để trống để cho phép tất cả người gửi.
Địa chỉ và mạng IPv4/IPv6.", + "allowed_protocols": "Các giao thức được phép truy cập trực tiếp của người dùng (không ảnh hưởng đến giao thức mật khẩu ứng dụng)", + "app_name": "Tên ứng dụng", + "app_passwd": "Mật khẩu ứng dụng", + "app_passwd_protocols": "Các giao thức được phép cho mật khẩu ứng dụng", + "automap": "Thử tự động ánh xạ thư mục (\"Mục đã gửi\", \"Đã gửi\" => \"Đã gửi\" v.v.)", + "backup_mx_options": "Tùy chọn chuyển tiếp", + "bcc_dest_format": "Đích BCC phải là một địa chỉ email hợp lệ duy nhất.
Nếu bạn cần gửi bản sao đến nhiều địa chỉ, hãy tạo một bí danh và sử dụng nó ở đây.", + "client_id": "ID khách hàng", + "client_secret": "Khóa bí mật khách hàng", + "comment_info": "Bình luận riêng tư không hiển thị với người dùng, trong khi bình luận công khai được hiển thị dưới dạng chú thích khi di chuột qua trong tổng quan người dùng", + "created_on": "Được tạo vào", + "custom_attributes": "Thuộc tính tùy chỉnh", + "delete1": "Xóa từ nguồn khi hoàn thành", + "delete2": "Xóa thư ở đích không có ở nguồn", + "delete2duplicates": "Xóa các bản sao ở đích", + "delete_ays": "Vui lòng xác nhận quá trình xóa.", + "description": "Mô tả", + "disable_login": "Không cho phép đăng nhập (vẫn nhận được thư đến)", + "domain": "Chỉnh sửa tên miền", + "domain_admin": "Chỉnh sửa quản trị viên tên miền", + "domain_footer": "Chân trang toàn tên miền", + "domain_footer_html": "Chân trang HTML", + "domain_footer_info": "Chân trang toàn tên miền được thêm vào tất cả các email gửi đi liên quan đến một địa chỉ trong tên miền này.
Các biến sau có thể được sử dụng cho chân trang:", + "domain_footer_info_vars": { + "auth_user": "{= auth_user =} - Tên người dùng đã xác thực được chỉ định bởi MTA", + "from_user": "{= from_user =} - Phần người dùng của phong bì, ví dụ \"moo@mailcow.tld\" sẽ trả về \"moo\"", + "from_name": "{= from_name =} - Tên từ phong bì, ví dụ \"Mailcow <moo@mailcow.tld>\" sẽ trả về \"Mailcow\"", + "from_addr": "{= from_addr =} - Phần địa chỉ của phong bì", + "from_domain": "{= from_domain =} - Phần tên miền của phong bì", + "custom": "{= foo =} - Nếu hộp thư có thuộc tính tùy chỉnh \"foo\" với giá trị \"bar\" sẽ trả về \"bar\"" + }, + "domain_footer_plain": "Chân trang văn bản thuần", + "domain_footer_skip_replies": "Bỏ qua chân trang trong email trả lời", + "domain_quota": "Hạn ngạch tên miền", + "domains": "Các tên miền", + "dont_check_sender_acl": "Tắt kiểm tra người gửi cho tên miền %s (+ tên miền bí danh)", + "edit_alias_domain": "Chỉnh sửa tên miền bí danh", + "encryption": "Mã hóa", + "exclude": "Loại trừ đối tượng (biểu thức chính quy)", + "extended_sender_acl": "Địa chỉ người gửi bên ngoài", + "extended_sender_acl_info": "Khóa tên miền DKIM nên được nhập vào, nếu có sẵn.
\n Nhớ thêm máy chủ này vào bản ghi SPF TXT tương ứng.
\n Khi một tên miền hoặc tên miền bí danh được thêm vào máy chủ này, mà trùng với một địa chỉ bên ngoài, địa chỉ bên ngoài sẽ bị xóa.
\n Sử dụng @domain.tld để cho phép gửi dưới dạng *@domain.tld.", + "force_pw_update": "Bắt buộc cập nhật mật khẩu trong lần đăng nhập tiếp theo", + "force_pw_update_info": "Người dùng này sẽ chỉ có thể đăng nhập vào %s. Mật khẩu ứng dụng vẫn có thể sử dụng được.", + "footer_exclude": "Loại trừ khỏi chân trang", + "full_name": "Tên đầy đủ", + "gal": "Danh sách địa chỉ toàn cục", + "gal_info": "GAL chứa tất cả các đối tượng của một tên miền và không thể được chỉnh sửa bởi bất kỳ người dùng nào. Thông tin rảnh/bận trong SOGo sẽ bị thiếu nếu vô hiệu hóa! Khởi động lại SOGo để áp dụng thay đổi.", + "generate": "tạo", + "grant_types": "Các loại cấp quyền", + "hostname": "Tên máy chủ", + "inactive": "Không hoạt động", + "internal": "Nội bộ", + "internal_info": "Bí danh nội bộ chỉ có thể truy cập từ tên miền sở hữu hoặc tên miền bí danh.", + "kind": "Loại", + "last_modified": "Sửa đổi lần cuối" } } From 22a09b9795d26021da5c706dc5b8ff038448374f Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu, 23 Oct 2025 15:16:24 +0200 Subject: [PATCH 073/109] [PHP] re-add opcache.revalidate_freq setting --- data/conf/phpfpm/php-conf.d/opcache-recommended.ini | 1 + 1 file changed, 1 insertion(+) diff --git a/data/conf/phpfpm/php-conf.d/opcache-recommended.ini b/data/conf/phpfpm/php-conf.d/opcache-recommended.ini index 452b45484..1af81b85a 100644 --- a/data/conf/phpfpm/php-conf.d/opcache-recommended.ini +++ b/data/conf/phpfpm/php-conf.d/opcache-recommended.ini @@ -7,6 +7,7 @@ opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.memory_consumption=128 opcache.save_comments=1 +opcache.revalidate_freq=1 opcache.validate_timestamps=0 ; JIT From 9a806e64cef1ab96d8ca0c4a247dc9dafb352f4b Mon Sep 17 00:00:00 2001 From: FreddleSpl0it <75116288+FreddleSpl0it@users.noreply.github.com> Date: Fri, 24 Oct 2025 08:18:49 +0200 Subject: [PATCH 074/109] [PHP] remove opcache.revalidate_freq --- data/conf/phpfpm/php-conf.d/opcache-recommended.ini | 1 - 1 file changed, 1 deletion(-) diff --git a/data/conf/phpfpm/php-conf.d/opcache-recommended.ini b/data/conf/phpfpm/php-conf.d/opcache-recommended.ini index 1af81b85a..452b45484 100644 --- a/data/conf/phpfpm/php-conf.d/opcache-recommended.ini +++ b/data/conf/phpfpm/php-conf.d/opcache-recommended.ini @@ -7,7 +7,6 @@ opcache.interned_strings_buffer=16 opcache.max_accelerated_files=10000 opcache.memory_consumption=128 opcache.save_comments=1 -opcache.revalidate_freq=1 opcache.validate_timestamps=0 ; JIT From 04200c99a4b3605c6c6bd583affdbd6343a8f5e7 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 27 Oct 2025 20:00:29 +0100 Subject: [PATCH 075/109] Translations update from Weblate (#6880) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.vi-vn.json Co-authored-by: Nguyễn Thái Dũng Co-authored-by: milkmaker * [Web] Updated lang.nb-no.json Co-authored-by: Runar Ingebrigtsen --------- Co-authored-by: Nguyễn Thái Dũng Co-authored-by: Runar Ingebrigtsen --- data/web/lang/lang.nb-no.json | 5 +++-- data/web/lang/lang.vi-vn.json | 3 ++- 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/data/web/lang/lang.nb-no.json b/data/web/lang/lang.nb-no.json index 3b267b9ea..bca608745 100644 --- a/data/web/lang/lang.nb-no.json +++ b/data/web/lang/lang.nb-no.json @@ -185,11 +185,12 @@ "protocol_access": "Endre protokolltilgang", "pushover": "Pushover", "quarantine": "Karantenehandlinger", - "quarantine_attachments": "Sett vedlegg i karantene", + "quarantine_attachments": "Se vedlegg i karantene", "quarantine_category": "Endre varslingskategori for karantene", "quarantine_notification": "Endre karantenevarslinger", "domain_desc": "Endre domenebeskrivelse", - "extend_sender_acl": "Tillat utvidelse av sender-ACL fra eksterne adresser" + "extend_sender_acl": "Tillat utvidelse av sender-ACL fra eksterne adresser", + "pw_reset": "Tillat endring av brukerpassord" }, "add": { "app_passwd_protocols": "Tillatte protokoller for app-passord", diff --git a/data/web/lang/lang.vi-vn.json b/data/web/lang/lang.vi-vn.json index 54e0b99b2..0e9e6a2c4 100644 --- a/data/web/lang/lang.vi-vn.json +++ b/data/web/lang/lang.vi-vn.json @@ -691,6 +691,7 @@ "internal": "Nội bộ", "internal_info": "Bí danh nội bộ chỉ có thể truy cập từ tên miền sở hữu hoặc tên miền bí danh.", "kind": "Loại", - "last_modified": "Sửa đổi lần cuối" + "last_modified": "Sửa đổi lần cuối", + "lookup_mx": "Đích là một biểu thức chính quy để khớp với tên MX (.*.google.com để định tuyến tất cả thư nhắm đến MX kết thúc bằng google.com qua bước nhảy này)" } } From 9912e41f787a92b6e002d98b833076d15efed0bc Mon Sep 17 00:00:00 2001 From: Josh <75700a85-1205-4740-aebf-4413a352e81b@otake.pw> Date: Mon, 3 Nov 2025 12:07:20 -0800 Subject: [PATCH 076/109] [Web] Correct order of Dansk/Danish in UI (#6887) --- data/web/inc/vars.inc.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php index f8d760081..9f3208e3d 100644 --- a/data/web/inc/vars.inc.php +++ b/data/web/inc/vars.inc.php @@ -85,7 +85,7 @@ $AVAILABLE_LANGUAGES = array( // 'ca-es' => 'Català (Catalan)', 'bg-bg' => 'Български (Bulgarian)', 'cs-cz' => 'Čeština (Czech)', - 'da-dk' => 'Danish (Dansk)', + 'da-dk' => 'Dansk (Danish)', 'de-de' => 'Deutsch (German)', 'en-gb' => 'English', 'es-es' => 'Español (Spanish)', From d3065612fd5defb91d569ca1e4b71c148235a8a4 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 3 Nov 2025 21:07:40 +0100 Subject: [PATCH 077/109] update postscreen_access.cidr (#6886) --- data/conf/postfix/postscreen_access.cidr | 71 +++--------------------- 1 file changed, 8 insertions(+), 63 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 9249520bc..3511c6ae4 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Wed Oct 1 00:21:33 UTC 2025 +# Whitelist generated by Postwhite v3.4 on Sat Nov 1 00:21:43 UTC 2025 # https://github.com/stevejenkins/postwhite/ -# 2216 total rules +# 2161 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:2800::/53 permit @@ -50,14 +50,11 @@ 8.25.194.0/23 permit 8.25.196.0/23 permit 8.36.116.0/24 permit -8.39.54.0/23 permit -8.39.54.250/31 permit 8.39.144.0/24 permit -8.40.222.0/23 permit -8.40.222.250/31 permit 12.130.86.238 permit -13.107.213.41 permit -13.107.246.41 permit +13.107.213.69 permit +13.107.246.69 permit +13.108.16.0/20 permit 13.110.208.0/21 permit 13.110.209.0/24 permit 13.110.216.0/22 permit @@ -169,7 +166,6 @@ 34.215.104.144 permit 34.218.115.239 permit 34.225.212.172 permit -34.241.242.183 permit 35.83.148.184 permit 35.155.198.111 permit 35.158.23.94 permit @@ -193,7 +189,6 @@ 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 @@ -275,7 +270,6 @@ 50.112.246.219 permit 52.1.14.157 permit 52.5.230.59 permit -52.6.74.205 permit 52.12.53.23 permit 52.13.214.179 permit 52.26.1.71 permit @@ -302,7 +296,6 @@ 52.96.91.34 permit 52.96.111.82 permit 52.96.172.98 permit -52.96.214.50 permit 52.96.222.194 permit 52.96.222.226 permit 52.96.223.2 permit @@ -341,7 +334,6 @@ 54.244.54.130 permit 54.244.242.0/24 permit 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 @@ -426,7 +418,6 @@ 65.110.161.77 permit 65.123.29.213 permit 65.123.29.220 permit -65.154.166.0/24 permit 65.212.180.36 permit 66.102.0.0/20 permit 66.119.150.192/26 permit @@ -1233,8 +1224,6 @@ 99.83.190.102 permit 103.9.96.0/22 permit 103.28.42.0/24 permit -103.84.217.238 permit -103.89.75.238 permit 103.151.192.0/23 permit 103.168.172.128/27 permit 103.237.104.0/22 permit @@ -1400,9 +1389,6 @@ 117.120.16.0/21 permit 119.42.242.52/31 permit 119.42.242.156 permit -121.244.91.48 permit -121.244.91.52 permit -122.15.156.182 permit 123.126.78.64/29 permit 124.108.96.24/31 permit 124.108.96.28/31 permit @@ -1430,6 +1416,7 @@ 128.245.248.0/21 permit 129.41.77.70 permit 129.41.169.249 permit +129.77.16.0/20 permit 129.80.5.164 permit 129.80.64.36 permit 129.80.67.121 permit @@ -1466,21 +1453,8 @@ 134.170.141.64/26 permit 134.170.143.0/24 permit 134.170.174.0/24 permit -135.84.80.0/24 permit -135.84.81.0/24 permit -135.84.82.0/24 permit -135.84.83.0/24 permit 135.84.216.0/22 permit -136.143.160.0/24 permit -136.143.161.0/24 permit -136.143.162.0/24 permit -136.143.176.0/24 permit -136.143.177.0/24 permit -136.143.178.49 permit -136.143.182.0/23 permit -136.143.184.0/24 permit -136.143.188.0/24 permit -136.143.190.0/23 permit +136.146.128.0/20 permit 136.147.128.0/20 permit 136.147.135.0/24 permit 136.147.176.0/20 permit @@ -1495,7 +1469,6 @@ 139.138.46.219 permit 139.138.57.55 permit 139.138.58.119 permit -139.167.79.86 permit 139.180.17.0/24 permit 140.238.148.191 permit 141.148.159.229 permit @@ -1618,9 +1591,6 @@ 164.152.23.32 permit 164.152.25.241 permit 164.177.132.168/30 permit -165.173.128.0/24 permit -165.173.180.250/31 permit -165.173.182.250/31 permit 166.78.68.0/22 permit 166.78.68.221 permit 166.78.69.169 permit @@ -1650,23 +1620,12 @@ 168.245.12.252 permit 168.245.46.9 permit 168.245.127.231 permit -169.148.129.0/24 permit -169.148.131.0/24 permit -169.148.138.0/24 permit -169.148.142.10 permit -169.148.142.33 permit -169.148.144.0/25 permit -169.148.144.10 permit -169.148.146.0/23 permit -169.148.175.3 permit -169.148.188.0/24 permit -169.148.188.182 permit 170.10.128.0/24 permit 170.10.129.0/24 permit 170.10.132.56/29 permit 170.10.132.64/29 permit 170.10.133.0/24 permit -172.217.32.0/20 permit +172.217.32.0/21 permit 172.253.56.0/21 permit 172.253.112.0/20 permit 173.0.84.0/29 permit @@ -1846,16 +1805,7 @@ 199.16.156.0/22 permit 199.33.145.1 permit 199.33.145.32 permit -199.34.22.36 permit 199.59.148.0/22 permit -199.67.80.2 permit -199.67.80.20 permit -199.67.82.2 permit -199.67.82.20 permit -199.67.84.0/24 permit -199.67.86.0/24 permit -199.67.88.0/24 permit -199.67.90.0/24 permit 199.101.161.130 permit 199.101.162.0/25 permit 199.122.120.0/21 permit @@ -1912,8 +1862,6 @@ 204.92.114.187 permit 204.92.114.203 permit 204.92.114.204/31 permit -204.141.32.0/23 permit -204.141.42.0/23 permit 204.216.164.202 permit 204.220.160.0/21 permit 204.220.168.0/21 permit @@ -2201,9 +2149,6 @@ 2603:1030:20e:3::23c permit 2603:1030:b:3::152 permit 2603:1030:c02:8::14 permit -2607:13c0:0001:0000:0000:0000:0000:7000/116 permit -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 From b0f5aee62867c6ae25c50617b0c5c914ed09abda Mon Sep 17 00:00:00 2001 From: milkmaker Date: Wed, 5 Nov 2025 17:37:26 +0100 Subject: [PATCH 078/109] [Web] Updated lang.pl-pl.json (#6898) Co-authored-by: Monika Bark --- data/web/lang/lang.pl-pl.json | 282 ++++++++++++++++++++++++++++++---- 1 file changed, 248 insertions(+), 34 deletions(-) diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index 02c892c64..775fd0c7f 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -1,50 +1,117 @@ { "acl": { - "sogo_profile_reset": "Usuń profil SOGo (webmail)", - "syncjobs": "Polecenie synchronizacji", + "sogo_profile_reset": "Zresetuj profil SOGo", + "syncjobs": "Zadania doryczące synchronizacji kont", "alias_domains": "Dodaj aliasy domen", - "delimiter_action": "Akcja oparta na separatorze" + "delimiter_action": "Akcja oparta na separatorze", + "app_passwds": "Zarządzaj hasłami do aplikacji", + "bcc_maps": "mapy do BCC", + "domain_desc": "Zmień opis dotyczący domeny", + "domain_relayhost": "Zmień serwer przekazujący dla tej domeny", + "eas_reset": "Resetuj urządzenia EAS", + "extend_sender_acl": "Zezwalaj na rozszerzenie listy kontroli dostępu nadawców(ACL) o adresy zewnętrzne", + "filters": "Dostępne filtry", + "login_as": "Zaloguj się jako użytkownik poczty", + "mailbox_relayhost": "Zmień serwer pocztowy(relayhost) dla skrzynki pocztowej", + "prohibited": "Zakazane przez liste kontroli dostępu(ACL)", + "protocol_access": "Zakazane przez ACL", + "pushover": "Pushover(powiadomienia push w czasie rzeczywistym)", + "pw_reset": "Zezwalaj na resetowanie hasła użytkownika mailcow", + "quarantine": "Akcje kwarantanny", + "quarantine_attachments": "Załączniki do kwarantanny", + "quarantine_category": "Zmień kategorię dotyczącą powiadomień o kwarantannie", + "quarantine_notification": "Zmień powiadomienia o kwarantannie", + "ratelimit": "Ograniczenie liczby zapytań", + "recipient_maps": "Mapy odbiorców", + "smtp_ip_access": "Zmiana dozwolonych hostów SMTP", + "sogo_access": "Zezwól na zarządzanie dostępem SOGo", + "spam_alias": "Tymczasowe aliasy", + "spam_policy": "Zablokowane adresy/Dozwolone adresy", + "spam_score": "Wskaźnik spam", + "tls_policy": "Polityka TLS", + "unlimited_quota": "Nieograniczony limit dla skrzynek pocztowych" }, "add": { "active": "Aktywny", "add": "Dodaj", - "alias_address": "Alias/y:", + "alias_address": "Alias/y", "alias_address_info": "Pełny/e adres/y email lub @example.com, aby przejąć wszystkie wiadomości dla domeny (oddzielone przecinkami). tylko domeny mailcow.", "alias_domain": "Alias domeny", "alias_domain_info": "Tylko prawidłowe nazwy domen (oddzielone przecinkami).", - "backup_mx_options": "Opcje Backup MX:", + "backup_mx_options": "Opcje Backup MX", "delete1": "Usuń ze źródła po zakończeniu", "delete2duplicates": "Usuń duplikaty w miejscu docelowym", - "description": "Opis:", + "description": "Opis", "domain": "Domena", - "domain_quota_m": "Łączny limit domeny (MiB):", + "domain_quota_m": "Łączny limit domeny (MiB)", "enc_method": "Metoda szyfrowania", "exclude": "Wyklucz obiekty (regex)", - "full_name": "Pełna nazwa:", + "full_name": "Pełna nazwa", "hostname": "Nazwa hosta", "kind": "Rodzaj", - "mailbox_quota_m": "Maks. wielkość skrzynki (MiB):", - "mailbox_username": "Nazwa użytkownika (lewa strona adresu email):", - "max_aliases": "Maks. liczba aliasów:", - "max_mailboxes": "Maks. liczba skrzynek:", + "mailbox_quota_m": "Maks. wielkość skrzynki (MiB)", + "mailbox_username": "Nazwa użytkownika (lewa strona adresu email)", + "max_aliases": "Maks. liczba aliasów", + "max_mailboxes": "Maks. liczba skrzynek", "mins_interval": "Zakres pobierania (minuty)", "multiple_bookings": "Wielokrotne rejestracje", - "password": "Hasło:", - "password_repeat": "Potwierdź hasło(powtórz):", + "password": "Hasło", + "password_repeat": "Potwierdź hasło(powtórz)", "port": "Port", - "post_domain_add": "Po dodaniu nowej domeny będziesz musiał ponownie uruchomić kontener serwisowy SOGo!", - "quota_mb": "Limit wielkości (MiB):", + "post_domain_add": "Kontener SOGo, \"sogo-mailcow\", musi zostać ponownie uruchomiony po dodaniu nowej domeny!

Dodatkowo należy przejrzeć konfigurację DNS domeny. Po zatwierdzeniu konfiguracji DNS uruchom ponownie \"acme-mailcow\", aby automatycznie wygenerować certyfikaty dla nowej domeny (autoconfig.<domain>, autodiscover.<domain>).
Ten krok jest opcjonalny i będzie ponownie wykonywany co 24 godziny.", + "quota_mb": "Limit wielkości (MiB)", "relay_all": "Przekaż wszystkim odbiorcom", - "relay_all_info": "Jeśli decydujesz się nie przekazywać wszystkim odbiorcom, musisz dodać (\"ślepą\")skrzynkę dla każdego poszczególnego odbiorcy, któremu należy przekazać.", + "relay_all_info": "↪Jeśli wybierzesz not, aby przekazać wszystkich odbiorców, musisz dodać (\"ślepą\") skrzynkę pocztową dla każdego pojedynczego odbiorcy, która powinna być przekazywana.", "relay_domain": "Domena przekaźnikowa", "select": "Proszę wybrać...", "select_domain": "Proszę najpierw wybrać domenę", "syncjob": "Dodaj polecenie synchronizacji", "syncjob_hint": "Pamiętaj, że hasła należy zapisywać w zwykłym tekście!", - "target_address": "Adresy Idź do:", + "target_address": "Adresy Idź do", "target_address_info": " Pełny/e adres/y email (oddzielone przecinkami).", - "target_domain": "Domena docelowa:", - "username": "Nazwa użytkownika" + "target_domain": "Domena docelowa", + "username": "Nazwa użytkownika", + "activate_filter_warn": "Wszystkie pozostałe filtry zostaną wyłączone, gdy opcja active zostanie zaznaczona.", + "add_domain_only": "Dodaj wyłącznie domene", + "add_domain_restart": "Dodaj domenę i uruchom ponownie SOGo", + "app_name": "Nazwa aplikacji", + "app_password": "Dodaj hasło do aplikacji", + "app_passwd_protocols": "Dozwolone protokoły dla hasła aplikacji", + "automap": "Spróbuj automatycznie mapować foldery (\"Wysłane elementy\", \"Wysłane\" => \"Wysłane\" itp.)", + "bcc_dest_format": "Miejscem docelowym BCC musi być jeden prawidłowy adres e-mail.
Jeśli chcesz wysłać kopię do wielu adresów, utwórz alias i użyj go tutaj.", + "comment_info": "Prywatny komentarz nie jest widoczny dla użytkownika, podczas gdy publiczny komentarz jest wyświetlany jako podpowiedź, które pojawia się, gdy użytkownik najedzie myszką nad elementem", + "custom_params": "Niestandardowe parametry", + "custom_params_hint": "Właściwa: --param=xy, błędna: --param xy", + "delete2": "Usuń wiadomości w miejscu docelowym, które nie znajdują się w źródle", + "destination": "Miejsce docelowe", + "disable_login": "Nie pozwalaj na logowanie(poczta przychodząca jest nadal akceptowana)", + "domain_matches_hostname": "Domena %s pasuje do nazwy hosta", + "dry": "Symulacja synchronizacji", + "gal": "Globalna lista adresów", + "gal_info": "GAL zawiera wszystkie obiekty domeny i nie może być edytowany przez żadnego użytkownika. Wolne/zajęte logi w SOGo bedą nidostępne, jeśli są wyłączone! Uruchom ponownie SOGo, aby zastosować zmiany.", + "generate": "generuj", + "goto_ham": "Ucz się jako ham", + "goto_null": "Odrzucaj pocztę \"po cichu\"", + "goto_spam": "Ucz się jako spam", + "inactive": "Nieaktywny", + "internal": "Wewnętrzny", + "internal_info": "Aliasy wewnętrzne są dostępne tylko z domeny własnej lub domeny aliasów.", + "mailbox_quota_def": "Domyślny przydział skrzynki pocztowej", + "nexthop": "Następny hop", + "private_comment": "Prywatny komentarz", + "public_comment": "Komentarz publiczny", + "relay_transport_info": "
Info
Możesz transports maps dla niestandardowego miejsca docelowego dla tej domeny. Jeśli nie jest ustawiony, zostanie aktywowany lookup MX.", + "relay_unknown_only": "Przekaż tylko nieistniejące skrzynki pocztowe. Istniejące skrzynki pocztowe będą dostarczane lokalnie.", + "relayhost_wrapped_tls_info": "Proszę nie używać portów owiniętych TLS (głównie używanych na porcie 465).
\nUżyj dowolnego portu niezawiniętego i uruchom STARTTLS. Polityka TLS w celu egzekwowania TLS może być utworzona w \"mapie zasad TLS\".", + "sieve_desc": "Krótki opis", + "sieve_type": "Typ filtra", + "skipcrossduplicates": "Pomiń duplikaty wiadomości w folderach (na zasadzie kolejności zgłoszeń)", + "subscribeall": "Subskrybuj wszystkie foldery", + "tags": "Tagi", + "timeout1": "Limit czasu połączenia z hostem zdalnym", + "timeout2": "Limit czasu połączenia dla lokalnego hosta", + "validate": "Zatwierdź", + "validation_success": "Zatwierdzone z powodzeniem" }, "admin": { "access": "Dostęp", @@ -100,7 +167,136 @@ "spamfilter": "Filtr spamu", "time": "Czas", "unchanged_if_empty": "W przypadku braku zmian, nie wypełniaj", - "username": "Nazwa użytkownika" + "username": "Nazwa użytkownika", + "activate_api": "Aktywuj API", + "activate_send": "Aktywuj przycisk wysyłania", + "active_rspamd_settings_map": "Aktywne ustawienia mapy", + "add_admin": "Dodaj administratora", + "add_relayhost": "Dodaj transport zależny od nadawcy", + "add_relayhost_hint": "Miej na uwadze, że dane uwierzytelniające, jeśli takie istnieją, będą przechowywane w postaci zwykłego tekstu", + "add_row": "Dodaj wiersz", + "add_settings_rule": "Dodaj regułę ustawień", + "add_transport": "Dodaj transport", + "add_transports_hint": "Należy pamiętać, że dane uwierzytelniające, jeśli takie istnieją, będą przechowywane jako zwykły tekst.", + "additional_rows": " Dodano kolejne rzędy", + "admins": "Administratorzy", + "admins_ldap": "Administratorzy LDAP", + "admin_quicklink": "Ukryj szybki link do strony logowania administratora", + "advanced_settings": "Ustawienia zaawansowane", + "allowed_methods": "Dostęp-kontrola-zezwolenie-metody", + "allowed_origins": "Dostęp-Kontrola-Zezwolenia-Pochodzenie", + "api_allow_from": "Zezwalaj na dostęp API z tych notacji sieciowych IP/CIDR", + "api_info": "API jest w trakcie prac. Dokumentację można znaleźć pod adresem /api", + "api_key": "klucz API", + "api_read_only": "Dostęp tylko do odczytu", + "api_read_write": "Dostęp tylko do odczytu", + "api_skip_ip_check": "Pomiń sprawdzenie IP dla API", + "app_hide": "Ukryj dla logowania", + "app_links": "Linki aplikacji", + "app_name": "Nazwa aplikacji", + "apps_name": "Nazwa \"aplikacji mailcow\"", + "arrival_time": "Czas serwera", + "authed_user": "Autoryzowany użytkownik", + "ays": "Jesteś pewien, że chcesz kontynuować?", + "ban_list_info": "Zobacz listę zakazanych adresów IP poniżej: network (pozostały czas zakazu) - [działania].
IP kolejkowane do odbanowania zostaną usunięte z listy aktywnych zakazów w ciągu kilku sekund.
Czerwone etykiety wskazują aktywny stałe zakazy poprzez odmowę wpisu.", + "change_logo": "Zmień logo", + "logo_normal_label": "Normalna", + "logo_dark_label": "Odwrócony dla trybu ciemnego", + "convert_html_to_text": "Konwertuj HTML na zwykły tekst", + "copy_to_clipboard": "Tekst skopiowany do schowka!", + "cors_settings": "Ustawienia CORS", + "credentials_transport_warning": "Ostrzeżenie: Dodanie nowego wpisu mapy transportu spowoduje aktualizację danych uwierzytelniających dla wszystkich wpisów z pasującą kolumną hop.", + "customer_id": "Identyfikator klienta", + "customize": "Dostosuj", + "login_page": "Strona logowania", + "destination": "Miejsce docelowe", + "dkim_domains_selector": "Selektor", + "dkim_domains_wo_keys": "Wybierz domeny z brakującymi kluczami", + "dkim_from": "Od", + "dkim_from_title": "Domena źródłowa do kopiowania danych z", + "dkim_overwrite_key": "Nadpisanie istniejącego klucza DKIM", + "dkim_to": "Do", + "dkim_to_title": "Domeny docelowe - zostaną nadpisane", + "domain_admin": "Administrator domeny", + "domainadmin_quicklink": "Ukryj szybki link do strony logowania administratora domeny", + "domain_s": "Domena/y", + "duplicate": "Duplikat", + "duplicate_dkim": "Duplikat rekordu DKIM", + "excludes": "Wyklucza tych odbiorców", + "f2b_ban_time_increment": "Czas zakazu jest zwiększany z każdym zakazem", + "f2b_blacklist": "Lista odrzuconych sieci/hostów", + "f2b_filter": "Filtry Regex", + "f2b_list_info": "Odrzucony host lub sieć zawsze będzie przewyższać jednostkę zezwalającą.Zastosowanie aktualizacji listy zajmie kilka sekund.", + "f2b_manage_external": "Zarządzaj Fail2Ban zewnętrznie", + "f2b_manage_external_info": "Fail2ban nadal będzie utrzymywać listę banów, ale nie będzie aktywnie ustalać zasad blokowania ruchu. Użyj wygenerowane listy banów poniżej, aby zewnętrznie zablokować ruch.", + "f2b_max_ban_time": "Max. czas bana (s)", + "f2b_netban_ipv4": "Rozmiar podsieci IPv4 do zastosowania zakazu (8-32)", + "f2b_netban_ipv6": "Rozmiar podsieci IPv6 do zastosowania zakazu (8-128)", + "f2b_regex_info": "Logi brane pod uwagę: SOGo, Postfix, Dovecot, PHP-FPM.", + "filter": "Filtr", + "force_sso_text": "Jeśli skonfigurowany jest zewnętrzny dostawca OIDC, ta opcja ukrywa domyślne formularze logowania mailcow i pokazuje tylko przycisk logowania pojedynczego", + "force_sso": "Wyłącz logowanie mailcow i pokaż tylko pojedyncze logowanie", + "from": "Od", + "generate": "Generuj", + "guid": "GUID - unikalny identyfikator instancji", + "guid_and_license": "GUID & licencja", + "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.
\n\nKażdy hash jest oznaczony indywidualnym kolorem.", + "help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)", + "html": "HTML", + "iam": "Dostawca tożsamości", + "iam_attribute_field": "Pole atrybutów", + "iam_authorize_url": "Punkt końcowy autoryzacji", + "iam_auth_flow": "Przepływ uwierzytelniania", + "iam_auth_flow_info": "Oprócz przepływu kodu autoryzacyjnego (Standardowy przepływ w Keycloak), który służy do logowania jednokrotnego logowania, mailcow obsługuje również przepływ uwierzytelniania z bezpośrednimi poświadczeniami. Mailpassword Flow próbuje zweryfikować dane uwierzytelniające użytkownika za pomocą Keycloak Admin REST API. mailcow pobiera hashowane hasło z atrybutu mailcow_password, który jest mapowany w Keycloak.", + "iam_basedn": "Baza DN", + "iam_client_id": "ID klienta", + "iam_client_secret": "Sekret klienta", + "iam_client_scopes": "Zakresy klientów", + "iam_default_template": "Domyślny szablon", + "iam_default_template_description": "Jeśli użytkownikowi nie zostanie przypisany żaden szablon, domyślny szablon zostanie użyty do utworzenia skrzynki pocztowej, ale nie do aktualizacji skrzynki pocztowej.", + "iam_description": "Skonfiguruj zewnętrznego dostawce uwierzytelniania
Skrzynki pocztowe użytkownika zostaną automatycznie utworzone przy pierwszym logowaniu, pod warunkiem, że zostało ustawione mapowanie atrybutów.", + "iam_extra_permission": "Aby następujące ustawienia działały, klient mailcow w Keycloak potrzebuje konta serwisowego oraz uprawnień do podgląd-użytkowników.", + "iam_host": "Host", + "iam_host_info": "Wprowadź jeden lub więcej hostów LDAP, oddzielonych przecinkami.", + "iam_import_users": "Zaimportuj użytkowników", + "iam_login_provisioning": "Automatyczne tworzenie użytkowników przy logowaniu", + "iam_mapping": "Mapowanie atrybutów", + "iam_bindpass": "Powiąż hasło", + "iam_periodic_full_sync": "Okresowa pełna synchronizacja", + "iam_port": "Port", + "iam_realm": "Realm", + "iam_redirect_url": "Przekierowanie Url", + "iam_rest_flow": "Mailpassword Flow", + "iam_server_url": "Adres URL serwera", + "iam_sso": "Pojedyncze logowanie", + "iam_sync_interval": "Interwał synchronizacji / importu (min)", + "iam_test_connection": "Test połączenia", + "iam_token_url": "Tokenowy punkt końcowy", + "iam_userinfo_url": "Endpoint informacji o użytkowniku", + "iam_username_field": "Pole nazwy użytkownika", + "iam_binddn": "Powiąź DN", + "iam_use_ssl": "Używaj SSL", + "iam_use_ssl_info": "Jeśli włączysz SSL, a port zostanie ustawiony na 389, zostanie automatycznie nadpisany, aby użyć 636.", + "iam_use_tls": "Używaj StartTLS", + "iam_use_tls_info": "Jeśli włączono TLS, należy użyć domyślnego portu dla serwera LDAP (389). Nie można używać portów SSL.", + "iam_version": "Wersja", + "ignore_ssl_error": "Ignoruj błędy SSL", + "in_use_by": "W użyciu przez", + "include_exclude": "Uwzględnij/Nie uwzględniaj", + "include_exclude_info": "Domyślnie - bez zaznaczenia - wszystkie skrzynki pocztowe są adresowane", + "includes": "Uwzględnij tych odbiorców", + "ip_check": "Sprawdź IP", + "ip_check_disabled": "Sprawdzenie IP jest wyłączone. Możesz go włączyć w obszarze
System > Konfiguracja > Opcje > Dostosuj", + "ip_check_opt_in": "Opt-In korzystania z usług stron trzecich ipv4.mailcow.email i ipv6.mailcow.email w celu rozwiązania zewnętrznych adresów IP.", + "is_mx_based": "Bazuje na MX", + "last_applied": "ostatnio zastosowany", + "license_info": "Licencja nie jest wymagana, ale pomaga w dalszym rozwoju.
Zarejestruj swój GUID tutaj lub kup wsparcie dla instalacji mailcow.", + "link": "Link", + "login_time": "Cześć logowania", + "logo_info": "Twój obraz zostanie przeskalowany do wysokości 40px dla górnego paska nawigacyjnego i max. szerokości 250px dla strony startowej. Zalecana jest skalowalna grafika.", + "recipients": "Odbiorcy", + "send": "Wyślij", + "sender": "Nadawca" }, "danger": { "access_denied": "Odmowa dostępu lub nieprawidłowe dane w formularzu", @@ -146,7 +342,8 @@ "target_domain_invalid": "Domena Idź do jest nieprawidłowa", "targetd_not_found": "Nie znaleziono domeny docelowej", "username_invalid": "Nie można użyć nazwy użytkownika", - "validity_missing": "Proszę wyznaczyć termin ważności" + "validity_missing": "Proszę wyznaczyć termin ważności", + "to_invalid": "Pole odbiorca nie może być puste" }, "edit": { "active": "Aktywny", @@ -191,13 +388,14 @@ "target_domain": "Domena docelowa", "title": "Edytuj obiekt", "unchanged_if_empty": "Jeżli bez zmian, nie wypełniaj", - "username": "Nazwa użytkownika" + "username": "Nazwa użytkownika", + "delete_ays": "Proszę o potwierdzenie procesu usuwania." }, "footer": { "cancel": "Anuluj", "confirm_delete": "Potwierdź usunięcie", "delete_now": "Usuń teraz", - "delete_these_items": "Czy jesteś pewien, że chcesz usunąć następujące elementy?", + "delete_these_items": "Proszę potwierdzić zmiany w poniższym identyfikatorze obiektu", "loading": "Proszę czekać...", "restart_now": "Uruchom ponownie teraz" }, @@ -216,7 +414,14 @@ "delayed": "Logowanie zostało opóźnione o %s sekund.", "login": "Zaloguj się", "password": "Hasło", - "username": "Nazwa użytkownika" + "username": "Nazwa użytkownika", + "forgot_password": "Zapomniałeś hasła?", + "login_linkstext": "Login nieprawidłowy?", + "login_usertext": "Zaloguj się jako użytkownik", + "login_domainadmintext": "Zaloguj się jako administrator domeny", + "login_admintext": "Zaloguj się jako admin", + "other_logins": "lub zaloguj za pomocą", + "email": "Adres e-mail" }, "mailbox": { "action": "Działanie", @@ -284,10 +489,15 @@ "quarantine": "Kwarantanna", "quick_actions": "Szybkie działania", "remove": "Usuń", - "toggle_all": "Zaznacz wszystkie" + "toggle_all": "Zaznacz wszystkie", + "confirm_delete": "Potwierdź usunięcie tego elementu.", + "learn_spam_delete": "Zapamiętaj jako spam i usuwaj w przyszłości", + "quick_delete_link": "Otwórz szybki link do usuwania" }, "queue": { - "queue_manager": "Queue Manager" + "queue_manager": "Menedżer kolejki", + "delete": "Usuń wszystko", + "ays": "Potwierdź, że chcesz usunąć wszystkie elementy z bieżącej kolejki." }, "start": { "help": "Pokaż/Ukryj panel pomocy", @@ -298,7 +508,7 @@ "alias_added": "Alias/y został/y dodany/e", "alias_domain_removed": "Usunięto alias domeny %s", "alias_modified": "Zapisano zmiany w aliasie/ach %s", - "alias_removed": "Usunięto alias %s ", + "alias_removed": "Usunięto alias %s", "aliasd_added": "Dodano alias domeny %s", "aliasd_modified": "Zapisano zmiany w aliasie domeny %s", "dkim_added": "Klucz DKIM został zapisany", @@ -314,7 +524,7 @@ "forwarding_host_added": "Dodano hosta przekazującego %s", "forwarding_host_removed": "Usunięto hosta przekazującego %s", "item_deleted": "", - "items_deleted": "Item %s successfully deleted", + "items_deleted": "Elementy %s skutecznie usunięte", "mailbox_added": "Dodano skrzynkę %s", "mailbox_modified": "Zapisano zmiany w skrzynce %s", "mailbox_removed": "Usunięto skrzynkę %s", @@ -340,7 +550,7 @@ "totp": "Time-based OTP (Google Authenticator itd.)", "webauthn": "Uwierzytelnianie WebAuthn", "waiting_usb_auth": "Czekam na urządzenie USB...

Wciśnij teraz przycisk na urządzeniu WebAuthn USB.", - "waiting_usb_register": " Czekam na urządzenie USB...

Wprowadź swoje hasło powyżej i potwierdź rejestrację WebAuthn przez naciśnięcie przycisku na urządzeniu WebAuthn USB.", + "waiting_usb_register": " Czekam na urządzenie USB...

Wprowadź swoje hasło powyżej i potwierdź rejestrację przez naciśnięcie przycisku na urządzeniu USB.", "yubi_otp": "Uwierzytelnianie Yubico OTP" }, "user": { @@ -379,7 +589,7 @@ "interval": "Zakres", "is_catch_all": "Funkcja catch-all dla domen/y", "last_run": "Ostatnie uruchomienie", - "mailbox_details": " Szczegóły skrzynki", + "mailbox_details": "Szczegóły", "messages": "wiadomości", "never": "Nigdy", "new_password": "Nowe hasło", @@ -398,10 +608,10 @@ "sogo_profile_reset_now": "Usuń profil teraz", "spam_aliases": "Tymczasowy alias email", "spamfilter": "Filtr spamu", - "spamfilter_behavior": "Rating", + "spamfilter_behavior": "Ocena", "spamfilter_bl": "Czarna lista", "spamfilter_bl_desc": "Adresy email z czarnej listy zawsze klasyfikuj jako spam i odrzucaj. Można użyć wildcards.", - "spamfilter_default_score": "Wartości domyślne:", + "spamfilter_default_score": "Wartości domyślne", "spamfilter_green": "Zielony: ta wiadomość nie jest spamem", "spamfilter_hint": "Pierwsza wartość oznacza \"niską punktację spam\", druga wartość oznacza \"wysoką punktację spam\".", "spamfilter_red": "Czerwony: ta wiadomość jest spamem i zostanie odrzucona przez serwer", @@ -429,6 +639,10 @@ "username": "Nazwa użytkownika", "week": "Tydzień", "weekly": "Co tydzień", - "weeks": "Tygodnie" + "weeks": "Tygodnie", + "q_add_header": "Spam" + }, + "warning": { + "session_ua": "Nieprawidłowy token formularza: Błąd walidacji User-Agent" } } From 07d7e3dc30d00f4d43327f18089ec3e1c3fbdd5e Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sun, 9 Nov 2025 23:03:00 +0100 Subject: [PATCH 079/109] [Web] Updated lang.pl-pl.json (#6906) [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json Co-authored-by: Monika Bark --- data/web/lang/lang.pl-pl.json | 496 ++++++++++++++++++++++++++++++++-- 1 file changed, 468 insertions(+), 28 deletions(-) diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index 775fd0c7f..4d68d0dd0 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -2,10 +2,10 @@ "acl": { "sogo_profile_reset": "Zresetuj profil SOGo", "syncjobs": "Zadania doryczące synchronizacji kont", - "alias_domains": "Dodaj aliasy domen", + "alias_domains": "Dodaj domeny aliasowe", "delimiter_action": "Akcja oparta na separatorze", "app_passwds": "Zarządzaj hasłami do aplikacji", - "bcc_maps": "mapy do BCC", + "bcc_maps": "Mapy BCC", "domain_desc": "Zmień opis dotyczący domeny", "domain_relayhost": "Zmień serwer przekazujący dla tej domeny", "eas_reset": "Resetuj urządzenia EAS", @@ -14,7 +14,7 @@ "login_as": "Zaloguj się jako użytkownik poczty", "mailbox_relayhost": "Zmień serwer pocztowy(relayhost) dla skrzynki pocztowej", "prohibited": "Zakazane przez liste kontroli dostępu(ACL)", - "protocol_access": "Zakazane przez ACL", + "protocol_access": "Zmień dostęp do protokołów", "pushover": "Pushover(powiadomienia push w czasie rzeczywistym)", "pw_reset": "Zezwalaj na resetowanie hasła użytkownika mailcow", "quarantine": "Akcje kwarantanny", @@ -296,7 +296,122 @@ "logo_info": "Twój obraz zostanie przeskalowany do wysokości 40px dla górnego paska nawigacyjnego i max. szerokości 250px dla strony startowej. Zalecana jest skalowalna grafika.", "recipients": "Odbiorcy", "send": "Wyślij", - "sender": "Nadawca" + "sender": "Nadawca", + "lookup_mx": "Destynacja jest regularnym wyrażeniem, które pasuje do nazwy MX (.*\\\\.google\\.com, aby przekierować całą pocztę skierowaną do MX kończącego się na google.com w tym hopie)", + "main_name": "Nazwa \"mailcow UI\"", + "merged_vars_hint": "Wyszarzone wiersze zostały połączone z vars. (local.) inc.php i nie można ich modyfikować.", + "message_size": "Rozmiar wiadomości", + "nexthop": "Następny hop", + "needs_restart": "potrzebny restart", + "no": "✕", + "no_active_bans": "Brak aktywnych banów", + "no_new_rows": "Brak dostępnych kolejnych wierszy", + "oauth2_apps": "Aplikacje OAuth2", + "oauth2_add_client": "Dodaj klienta OAuth2", + "oauth2_client_id": "ID klienta", + "oauth2_client_secret": "Sekret klienta", + "oauth2_info": "Implementacja OAuth2 obsługuje typ grantu \"Kod autoryzacji\" i wydaje tokeny odświeżania.
\nSerwer automatycznie wydaje również nowe tokeny odświeżania, po użyciu tokena odświeżania.

\n• Domyślnym zakresem jest profil. Tylko użytkownicy skrzynek pocztowych mogą być uwierzytelniani w OAuth2. Jeśli parametr zakresu zostanie pominięty, wraca do profil.
\n\nParametr state musi zostać wysłany przez klienta w ramach żądania autoryzacji.

>\nŚcieżki zapytań do API OAuth2:
\n
    \nPunkt końcowy autoryzacji: /autoryzuj\nPunkt końcowy tokena: /autoth/token\nStrona zasobów: /prawo/profil>\n
\nRegeneracja tajemnicy klienta nie spowoduje wygaśnięcia istniejących kodów autoryzacyjnych, ale nie odnowi ich tokena.

\nOdwołanie tokenów klienta spowoduje natychmiastowe zakończenie wszystkich aktywnych sesji. Wszyscy klienci muszą się ponownie uwierzytelnić.", + "oauth2_redirect_uri": "Przekieruj URI", + "oauth2_renew_secret": "Wygeneruj sekret nowego klienta", + "oauth2_revoke_tokens": "Unieważnij wszystkie tokeny klienta", + "optional": "Opcjonalny", + "options": "Opcje", + "password_length": "Długość hasła", + "password_policy": "Polityka haseł", + "password_policy_chars": "Musi zawierać co najmniej jeden znak alfabetyczny", + "password_policy_length": "Minimalna długość hasła to %d", + "password_policy_lowerupper": "Musi zawierać małe i duże litery", + "password_policy_numbers": "Musi zawierać co najmniej jeden numer", + "password_policy_special_chars": "Musi zawierać znaki specjalne", + "password_reset_info": "Jeśli nie jest udostępniony e-mail zapasowy, ta funkcja nie może być używana.", + "password_reset_settings": "Ustawienia odzyskiwania haseł", + "password_reset_tmpl_html": "Szablon HTML", + "password_reset_tmpl_text": "Szablon tekstu", + "password_settings": "Ustawienia hasła", + "quarantine_bcc": "Wyślij kopię wszystkich powiadomień (BCC) do tego odbiorcy:
Pozostaw pustą aby wyłączyć. Niepodpisana, niezaznaczona poczta. Powinna być dostarczana tylko wewnętrznie.", + "quarantine_exclude_domains": "Wyklucz domeny i domeny aliasowe", + "quarantine_max_age": "Maksymalny wiek w dniach
Wartość musi być równa lub większa niż 1 dzień.", + "quarantine_max_score": "Odrzuć powiadomienie, jeśli wskaźnik spamu wiadomości jest wyższy niż ta wartość:
Domyślne do 9999.0", + "quarantine_max_size": "Maksymalny rozmiar w MiB (większe elementy są odrzucane):
0 oznacza, że nie oznacza nieograniczony.", + "quarantine_notification_html": "Szablon wiadomości e-mail z powiadomieniem:
Pozostaw puste, aby przywrócić szablon domyślny.", + "quarantine_notification_sender": "Powiadomienie nadawcy wiadomości e-mail", + "quarantine_notification_subject": "Powiadomienie E-mail Temat", + "quarantine_redirect": "Przekieruj wszystkie powiadomienia do tego odbiorcy:
Pozostaw pusty aby wyłączyć. Niepodpisana, niezaznaczona poczta. Powinny być dostarczane tylko wewnętrznie.", + "quarantine_release_format": "Format zwolnionych przedmiotów", + "quarantine_release_format_att": "Jako załącznik", + "quarantine_release_format_raw": "Niezmodyfikowany oryginał", + "quarantine_retention_size": "Retencje na skrzynkę pocztową:
0 oznacza nieaktywne.", + "quicklink_text": "Pokaż lub ukryj szybkie linki do innych stron logowania pod formularzem logowania", + "quota_notification_html": "Szablon wiadomości e-mail z powiadomieniem:
Pozostaw puste, aby przywrócić szablon domyślny.", + "quota_notification_sender": "Powiadomienie nadawcy wiadomości e-mail", + "quota_notification_subject": "Temat powiadomienia e-mail", + "quota_notifications": "Powiadomienia o limitach", + "quota_notifications_info": "Powiadomienia o limktach są wysyłane do użytkowników raz przy przekroczaniu 80% i raz przy przekraczaniu 95% zużycia.", + "quota_notifications_vars": "{{percent}} równa się aktualnemu limitowi użytkownika
{{username}} jest nazwą skrzynki pocztowej", + "queue_unban": "Zdejmij bana", + "rate_name": "Nazwa oceny", + "regen_api_key": "Regeneruj klucz API", + "regex_maps": "Mapy Regex", + "relay_from": "\"Od:\" adres", + "relay_rcpt": "\"Do:\"Adres", + "relay_run": "Uruchom test", + "relayhosts": "Transporty zależne od nadawcy", + "relayhosts_hint": "Zdefiniuj transporty zależne od nadawcy, aby móc wybrać je w oknie dialogowym konfiguracji domeny.
\nUsługa transportu jest zawsze \"smtp:\" i dlatego uruchomj TLS, gdy będzie oferowana. Owinięty TLS (SMTPS) nie jest obsługiwany. Pod uwagę brane jest indywidualne ustawienie polityki wychodzącej TLS użytkownika.
\nDotyczy wybranych domen, w tym domen aliasowych.", + "remove_row": "Usuń wiersz", + "reset_default": "Zresetuj do ustawień domyślnych", + "reset_limit": "Usuń hash", + "reset_password_vars": "{{link}} Wygenerowany link do resetu hasła
{{username}} Nazwa skrzynki pocztowej użytkownika, który poprosił o zresetowanie hasła
{{username2}} Nazwa skrzynki pocztowej do odzyskiwania
{{date}} Data złożenia żądania resetowania hasła
{{token_lifetime}}Żywotność tokena w minutach
{{hostname}} Nazwa hosta mailcow", + "restore_template": "Pozostaw puste, aby przywrócić szablon domyślny.", + "routing": "Routing", + "rsetting_add_rule": "Dodaj regułę", + "rsetting_content": "Zawartość reguły", + "rsetting_desc": "Krótki opis", + "rsetting_no_selection": "Proszę zaznaczyć regułę", + "rsetting_none": "Brak dostępnych reguł", + "rsettings_insert_preset": "Wstaw przykład presetowany \"%s\"", + "rsettings_preset_1": "Wyłącz wszystkie z wyjątkiem DKIM i limitu stawek dla uwierzytelnionych użytkowników", + "rsettings_preset_2": "Administratorzy poczty pozwalają na spam", + "rsettings_preset_3": "Zezwalaj tylko określonym nadawcom na skrzynkę pocztową (tj. używaj tylko jako wewnętrznej skrzynki pocztowej)", + "rsettings_preset_4": "Wyłącz Rspamd dla domeny", + "rspamd_com_settings": "Nazwa ustawienia zostanie automatycznie wygenerowana, zobacz przykładowe ustawienia wstępne poniżej. Aby uzyskać więcej informacji, zobacz Rspamd docs", + "rspamd_global_filters": "Globalne mapy filtrów", + "rspamd_global_filters_agree": "Będę ostrożny!", + "rspamd_global_filters_info": "Globalne mapy filtrów zawierają różne rodzaje globalnych list dozwolonych i zablokowanych adresów.", + "rspamd_global_filters_regex": "Ich imiona wyjaśniają ich cel. Cała zawartość musi zawierać ważne wyrażenie regularne w formacie \"/pattern/options\" (e.g. /.+@domain\\.tld/i).
\nChociaż podstawowe kontrole są wykonywane na każdej linii regex, funkcja Rspamd może zostać złamana, jeśli nie odczyta poprawnie składni.
>\nRspamd po zmianie spróbuje odczytać zawartość mapy. Jeśli wystąpią problemy, restart Rspamd, aby wymusić ponowne ładowanie mapy.
Elementy z listy odrzuconych są wyłączone z kwarantanny.", + "rspamd_settings_map": "Mapa ustawień Rspamd", + "sal_level": "Poziom Moo", + "service": "Usługa", + "service_id": "Id usługi", + "subject": "Temat", + "success": "Sukces", + "sys_mails": "Maile systemowe", + "task": "Zadanie", + "text": "Tekst", + "title": "Tytuł", + "title_name": "Tytuł strony internetowej \"mailcow UI\"", + "to_top": "Powrót na górę", + "transport_dest_format": "Regex lub syntax: example.org, .example.org, *, box@example.org\n(wiele wartości można rozdzielić przecinkami)", + "transport_maps": "Mapy transportu", + "transport_test_rcpt_info": "• Użyj null@hosted.mailcow.de aby przetestować przekazywanie do nieznanego miejsca docelowego.", + "transports_hint": "• Wpis mapy transportowej overrules mapa transportowa zależna od nadawcy
.
\nNajlepiej stosować transporty oparte na MX •.
\nUstawienia zasad Outbound TLS dotyczące użytkownika są ignorowane i mogą być egzekwowane tylko przez wpisy mapy zasad TLS\n• Usługa transportu dla zdefiniowanych transportów jest zawsze \"smtp:\" i dlatego uruchomi TLS, gdy będzie oferowana. Wrapped TLS (SMTPS) nie jest obsługiwany.
\nAdresy pasujące do \"/localhost$/\" będą zawsze transportowane przez \"lokalne:\", dlatego miejsce docelowe \"*\" nie będzie miało zastosowania do tych adresów.
\n• Aby określić poświadczenia dla przykładowego następnego hopa \"[host]:25\", Postfix zawsze kolejkuje zapytania o \"host\" przed wyszukaniem \"[host]:25\". Takie zachowanie uniemożliwia jednoczesne użycie \"host\" i \"[host]:25.", + "ui_footer": "Stopka (dozwolone HTML)", + "ui_header_announcement": "Ogłoszenia", + "ui_header_announcement_active": "Ustaw ogłoszenie jako aktywne", + "ui_header_announcement_content": "Tekst (dozwolony HTML)", + "ui_header_announcement_help": "Ogłoszenie jest widoczne dla wszystkich zalogowanych użytkowników oraz na ekranie logowania interfejsu użytkownika.", + "ui_header_announcement_select": "Wybierz typ ogłoszenia", + "ui_header_announcement_type": "Typ", + "ui_header_announcement_type_danger": "Bardzo ważne", + "ui_header_announcement_type_info": "Info", + "ui_header_announcement_type_warning": "Ważne", + "ui_texts": "Etykiety i teksty UI", + "unban_pending": "oczekuje na odblokowanie", + "upload": "Prześlij", + "user_link": "Link użytkownika", + "user_quicklink": "Ukryj Quicklink do strony logowania użytkownika", + "validate_license_now": "Sprawdź identyfikator GUID względem serwera licencji", + "verify": "Zweryfikuj", + "yes": "✓" }, "danger": { "access_denied": "Odmowa dostępu lub nieprawidłowe dane w formularzu", @@ -309,17 +424,17 @@ "description_invalid": "Nieprawidłowy opis źródła", "dkim_domain_or_sel_invalid": "Nieprawidłowa domena lub selektor DKIM", "domain_exists": "Domena %s już istnieje", - "domain_invalid": "Błędna nazwa domeny", + "domain_invalid": "Nazwa domeny jest pusta lub nieprawidłowa", "domain_not_empty": "Nie można usunąć niepustej domeny", "domain_not_found": "Nie znaleziono domeny %s", - "domain_quota_m_in_use": "Limit domeny %s MiB", - "goto_empty": "Adres Idź do nie może być pusty", + "domain_quota_m_in_use": "Limit domeny musi być większy lub równy do %s MiB", + "goto_empty": "Adres alias musi zawierać co najmniej jeden prawidłowy adres goto", "goto_invalid": "Adres Idź do jest nieprawidłowy", "is_alias": "%s został już podany jako alias", "is_alias_or_mailbox": "%s podano wcześniej jako alias lub skrzynkę", "is_spam_alias": "%s podano wcześniej jako alias dla spam", - "last_key": "Nie można usunąć ostatniego klucza", - "login_failed": "Niepowodzenie logowania", + "last_key": "Nie można usunąć ostatniego klucza, zamiast tego należy wyłączyć TFA.", + "login_failed": "Logowanie nie powiodło się", "mailbox_invalid": "Nieprawidłowa nazwa skrzynki", "mailbox_quota_exceeded": "Wielkość przekracza limit domeny (maks. %d MiB)", "mailbox_quota_exceeds_domain_quota": "Maksymalna wielkość przekracza limit domeny", @@ -343,7 +458,105 @@ "targetd_not_found": "Nie znaleziono domeny docelowej", "username_invalid": "Nie można użyć nazwy użytkownika", "validity_missing": "Proszę wyznaczyć termin ważności", - "to_invalid": "Pole odbiorca nie może być puste" + "to_invalid": "Pole odbiorca nie może być puste", + "app_name_empty": "Nazwa aplikacji nie może być pusta", + "app_passwd_id_invalid": "Identyfikator hasła aplikacji %s jest niepoprawny", + "authsource_in_use": "Nie można zmienić ani usunąć dostawcy tożsamości, ponieważ jest używany przez co najmniej jednego użytkownika.", + "bcc_empty": "Miejsce docelowe BCC nie może być puste", + "bcc_exists": "Mapa BCC %s istnieje dla typu %s", + "bcc_must_be_email": "Miejsce docelowe BCC %s nie jest prawidłowym adresem e-mail", + "comment_too_long": "Komentarz zbyt długi, maksymalnie 160 dozwolonych znaków.", + "cors_invalid_method": "Podano nieprawidłową metodę Allow-Method", + "cors_invalid_origin": "Podano nieprawidłową wartość Allow-Origin", + "defquota_empty": "Domyślny limit skrzynki pocztowej nie może wynosić 0", + "demo_mode_enabled": "Tryb demo jest włączony", + "dkim_domain_or_sel_exists": "Klucz DKIM dla \"%s\" istnieje i nie zostanie nadpisany", + "domain_cannot_match_hostname": "Domena nie może być taka sama jak nazwa hosta", + "extended_sender_acl_denied": "brak ACL do ustawiania adresów nadawcy zewnętrznego", + "extra_acl_invalid": "Adres nadawcy zewnętrznego \"%s\" jest nieważny", + "extra_acl_invalid_domain": "Nadawca zewnętrzny \"%s\" używa nieprawidłowej domeny", + "fido2_verification_failed": "Weryfikacja FIDO2 nie powiodła się: %s", + "file_open_error": "Nie można otworzyć pliku do zapisu", + "filter_type": "Niewłaściwy typ filtra", + "from_invalid": "Nadawca nie może być pusty", + "generic_server_error": "Wystąpił nieoczekiwany błąd serwera. Skontaktuj się z administratorem.", + "global_filter_write_error": "Nie można zapisać pliku filtra: %s", + "global_map_invalid": "Id mapy globalnej %s nieprawidłowe", + "global_map_write_error": "Nie można napisać globalnej mapy ID %s: %s", + "ham_learn_error": "Błąd uczenia ham: %s", + "iam_test_connection": "Połączenie nie powiodło się", + "imagick_exception": "Błąd: wyjątek Imagick podczas odczytu obrazu", + "img_dimensions_exceeded": "Obraz przekracza maksymalny rozmiar obrazu", + "img_invalid": "Nie można zweryfikować pliku obrazu", + "img_size_exceeded": "Obraz przekracza maksymalny rozmiar pliku", + "img_tmp_missing": "Nie można zweryfikować pliku obrazu: Nie znaleziono pliku tymczasowego", + "invalid_bcc_map_type": "Nieprawidłowy typ mapy BCC", + "invalid_destination": "Format docelowy \"%s\" jest nieprawidłowy", + "invalid_filter_type": "Nieprawidłowy typ filtra", + "invalid_host": "Nieprawidłowy określony host: %s", + "invalid_mime_type": "Niepoprawny typ mime", + "invalid_nexthop": "Następny format hop jest nieprawidłowy", + "invalid_nexthop_authenticated": "Następny hop już istnieje z innymi danymi logowania — zaktualizuj najpierw istniejące dane uwierzytelniające dla tego hopa", + "invalid_recipient_map_new": "Określony nieprawidłowy nowy odbiorca: %s", + "invalid_recipient_map_old": "Określony nieprawidłowy pierwotny odbiorca: %s", + "invalid_reset_token": "Nieprawidłowy token resetu", + "ip_list_empty": "Lista dozwolonych adresów IP nie może być pusta", + "mailbox_defquota_exceeds_mailbox_maxquota": "Domyślny limit skrzynki pocztowej przekracza maksymalny dozwolony limit", + "malformed_username": "Nieprawidłowy format nazwy użytkownika.", + "map_content_empty": "Zawartość mapy nie może być pusta", + "max_age_invalid": "Nieprawidłowa wartość maksymalnego wieku: %s", + "mode_invalid": "Tryb %s jest nieprawidłowy", + "mx_invalid": "Rekord MX %s jest nieprawidłowy", + "mysql_error": "Błąd MySQL: %s", + "network_host_invalid": "Nieprawidłowa sieć lub host: %s", + "next_hop_interferes": "%s powoduje konflikt z nexthop %s.", + "next_hop_interferes_any": "Istniejący next hop koliduje z %s.”", + "nginx_reload_failed": "Nie udało się przeładować Nginx: %s", + "no_user_defined": "Brak zdefiniowanego użytkownika", + "password_reset_invalid_user": "Skrzynka pocztowa nie została znaleziona lub nie ustawiono adresu e-mail do odzyskiwania", + "password_reset_na": "Odzyskiwanie hasła jest obecnie niedostępne. Skontaktuj się ze swoim administratorem.", + "private_key_error": "Błąd klucza prywatnego: %s", + "pushover_credentials_missing": "Brak tokena i/lub klucza Pushover", + "pushover_key": "Klucz Pushover ma niewłaściwy format", + "pushover_token": "Token Pushover ma zły format", + "recipient_map_entry_exists": "Istnieje wpis mapy odbiorcy \"%s", + "recovery_email_failed": "Nie można wysłać e-maila odzyskiwania. Skontaktuj się ze swoim administratorem.", + "redis_error": "Błąd Redis: %s", + "relayhost_invalid": "Wpis mapy %s jest niepoprawny", + "release_send_failed": "Nie udało się zwolnić wiadomości: %s.", + "required_data_missing": "Brakuje wymaganych danych %s", + "reset_f2b_regex": "Filtr Regex nie mógł zostać zresetowany na czas, spróbuj ponownie lub poczekaj jeszcze kilka sekund i przeładuj stronę.", + "reset_token_limit_exceeded": "Limit tokenów Reset został przekroczony. Spróbuj ponownie później", + "rl_timeframe": "Nieprawidłowo ustawiony przedział czasu limitu", + "rspamd_ui_pw_length": "Hasło do Rspamd UI powinno mieć co najmniej 6 znaków długości", + "script_empty": "Skrypt nie może być pusty", + "set_acl_failed": "Nie udało się ustawić ACL", + "settings_map_invalid": "Ustawienia id mapy %s są nieprawidłowe", + "sieve_error": "Błąd podczas analizy skryptu Sieve: %s", + "spam_learn_error": "Błąd uczenia spamu: %s.", + "subject_empty": "Temat nie może być pusty", + "targetd_relay_domain": "Domena docelowa %s jest skonfigurowana jako domena przekazująca relay", + "template_exists": "Szablon %s już istnieje", + "template_id_invalid": "Identyfikator szablonu %s niepoprawny", + "template_name_invalid": "Nazwa szablonu niepoprawna", + "temp_error": "Tymczasowy błąd", + "text_empty": "Pole tekstowe nie może być puste", + "tfa_token_invalid": "Niepoprawny token TFA", + "tls_policy_map_dest_invalid": "Podano błędne lub nieobsługiwane miejsce docelowe dla tej polityki", + "tls_policy_map_entry_exists": "Istnieje mapa polityki TLS \"%s", + "tls_policy_map_parameter_invalid": "Parametr polityki jest nieprawidłowy", + "totp_verification_failed": "Weryfikacja TOTP nie powiodła się", + "transport_dest_exists": "Miejsce docelowe transportu „%s” już istnieje", + "webauthn_verification_failed": "Weryfikacja WebAuthn nie powiodła się: %s", + "webauthn_authenticator_failed": "Wybrany autoryzator nie został odnaleziony", + "webauthn_publickey_failed": "Nie przechowywano klucza publicznego dla wybranego uwierzytelniacza", + "webauthn_username_failed": "Wybrany autoryzator należy do innego konta", + "unknown": "Wystąpił nieznany błąd", + "unknown_tfa_method": "Nieznana metodą TFA", + "unlimited_quota_acl": "Ustawienie nieograniczonego limitu przestrzeni jest zabronione przez reguły ACL", + "value_missing": "Proszę o podanie wszystkich wartości", + "version_invalid": "Wersja %s jest niepoprawna", + "yotp_verification_failed": "Weryfikacja OTP Yubico nie powiodła się: %s" }, "edit": { "active": "Aktywny", @@ -389,7 +602,51 @@ "title": "Edytuj obiekt", "unchanged_if_empty": "Jeżli bez zmian, nie wypełniaj", "username": "Nazwa użytkownika", - "delete_ays": "Proszę o potwierdzenie procesu usuwania." + "delete_ays": "Proszę o potwierdzenie procesu usuwania.", + "acl": "ACL (Pozwolenie)", + "admin": "Edytyj administratora", + "advanced_settings": "Ustawienia zaawansowane", + "allow_from_smtp": "Zezwalaj tylko tym adresom IP na używanie SMTP", + "allow_from_smtp_info": "Pozostaw puste, aby zezwolić na wszystkich nadawców.
adresy IPv4/IPv6 i sieci.", + "allowed_protocols": "Dozwolone protokoły dla bezpośredniego dostępu użytkownika (nie wpływa na protokoły haseł aplikacji).", + "app_name": "Nazwa aplikacji", + "app_passwd": "Hasło do aplikacji", + "app_passwd_protocols": "Dozwolone protokoły dla hasła aplikacji", + "automap": "Spróbuj automatycznie mapować foldery (np. „Sent items”, „Sent” ⇒ „Sent” itp.)", + "bcc_dest_format": "Miejscem docelowym BCC musi być jeden prawidłowy adres e-mail.
Jeśli chcesz wysłać kopię na wiele adresów, utwórz alias i użyj go tutaj.", + "client_id": "Id klienta", + "client_secret": "Tajny klucz klienta(sekret)", + "comment_info": "Komentarz prywatny nie jest widoczny dla użytkownika, natomiast komentarz publiczny jest wyświetlany jako podpowiedź po najechaniu kursorem w widoku użytkownika.", + "created_on": "Stworzony na", + "custom_attributes": "Niestandardowe atrybuty", + "delete2": "Usunąć wiadomości na koncie docelowym, które nie występują na koncie źródłowym?", + "disable_login": "Zablokuj logowanie (przychodząca poczta nadal będzie przyjmowana)", + "domain_footer": "Stopka dla całej domeny", + "domain_footer_html": "Stopka HTML", + "domain_footer_info": "Stopki dla całej domeny są dodawane do wszystkich wychodzących wiadomości e-mail powiązanych z adresami w tej domenie.
W stopce można użyć następujących zmiennych:", + "domain_footer_info_vars": { + "auth_user": "{= auth_user =} - Uwierzytelniona nazwa użytkownika określona przez MTA", + "from_user": "{= from_user =} – część użytkownika (local-part) adresu nadawcy; np. dla „moo@mailcow.tld\n” zwróci „moo”", + "from_name": "{= from_name =} – nazwa nadawcy (From name) z nagłówka wiadomości; np. dla „Mailcow ” zwróci „Mailcow”.", + "from_addr": "{= from_addr =} – pełny adres nadawcy (z części envelope)", + "from_domain": "{= from_domain =} – część domenowa adresu nadawcy (z envelope).", + "custom": "{= foo =} - jeśli skrzynka pocztowa ma niestandardowy atrybut „foo” o wartości „bar”, zwraca „bar”." + }, + "domain_footer_plain": "Stopka w formacie tekstowym(PLAIN)", + "domain_footer_skip_replies": "Nie dodawaj stopki do odpowiedzi na e-maile", + "extended_sender_acl": "Adresy nadawców zewnętrznych", + "extended_sender_acl_info": "Klucz DKIM dla domeny powinien zostać zaimportowany, jeśli jest dostępny.\nPamiętaj, aby dodać ten serwer do odpowiadającego rekordu SPF typu TXT.\nKiedy domena lub domena aliasu zostanie dodana do tego serwera i pokrywa się z zewnętrznym adresem, zewnętrzny adres zostanie usunięty.", + "force_pw_update": "Wymuszenie aktualizacji hasła przy następnym logowaniu", + "force_pw_update_info": "Ten użytkownik będzie mógł logować się wyłącznie do %s. Hasła aplikacyjne pozostają aktywne.", + "footer_exclude": "Wyklucz ze stopki", + "gal": "Globalna lista adresowa", + "gal_info": "GAL zawiera wszystkie obiekty domeny i nie może być edytowana przez żadnego użytkownika. Informacje o dostępności (free/busy) w SOGo są niedostępne, jeśli funkcja jest wyłączona!Uruchom ponownie SOGo, aby zastosować zmiany.", + "generate": "generuj", + "grant_types": "Rodzaje grantów(Typy przyznawania dostępu)", + "internal": "Wewnętrzny", + "internal_info": "Aliasów wewnętrznych można używać tylko w obrębie własnej domeny lub domen aliasów.", + "last_modified": "Ostatnio modyfikowany", + "lookup_mx": "Destination to wyrażenie regularne dopasowujące nazwę serwera MX (np. .*.google.com — aby kierować całą pocztę wysyłaną do MX kończących się na google.com przez ten hop)." }, "footer": { "cancel": "Anuluj", @@ -531,16 +788,25 @@ "object_modified": "Zapisano zmiany w obiekcie %s", "resource_added": "Dodano śródło %s", "resource_modified": "Zapisano zmiany w skrzynce %s", - "resource_removed": "Usunięto zasób %s" + "resource_removed": "Usunięto zasób %s", + "template_removed": "Szablon o identyfikatorze %s został usunięty.", + "tls_policy_map_entry_deleted": "Mapa polityki TLS o identyfikatorze %s została usunięta", + "tls_policy_map_entry_saved": "Wpis mapy polityki TLS \"%s\" został zapisany", + "ui_texts": "Zapisane zmiany w tekstach UI", + "upload_success": "Plik przesłany pomyślnie", + "verified_fido2_login": "Zweryfikowany login FIDO2", + "verified_totp_login": "Zweryfikowany login TOTP", + "verified_webauthn_login": "Zweryfikowany login WebAuthn", + "verified_yotp_login": "Zweryfikowany login Yubico OTP" }, "tfa": { - "api_register": "%s używa Yubico Cloud API. Proszę pobrać klucz API dla Twojego klucza here", + "api_register": "%s używa Yubico Cloud API. Proszę pobrać klucz API dla Twojego klucza tutaj", "confirm": "Potwierdź", "confirm_totp_token": "Potwierdź zmiany przez wprowadzenie wygenerowanego tokenu", "delete_tfa": "Wyłącz TFA", "disable_tfa": "Wyłącz TFA do kolejnego udanego logowania", "enter_qr_code": "Twój kod TOTP, jeśli Twoje urządzenie nie skanuje kodów QR.", - "key_id": "Identyfikator dla Twojego YubiKey", + "key_id": "Identyfikator dla twojego urządzenia", "key_id_totp": "Identyfikator dla Twojego klucza", "none": "Deaktywuj", "scan_qr_code": "Zeskanuj następujący kod aplikacją uwierzytelniającą lub wprowadź kod ręcznie.", @@ -551,7 +817,15 @@ "webauthn": "Uwierzytelnianie WebAuthn", "waiting_usb_auth": "Czekam na urządzenie USB...

Wciśnij teraz przycisk na urządzeniu WebAuthn USB.", "waiting_usb_register": " Czekam na urządzenie USB...

Wprowadź swoje hasło powyżej i potwierdź rejestrację przez naciśnięcie przycisku na urządzeniu USB.", - "yubi_otp": "Uwierzytelnianie Yubico OTP" + "yubi_otp": "Uwierzytelnianie Yubico OTP", + "authenticators": "Uwierzytelniacze", + "error_code": "Kod błędu", + "init_webauthn": "Inicjalizacja, proszę czekać...", + "reload_retry": "- (przeładuj przeglądarkę, jeśli błąd nadal występuje)", + "start_webauthn_validation": "Rozpocznij walidację", + "tfa_token_invalid": "Token TFA nieprawidłowy", + "u2f_deprecated": "Wygląda na to, że Twój klucz został zarejestrowany przy użyciu przestarzałej metody U2F. Dezaktywujemy dla Ciebie uwierzytelnianie dwuskładnikowe i usuniemy Twój klucz.", + "u2f_deprecated_important": "Zarejestruj swój klucz w panelu administracyjnym za pomocą nowej metody WebAuthn." }, "user": { "action": "Działanie", @@ -581,7 +855,7 @@ "edit": "Edytuj", "encryption": "Szyfrowanie", "excludes": "Wyłączenia", - "force_pw_update": "Musisz zmienić hasło, aby używać webmaila.", + "force_pw_update": "Musisz ustawić nowe hasło, aby mieć dostęp do usług groupware.", "hour": "Godzina", "hourly": "Co godzinę", "hours": "Godziny", @@ -601,16 +875,16 @@ "remove": "Usuń", "save_changes": "Zapisz zmiany", "shared_aliases": "Aliasy współdzielone", - "shared_aliases_desc": "Na aliasy współdzielone nie wpływają filtry spamu i ustawienia TLS.", - "show_sieve_filters": "Twój filtr sieve", - "sogo_profile_reset": "Usuń profil SOGo (webmail)", - "sogo_profile_reset_help": "To usunie ustawienia SOGo bezpowrotnie.", - "sogo_profile_reset_now": "Usuń profil teraz", - "spam_aliases": "Tymczasowy alias email", + "shared_aliases_desc": "Współdzielone aliasy nie są objęte ustawieniami specyficznymi dla użytkownika, takimi jak filtr antyspamowy czy polityka szyfrowania.\nOdpowiadające im filtry antyspamowe mogą być tworzone wyłącznie przez administratora — jako polityki obowiązujące dla całej domeny.", + "show_sieve_filters": "Pokaż filtr sieve aktywnego użytkownika", + "sogo_profile_reset": "Zresetuj profil SOGo", + "sogo_profile_reset_help": "Spowoduje to usunięcie profilu użytkownika SOGo oraz bezpowrotne usunięcie wszystkich danych kontaktów i kalendarza.", + "sogo_profile_reset_now": "Zresetuj profil teraz", + "spam_aliases": "Tymczasowe aliasy email", "spamfilter": "Filtr spamu", "spamfilter_behavior": "Ocena", "spamfilter_bl": "Czarna lista", - "spamfilter_bl_desc": "Adresy email z czarnej listy zawsze klasyfikuj jako spam i odrzucaj. Można użyć wildcards.", + "spamfilter_bl_desc": "Adresy e-mail znajdujące się na liście zablokowanych (denylist) są zawszeklasyfikowane jako spam i odrzucane.\nOdrzucone wiadomości nie sąkopiowane do kwarantanny.\nMożna używać symboli wieloznacznych (wildcardów).\nFiltr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów kierujących do jednej skrzynki pocztowej), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki.", "spamfilter_default_score": "Wartości domyślne", "spamfilter_green": "Zielony: ta wiadomość nie jest spamem", "spamfilter_hint": "Pierwsza wartość oznacza \"niską punktację spam\", druga wartość oznacza \"wysoką punktację spam\".", @@ -622,13 +896,13 @@ "spamfilter_table_remove": "Usuń", "spamfilter_table_rule": "Zasada", "spamfilter_wl": "Biała lista", - "spamfilter_wl_desc": "Adresy email z białej listy nigdy nie klasyfikuj jako spam. Można użyć wildcards.", + "spamfilter_wl_desc": "Adresy e-mail znajdujące się na liście dozwolonych (allowlist) są zaprogramowane tak, aby nigdy nie były klasyfikowane jako spam.\nMożna używać symboli wieloznacznych (wildcardów).\nFiltr jest stosowany wyłącznie do bezpośrednich aliasów (aliasów wskazujących na jedną skrzynkę pocztową), z wyłączeniem aliasów typu „catch-all” oraz samej skrzynki pocztowej", "spamfilter_yellow": "Żółty: ta wiadomość może być spamem, zostanie oznaczona jako spam i przeniesiona do folderu spam", - "sync_jobs": "Polecenie synchronizacji", + "sync_jobs": "Zadania synchronizacji", "tag_handling": "Ustaw obsługę znaczników pocztowych", "tag_help_example": "Przykład adresu email z etykietą: ja+Facebook@example.org", "tag_help_explain": "W podfolderze: tworzy nowy podfolder z nazwą taką jak etykieta, który zostanie umieszczony pod Skrzynką odbiorczą (\"Skrzynka odbiorcza/Facebook\").
\r\nW temacie: nazwy etykiet zostaną dodane na początku tematów wiadomości, np.: \"[Facebook] Moje wiadomości\".", - "tag_in_none": "Nic nie robić", + "tag_in_none": "Nie wykonuj żadnej akcji", "tag_in_subfolder": "W podfolderze", "tag_in_subject": "W temacie", "tls_enforce_in": "Uruchom TLS przychodzące", @@ -640,9 +914,175 @@ "week": "Tydzień", "weekly": "Co tydzień", "weeks": "Tygodnie", - "q_add_header": "Spam" + "q_add_header": "Spam", + "advanced_settings": "Ustawienia zaawansowane", + "app_hint": "Hasła aplikacji są alternatywnymi hasłami dla logowania IMAP, SMTP, CalDAV, CardDAV i EAS. Nazwa użytkownika pozostaje niezmieniona. Webmail SOGo nie jest dostępny za pośrednictwem haseł aplikacji.", + "allowed_protocols": "Dozwolone protokoły", + "app_name": "Nazwa aplikacji", + "app_passwds": "Hasła do aplikacji", + "apple_connection_profile": "Profil połączenia Apple", + "apple_connection_profile_complete": "Ten profil połączenia obejmuje parametry IMAP i SMTP, a także ścieżki CalDAV (kalendarze) i CardDAV (kontakty) dla urządzenia Apple.", + "apple_connection_profile_mailonly": "Ten profil połączenia zawiera parametry konfiguracji IMAP i SMTP dla urządzenia Apple.", + "apple_connection_profile_with_app_password": "Nowe hasło aplikacji jest generowane i dodawane do profilu, dzięki czemu nie trzeba wprowadzać hasła podczas konfigurowania urządzenia. Proszę nie udostępniaj tego pliku, ponieważ zapewnia on pełny dostęp do skrzynki pocztowej.", + "attribute": "Atrybut", + "authentication": "Uwierzytelnianie", + "change_password_hint_app_passwords": "Twoje konto ma %d hasła aplikacji, które nie zostaną zmienione. Aby nimi zarządzać, przejdź do zakładki Hasła aplikacji.", + "clear_recent_successful_connections": "Wyczyść udane połączenia", + "create_app_passwd": "Stwórz hasło do aplikacji", + "created_on": "Stworzony na", + "delete_ays": "Proszę o potwierdzenie procesu usuwania.", + "direct_protocol_access": "Ten użytkownik skrzynki pocztowej ma bezpośredni, zewnętrzny dostęp do następujących protokołów i aplikacji. To ustawienie jest kontrolowane przez administratora. Można tworzyć hasła aplikacji, aby przyznać dostęp do poszczególnych protokołów i aplikacji.Przycisk „Webmail” umożliwia jednokrotne logowanie (SSO) do SOGo i jest zawsze dostępny.", + "email": "Email", + "email_and_dav": "E-maile, kalendarze i kontakty", + "empty": "Brak wyników", + "expire_in": "wygasa w", + "fido2_webauthn": "FIDO2/WebAuthn", + "from": "od", + "generate": "generuj", + "last_mail_login": "Ostatni login na skrzynkę pocztową", + "last_pw_change": "Ostatnia zmiana hasła", + "last_ui_login": "Ostatni login UI", + "loading": "Ładowanie...", + "login_history": "Historia logowania", + "mailbox": "Skrzynka pocztowa", + "mailbox_general": "Ogólne ustawienia skrzynki", + "mailbox_settings": "Ustawienia", + "month": "miesiąc", + "months": "miesiące", + "no_last_login": "Brak ostatnich danych logowania do interfejsu użytkownika", + "open_logs": "Otwórz logi użytkownika", + "open_webmail_sso": "­Webmail", + "overview": "Przegląd", + "password": "Hasło", + "password_repeat": "Hasło (powtórz)", + "password_reset_info": "Jeśli nie ma wiadomości e-mail do odzyskiwania hasła, ta funkcja nie może być używana.", + "protocols": "Protokoły", + "pushover_evaluate_x_prio": "Eskaluj wiadomości o wysokim priorytecie [X-Priority: 1]", + "pushover_info": "Ustawienia powiadomień push będą stosowane do wszystkich czystych (niebędących spamem) wiadomości dostarczonych do %s, w tym aliasów (współdzielonych, niewspółdzielonych i oznaczonych).", + "pushover_only_x_prio": "Uwzględniaj tylko wiadomości o wysokim priorytecie [X-Priority: 1]", + "pushover_sender_array": "Uwzględnij następujące adresy e-mail nadawców (oddzielone przecinkami)", + "pushover_sender_regex": "Dopasuj nadawców według następującego regexu", + "pushover_text": "Tekst powiadomienia", + "pushover_title": "Tytuł powiadomienia", + "pushover_sound": "Dźwięk powiadomienia", + "pushover_vars": "Jeśli nie zdefiniowano filtra nadawcy, wszystkie wiadomości będą brane pod uwagę.
Filtry regex oraz dokładne sprawdzanie nadawców można definiować indywidualnie – są one przetwarzane kolejno i nie zależą od siebie.
Dostępne zmienne dla treści i tytułu (prosimy pamiętać o zasadach ochrony danych osobowych).", + "pushover_verify": "Zweryfikuj dane logowania", + "pw_recovery_email": "E-mail do odzyskiwania hasła", + "q_all": "Wszystkie kategorie", + "q_reject": "Odrzucono", + "quarantine_category": "Kategoria powiadomień o kwarantannie", + "quarantine_category_info": "Kategoria powiadomień „Odrzucone” obejmuje wiadomości, które zostały odrzucone, natomiast „Folder spam” powiadamia użytkownika o wiadomościach umieszczonych w folderze spam.", + "quarantine_notification_info": "Po wysłaniu powiadomienia elementy zostaną oznaczone jako „powiadomione” i żadne kolejne powiadomienia nie zostaną wysłane dla danego elementu.", + "recent_successful_connections": "Zarejestrowano udane połączenia", + "running": "Uruchomiony", + "save": "Zapisz zmiany", + "sender_acl_disabled": "Sprawdzenie nadawcy jest wyłączone", + "spam_score_reset": "Przywróć domyślne ustawienia serwera", + "status": "Status", + "syncjob_check_log": "Sprawdź log", + "syncjob_last_run_result": "Wynik ostatniego uruchomienia", + "syncjob_EX_OK": "Sukces", + "syncjob_EXIT_CONNECTION_FAILURE": "Problem z połączeniem", + "syncjob_EXIT_TLS_FAILURE": "Problem z szyfrowanym połączeniem", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problem uwierzytelniania", + "syncjob_EXIT_OVERQUOTA": "Docelowa skrzynka pocztowa przekroczyła limit pojemności", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nie można połączyć się ze zdalnym serwerem", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Niewłaściwa nazwa użytkownika lub hasło", + "text": "Tekst", + "tfa_info": "Uwierzytelnianie dwuskładnikowe pomaga chronić Twoje konto.\nJeśli je włączysz, będziesz potrzebować haseł aplikacji, aby logować się do programów lub usług, które nie obsługują uwierzytelniania dwuskładnikowego (np. klientów poczty).", + "title": "Tytuł", + "value": "Wartość", + "verify": "Zweryfikuj", + "waiting": "Oczekuje", + "with_app_password": "z hasłem aplikacji", + "year": "rok", + "years": "lata" }, "warning": { - "session_ua": "Nieprawidłowy token formularza: Błąd walidacji User-Agent" + "session_ua": "Nieprawidłowy token formularza: Błąd walidacji User-Agent", + "cannot_delete_self": "Nie można usunąć zalogowanego użytkownika", + "domain_added_sogo_failed": "Dodano domenę, ale nie udało się ponownie uruchomić SOGo, sprawdź logi serwera.", + "dovecot_restart_failed": "Nie udało się ponownie uruchomić Dovecota, sprawdź logi", + "fuzzy_learn_error": "Błąd uczenia fuzzy hash: %s", + "hash_not_found": "Hash nie został odnaleziony lub został już usunięty", + "ip_invalid": "Pominięto nieprawidłowe IP: %s", + "is_not_primary_alias": "Pominięto alias niebędący głównym: %s", + "no_active_admin": "Nie można dezaktywować ostatniego aktywnego administratora", + "quota_exceeded_scope": "Przekroczono limit pojemności domeny: w tym zakresie domeny można tworzyć tylko skrzynki o nieograniczonej pojemności.", + "session_token": "Nieprawidłowy token formularza: niedopasowanie tokenów" + }, + "datatables": { + "collapse_all": "Zwiń wszystko", + "decimal": ".", + "emptyTable": "Brak danych w tabeli", + "expand_all": "Rozszerz wszystko", + "info": "Wyświetlanie od START do END z TOTAL wpisów.", + "infoEmpty": "Wyświetlanie od 0 do 0 z 0 wpisów", + "infoFiltered": "(filtrowane z _MAX_ suma wpisów)", + "thousands": ",", + "lengthMenu": "Pokaż wpisy _MENU_", + "loadingRecords": "Ładowanie...", + "processing": "Proszę czekać...", + "search": "Szukaj:", + "zeroRecords": "Nie znaleziono pasujących rekordów", + "paginate": { + "first": "Pierwszy", + "last": "Ostatni", + "next": "Następny", + "previous": "Poprzedni" + }, + "aria": { + "sortAscending": "Aktywuj, aby posortować kolumnę rosnąco", + "sortDescending": "Aktywuj, aby posortować kolumnę malejąco" + } + }, + "debug": { + "architecture": "Architektura", + "chart_this_server": "Wykres (ten serwer)", + "containers_info": "Informacje o kontenerze", + "container_running": "uruchomiony", + "container_disabled": "Kontener zatrzymany lub wyłączony", + "container_stopped": "Zatrzymany", + "cores": "rdzenie", + "current_time": "Czas systemowy", + "disk_usage": "Użycie dysku", + "docs": "Dokumentacja", + "error_show_ip": "Nie można ustalić publicznych adresów IP.", + "external_logs": "Logi zewnętrzne", + "history_all_servers": "Historia (wszystkie serwery)", + "in_memory_logs": "Logi w pamięci", + "last_modified": "Ostatnia modyfikacja", + "log_info": "

mailcow logi w pamięci są gromadzone na listach Redis i przycinane do wartości LOG_LINES (%d) co minutę, aby ograniczyć nadmierne obciążenie systemu.

Logi w pamięci nie są przeznaczone do trwałego przechowywania. Wszystkie aplikacje, które zapisują logi w pamięci, wysyłają je również do daemon Dockera, a więc do domyślnego sterownika logowania.

Ten typ logów należy wykorzystywać do debugowania drobnych problemów z kontenerami.

Logi zewnętrzne są zbierane za pośrednictwem API danej aplikacji.

Logi statyczne to głównie dzienniki aktywności, które nie są zapisywane przez Dockerd, ale powinny być trwałe (z wyjątkiem logów API).

", + "login_time": "Czas", + "logs": "Logi", + "memory": "Pamięć", + "online_users": "Użytkownik online", + "restart_container": "Restart", + "service": "Usługa", + "show_ip": "Pokaż publiczne IP", + "size": "Rozmiar", + "started_at": "Zaczęło się od", + "started_on": "Zaczęło się od", + "static_logs": "Logi statyczne", + "success": "Sukces", + "system_containers": "System i kontenery", + "timezone": "Strefa czasowa", + "uptime": "Czas pracy", + "update_available": "Dostępna jest aktualizacja", + "no_update_available": "System jest w najnowszej wersji", + "update_failed": "Nie można było sprawdzić aktualizacji", + "username": "Nazwa użytkownika", + "wip": "Obecnie praca w toku" + }, + "diagnostics": { + "cname_from_a": "Wartość pochodzi z rekordu A/AAAA. Obsługiwane, o ile rekord wskazuje na prawidłowy zasób.", + "dns_records": "Rekordy DNS", + "dns_records_24hours": "Pamiętaj, że zmiany wprowadzone w DNS mogą zająć nawet do 24 godzin, zanim ich aktualny stan zostanie poprawnie odzwierciedlony na tej stronie.\nTa sekcja ma na celu ułatwienie Ci konfiguracji rekordów DNS oraz sprawdzenie, czy wszystkie rekordy zostały prawidłowo zapisane w DNS.", + "dns_records_data": "Poprawne dane", + "dns_records_docs": "Proszę skonsultuj również dokumnetację", + "dns_records_name": "Nazwa", + "dns_records_status": "Aktualny stan", + "dns_records_type": "Typ", + "optional": "Ten rekord jest opcjonalny." } } From 2e1d98cc7ccd40a72a259b18172b11478b2e0e22 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 10 Nov 2025 21:06:13 +0100 Subject: [PATCH 080/109] [Web] Updated lang.pl-pl.json (#6908) [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json Co-authored-by: Monika Bark --- data/web/lang/lang.pl-pl.json | 127 ++++++++++++++++++++++++++++++++-- 1 file changed, 120 insertions(+), 7 deletions(-) diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index 4d68d0dd0..b08b115a8 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -646,7 +646,35 @@ "internal": "Wewnętrzny", "internal_info": "Aliasów wewnętrznych można używać tylko w obrębie własnej domeny lub domen aliasów.", "last_modified": "Ostatnio modyfikowany", - "lookup_mx": "Destination to wyrażenie regularne dopasowujące nazwę serwera MX (np. .*.google.com — aby kierować całą pocztę wysyłaną do MX kończących się na google.com przez ten hop)." + "lookup_mx": "Destination to wyrażenie regularne dopasowujące nazwę serwera MX (np. .*.google.com — aby kierować całą pocztę wysyłaną do MX kończących się na google.com przez ten hop).", + "pushover_title": "Tytuł powiadomienia", + "pushover_sound": "Dźwięk powiadomienia", + "pushover_vars": "Gdy nie zdefiniowano żadnego filtra nadawcy, brane będą pod uwagę wszystkie wiadomości. Filtry oparte na wyrażeniach regularnych (regex) oraz dokładne dopasowania nadawców można definiować indywidualnie — będą one przetwarzane kolejno, niezależnie od siebie. Dostępne zmienne do użycia w treści i tytule (należy pamiętać o zasadach ochrony danych osobowych).", + "pushover_verify": "Zweryfikuj dane logowania", + "quota_warning_bcc": "Ukryta kopia ostrzeżenia o przekroczeniu limitu", + "quota_warning_bcc_info": "Ostrzeżenia będą wysyłane jako osobne kopie do poniższych odbiorców. Temat wiadomości zostanie rozszerzony o nazwę użytkownika w nawiasach, na przykład: Ostrzeżenie o limicie (user@example.com\n).", + "ratelimit": "Limit wysyłania", + "redirect_uri": "Adres przekierowania / adres zwrotny (Redirect/Callback URL)", + "relay_transport_info": "
Informacja
**Możesz zdefiniować mapy transportu (transport maps) dla niestandardowego miejsca docelowego tej domeny.** Jeśli nie zostanie to ustawione, zostanie wykonane wyszukiwanie", + "relay_unknown_only": "Przekazuj (relay) tylko nieistniejące skrzynki pocztowe. Istniejące skrzynki będą dostarczane lokalnie.", + "relayhost": "Transporty przypisane do nadawcy", + "scope": "Zakres", + "sender_acl_disabled": "Sprawdzanie nadawcy jest wyłączone", + "sender_acl_info": "Jeżeli użytkownik skrzynki pocztowej A ma pozwolenie na wysyłkę jako użytkownik skrzynki B, adres nadawcy nie jest automatycznie wyświetlany jako opcja w polu „Od” w SOGo.
\nUżytkownik skrzynki B musi utworzyć delegację w SOGo, aby użytkownik A mógł wybrać ich adres jako nadawcę. Aby zdelegować skrzynkę w SOGo, użyj menu (trzy kropki) po prawej stronie nazwy skrzynki w lewym górnym rogu, będąc w widoku poczty. To zachowanie nie dotyczy adresów aliasów.", + "sieve_desc": "Krótki opis", + "sieve_type": "Typ filtra", + "skipcrossduplicates": "Pomijaj duplikaty wiadomości w różnych folderach (pierwsza napotkana wiadomość zostaje zachowana).", + "sogo_access": "Bezpośrednie przekazywanie do SOGo", + "sogo_access_info": "Po zalogowaniu użytkownik jest automatycznie przekierowywany do SOGo.", + "sogo_visible": "Alias jest widoczny w SOGO", + "sogo_visible_info": "Ta opcja dotyczy tylko obiektów, które mogą być wyświetlane w SOGo (aliasy współdzielone lub nie współdzielone, wskazujące przynajmniej na jedną lokalną skrzynkę).\nJeśli obiekt zostanie ukryty, alias nie będzie dostępny jako wybieralny nadawca w SOGo.", + "spam_alias": "Tworzenie lub zmiana ograniczonych czasowo adresów aliasów", + "spam_filter": "Filtr spam", + "spam_policy": "Dodaj lub usuń elementy z listy dozwolonych / zablokowanych", + "spam_score": "Ustaw własny poziom punktacji spamu", + "timeout1": "Limit czasu połączenia z serwerem zdalnym", + "timeout2": "Limit czasu połączenia z serwerem lokalnym", + "validate_save": "Zatwierdź i zapisz" }, "footer": { "cancel": "Anuluj", @@ -654,7 +682,14 @@ "delete_now": "Usuń teraz", "delete_these_items": "Proszę potwierdzić zmiany w poniższym identyfikatorze obiektu", "loading": "Proszę czekać...", - "restart_now": "Uruchom ponownie teraz" + "restart_now": "Uruchom ponownie teraz", + "hibp_check": "Sprawdź w stosunku do haveibeenpwned.com", + "hibp_nok": "Dopasowano! To potencjalnie niebezpieczne hasło!", + "hibp_ok": "Nie znaleziono żadnego dopasowania.", + "nothing_selected": "Nic wybranego", + "restart_container": "Zresetuj kontener", + "restart_container_info": "Ważne: Łagodne ponowne uruchomienie może zająć trochę czasu — proszę poczekać na jego zakończenie.", + "restarting_container": "Ponowne uruchomienie kontenera, może to zająć trochę czasu" }, "header": { "administration": "Administrowanie", @@ -662,10 +697,16 @@ "mailcow_config": "Konfiguracja", "quarantine": "Kwarantanna", "restart_sogo": "Uruchom ponownie SOGo", - "user_settings": "Ustawienia użytkownika" + "user_settings": "Ustawienia użytkownika", + "apps": "Aplikacje", + "debug": "Informacja", + "mailcow_system": "System", + "restart_netfilter": "Uruchom ponownie netfilter" }, "info": { - "no_action": "Żadne działanie nie ma zastosowania" + "no_action": "Żadne działanie nie ma zastosowania", + "awaiting_tfa_confirmation": "Oczekiwanie na potwierdzenie TFA", + "session_expires": "Twoja sesja wygaśnie za około 15 sekund" }, "login": { "delayed": "Logowanie zostało opóźnione o %s sekund.", @@ -678,7 +719,18 @@ "login_domainadmintext": "Zaloguj się jako administrator domeny", "login_admintext": "Zaloguj się jako admin", "other_logins": "lub zaloguj za pomocą", - "email": "Adres e-mail" + "email": "Adres e-mail", + "back_to_mailcow": "Wróć do mailcow", + "fido2_webauthn": "FIDO2/WebAuthn Login", + "invalid_pass_reset_token": "Token resetowania hasła jest nieprawidłowy lub wygasł.
Proszę poprosić o nowy link do resetowania hasła.", + "login_user": "Logowanie użytkownika", + "login_dadmin": "Logowanie administratora domeny", + "login_admin": "Login Administratora", + "mobileconfig_info": "Zaloguj się jako użytkownik skrzynki pocztowej, aby pobrać żądany profil połączenia Apple.", + "new_password": "Nowe hasło", + "new_password_confirm": "Potwierdź nowe hasło", + "reset_password": "Zresetuj hasło", + "request_reset_password": "Poproś o zmianę hasła" }, "mailbox": { "action": "Działanie", @@ -738,7 +790,48 @@ "tls_enforce_out": "Uruchom TLS wychodzące", "toggle_all": "Zaznacz wszystkie", "username": "Nazwa użytkownika", - "weekly": "Co tydzień" + "weekly": "Co tydzień", + "add_alias_expand": "Rozszerz alias na domeny alias", + "add_bcc_entry": "Dodaj mapę BCC", + "add_filter": "Dodaj filtr", + "recipient_map_old_info": "Mapa odbiorcy (pierwotne miejsce docelowe) musi być prawidłowym adresem e-mail lub nazwą domeny.", + "recipient_maps": "Mapy odbiorców", + "relay_unknown": "Przekazuj nieznane skrzynki pocztowe", + "running": "Uruchomione", + "sender": "Nadawca", + "set_postfilter": "Oznacz jako postfilter", + "set_prefilter": "Oznacz jako prefilter", + "sieve_info": "Możesz przechowywać wiele filtrów dla każdego użytkownika, jednak w danym momencie aktywny może być tylko jeden prefilter i jeden postfilter
\nKażdy filtr będzie przetwarzany w opisanej kolejności. Ani błędny skrypt, ani polecenie „keep;” nie zatrzymają przetwarzania kolejnych skryptów.\nZmiany w globalnych skryptach Sieve spowodują ponowne uruchomienie usługi Dovecot.

\nGlobalny prefiltr Sieve • Prefilter • Skrypty użytkownika • Postfilter • Globalny postfilter Sieve", + "sieve_preset_1": "Odrzuć pocztę z prawdopodobnymi niebezpiecznymi typami plików", + "sieve_preset_2": "Zawsze zaznaczaj e-mail konkretnego nadawcy jako odczytane", + "sieve_preset_3": "Odrzuć po cichu, zatrzymaj cały proces sieve", + "sieve_preset_4": "Plik do INBOX, pomiń dalszy proces przez filtry sieve", + "sieve_preset_5": "Automatyczna odpowiedź (urlopowa)", + "sieve_preset_6": "Odrzuć pocztę z odpowiedzią", + "sieve_preset_7": "Przekierowanie wiadomości z możliwością zachowania lub usunięcia kopii", + "sieve_preset_8": "Przekieruj wiadomość e-mail od określonego nadawcy, oznacz jako odczytaną i posortuj do podfoldera", + "sieve_preset_header": "Zbacz przykładowe ustawienia poniżej. Więcej szczegółów znajdziesz w Wikipedii.", + "sogo_visible": "Alias jest widoczny w SOGo", + "sogo_visible_n": "Ukryj alias w SOGo", + "sogo_visible_y": "Pokaż alias w SOGo", + "stats": "Statystyki", + "status": "Status", + "syncjob_check_log": "Sprawdź log", + "syncjob_last_run_result": "Wynik ostatniego uruchomienia", + "syncjob_EX_OK": "Sukces", + "syncjob_EXIT_CONNECTION_FAILURE": "Problem z połączeniem", + "syncjob_EXIT_TLS_FAILURE": "Problem z szyfrowanym połączeniem", + "syncjob_EXIT_AUTHENTICATION_FAILURE": "Problem uwierzytelniania", + "syncjob_EXIT_OVERQUOTA": "Docelowa skrzynka pocztowa przekroczyła limit pojemności", + "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nie można połączyć się ze zdalnym serwerem", + "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Niewłaściwa nazwa użytkownika lub hasło", + "table_size": "Rozmiar tabeli", + "table_size_show_n": "Pokaż %s elementy", + "templates": "Szablony", + "template": "Szablon", + "tls_map_dest": "Miejsce docelowe", + "tls_map_dest_info": "Przykłady: example.org, .example.org, [mail.example.org]:25", + "tls_map_parameters": "Parametry" }, "quarantine": { "action": "Działanie", @@ -749,7 +842,12 @@ "toggle_all": "Zaznacz wszystkie", "confirm_delete": "Potwierdź usunięcie tego elementu.", "learn_spam_delete": "Zapamiętaj jako spam i usuwaj w przyszłości", - "quick_delete_link": "Otwórz szybki link do usuwania" + "quick_delete_link": "Otwórz szybki link do usuwania", + "refresh": "Odśwież", + "rejected": "Odrzucony", + "release": "Zwolnij", + "release_body": "Dołączyliśmy Twoją wiadomość jako plik eml do tej wiadomości.", + "release_subject": "Potencjalnie szkodliwa pozycja kwarantanny %s" }, "queue": { "queue_manager": "Menedżer kolejki", @@ -1084,5 +1182,20 @@ "dns_records_status": "Aktualny stan", "dns_records_type": "Typ", "optional": "Ten rekord jest opcjonalny." + }, + "fido2": { + "confirm": "Potwierdź", + "fido2_auth": "Logowanie za pomocą FIDO2", + "fido2_success": "Urządzenie pomyślnie zarejestrowane", + "fido2_validation_failed": "Walidacja nie powiodła się", + "fn": "Przyjazna nazwa FIDO", + "known_ids": "Znane Id", + "none": "Wyłączony", + "register_status": "Status rejestracji", + "rename": "Zmień nazwę", + "set_fido2": "Zarejestruj urządzenie FIDO2", + "set_fido2_touchid": "Zarejestruj Touch ID w Apple M1", + "set_fn": "Ustaw przyjazną nazwę w FIDO", + "start_fido2_validation": "Rozpocznij walidację FIDO2" } } From ec472f13cf6b974818a4a13d2388215bd68b528c Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 12 Nov 2025 09:50:41 +0100 Subject: [PATCH 081/109] sogo: removed URLDecrpytion by default, make it configurable in sogo.conf --- data/Dockerfiles/sogo/bootstrap-sogo.sh | 4 ---- data/conf/sogo/sogo.conf | 6 ++++++ docker-compose.yml | 3 ++- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/data/Dockerfiles/sogo/bootstrap-sogo.sh b/data/Dockerfiles/sogo/bootstrap-sogo.sh index af7d2a4db..96d8a6919 100755 --- a/data/Dockerfiles/sogo/bootstrap-sogo.sh +++ b/data/Dockerfiles/sogo/bootstrap-sogo.sh @@ -50,10 +50,6 @@ cat < /var/lib/sogo/GNUstep/Defaults/sogod.plist YES SOGoEncryptionKey ${RAND_PASS} - SOGoURLEncryptionEnabled - YES - SOGoURLEncryptionPassphrase - ${SOGO_URL_ENCRYPTION_KEY} OCSAdminURL mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_admin OCSCacheFolderURL diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf index 2c8d80a12..6854569f5 100644 --- a/data/conf/sogo/sogo.conf +++ b/data/conf/sogo/sogo.conf @@ -86,6 +86,12 @@ SOGoMaximumFailedLoginInterval = 900; SOGoFailedLoginBlockInterval = 900; + // Enable SOGo URL Description for GDPR compliance, this may cause some issues with calendars and contacts. Also uncomment the encryption key below to use it. + //SOGoURLEncryptionEnabled = NO; + + // Set a 16 character encryption key for SOGo URL Description, change this to your own value + //SOGoURLPathEncryptionKey = "SOGoSuperSecret0"; + GCSChannelCollectionTimer = 60; GCSChannelExpireAge = 60; diff --git a/docker-compose.yml b/docker-compose.yml index f38b8937c..317fba269 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -200,7 +200,7 @@ services: - phpfpm sogo-mailcow: - image: ghcr.io/mailcow/sogo:1.136 + image: ghcr.io/mailcow/sogo:5.12.4 environment: - DBNAME=${DBNAME} - DBUSER=${DBUSER} @@ -681,3 +681,4 @@ volumes: sogo-web-vol-1: sogo-userdata-backup-vol-1: clamd-db-vol-1: + mlmmj-vol-1: From 88adb1adf559ac08cd6a66434783a520f1dfc78c Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 12 Nov 2025 09:54:35 +0100 Subject: [PATCH 082/109] remove dev docker volume from upstream --- docker-compose.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 317fba269..0522a6a2b 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -681,4 +681,3 @@ volumes: sogo-web-vol-1: sogo-userdata-backup-vol-1: clamd-db-vol-1: - mlmmj-vol-1: From 1b833be760a5e48b9f4d4eb97495ae9c9a4696c8 Mon Sep 17 00:00:00 2001 From: Claas Flint Date: Wed, 12 Nov 2025 10:06:36 +0100 Subject: [PATCH 083/109] Replace pigz with zstd for backup compression (#6897) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * Replace pigz with zstd for backup compression This change replaces pigz (parallel gzip) with zstd (Zstandard) as the compression algorithm for mailcow backups while maintaining full backward compatibility with existing .tar.gz backups. Benefits: - Better compression ratios (12-37% improvement in tests) - Improved compression speed with modern algorithm - Maintains rsyncable functionality for incremental backups - Full backward compatibility for restoring old .tar.gz backups - Wide industry adoption and active development Changes: - Backup compression: pigz --rsyncable -p → zstd --rsyncable -T - Backup decompression: pigz -d -p → zstd -d -T - File extensions: .tar.gz → .tar.zst - Added get_archive_info() function for intelligent format detection - Updated backup Dockerfile to install zstd alongside pigz - Restore function now auto-detects and handles both formats - Updated FILE_SELECTION regex to recognize both .tar.zst and .tar.gz - Updated comments to reflect new file extension Backward Compatibility: - Restore automatically detects .tar.zst (preferred) or .tar.gz (legacy) - Existing .tar.gz backups can still be restored without issues - pigz remains installed in backup image for legacy support - Graceful fallback if backup file format not found Testing: - Added comprehensive test suite (test_backup_and_restore.sh) - 12 automated tests covering all scenarios: * Backup creation (both formats) * Restore (both formats) * Format detection and priority * Error handling (missing files, empty dirs) * Content integrity verification * Multi-threading configuration * Large file compression (8.59 MB realistic data) Test Results: ✓ zstd compression working ✓ pigz compression working (legacy) ✓ zstd decompression working ✓ pigz decompression working (backward compatible) ✓ Archive detection working ✓ Content integrity verified ✓ Format priority correct (.tar.zst preferred) ✓ Error handling for missing files ✓ Error handling for empty directories ✓ Multi-threading configuration verified ✓ Large file compression: 37.05% improvement ✓ Small file compression: 12.18% improvement * move testing script into development folder --------- Co-authored-by: DerLinkman --- data/Dockerfiles/backup/Dockerfile | 2 +- helper-scripts/backup_and_restore.sh | 123 +++++-- .../dev_tests/test_backup_and_restore.sh | 301 ++++++++++++++++++ 3 files changed, 390 insertions(+), 36 deletions(-) create mode 100755 helper-scripts/dev_tests/test_backup_and_restore.sh diff --git a/data/Dockerfiles/backup/Dockerfile b/data/Dockerfiles/backup/Dockerfile index 6234e725b..7f989c399 100644 --- a/data/Dockerfiles/backup/Dockerfile +++ b/data/Dockerfiles/backup/Dockerfile @@ -1,3 +1,3 @@ FROM debian:bookworm-slim -RUN apt update && apt install pigz -y --no-install-recommends \ No newline at end of file +RUN apt update && apt install pigz zstd -y --no-install-recommends \ No newline at end of file diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh index c7615c294..7b75272cf 100755 --- a/helper-scripts/backup_and_restore.sh +++ b/helper-scripts/backup_and_restore.sh @@ -110,32 +110,32 @@ function backup() { docker run --name mailcow-backup --rm \ -v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:ro,z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_vmail.tar.gz /vmail + ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="zstd --rsyncable -T${THREADS}" -Pcvpf /backup/backup_vmail.tar.zst /vmail ;;& crypt|all) docker run --name mailcow-backup --rm \ -v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:ro,z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_crypt.tar.gz /crypt + ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="zstd --rsyncable -T${THREADS}" -Pcvpf /backup/backup_crypt.tar.zst /crypt ;;& redis|all) docker exec $(docker ps -qf name=redis-mailcow) redis-cli -a ${REDISPASS} --no-auth-warning save docker run --name mailcow-backup --rm \ -v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:ro,z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_redis.tar.gz /redis + ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="zstd --rsyncable -T${THREADS}" -Pcvpf /backup/backup_redis.tar.zst /redis ;;& rspamd|all) docker run --name mailcow-backup --rm \ -v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:ro,z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_rspamd.tar.gz /rspamd + ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="zstd --rsyncable -T${THREADS}" -Pcvpf /backup/backup_rspamd.tar.zst /rspamd ;;& postfix|all) docker run --name mailcow-backup --rm \ -v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:ro,z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="pigz --rsyncable -p ${THREADS}" -Pcvpf /backup/backup_postfix.tar.gz /postfix + ${DEBIAN_DOCKER_IMAGE} /bin/tar --warning='no-file-ignored' --use-compress-program="zstd --rsyncable -T${THREADS}" -Pcvpf /backup/backup_postfix.tar.zst /postfix ;;& mysql|all) SQLIMAGE=$(grep -iEo '(mysql|mariadb)\:.+' ${COMPOSE_FILE}) @@ -154,7 +154,7 @@ function backup() { ${SQLIMAGE} /bin/sh -c "mariabackup --host mysql --user root --password ${DBROOT} --backup --rsync --target-dir=/backup_mariadb ; \ mariabackup --prepare --target-dir=/backup_mariadb ; \ chown -R 999:999 /backup_mariadb ; \ - /bin/tar --warning='no-file-ignored' --use-compress-program='gzip --rsyncable' -Pcvpf /backup/backup_mariadb.tar.gz /backup_mariadb ;" + /bin/tar --warning='no-file-ignored' --use-compress-program='zstd --rsyncable' -Pcvpf /backup/backup_mariadb.tar.zst /backup_mariadb ;" fi ;;& --delete-days) @@ -170,6 +170,19 @@ function backup() { done } +function get_archive_info() { + local backup_name="$1" + local location="$2" + + if [[ -f "${location}/${backup_name}.tar.zst" ]]; then + echo "${backup_name}.tar.zst|zstd -d -T${THREADS}" + elif [[ -f "${location}/${backup_name}.tar.gz" ]]; then + echo "${backup_name}.tar.gz|pigz -d -p ${THREADS}" + else + echo "" + fi +} + function restore() { for bin in docker; do if [[ -z $(which ${bin}) ]]; then @@ -199,10 +212,17 @@ function restore() { case "$1" in vmail) docker stop $(docker ps -qf name=dovecot-mailcow) - docker run -i --name mailcow-backup --rm \ - -v ${RESTORE_LOCATION}:/backup:z \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_vmail.tar.gz + ARCHIVE_INFO=$(get_archive_info "backup_vmail" "${RESTORE_LOCATION}") + if [[ -z "${ARCHIVE_INFO}" ]]; then + echo -e "\e[31mError: No backup file found for vmail (searched for .tar.zst and .tar.gz)\e[0m" + else + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) + docker run -i --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_vmail-vol-1$):/vmail:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} + fi docker start $(docker ps -aqf name=dovecot-mailcow) echo echo "In most cases it is not required to run a full resync, you can run the command printed below at any time after testing wether the restore process broke a mailbox:" @@ -218,31 +238,50 @@ function restore() { ;; redis) docker stop $(docker ps -qf name=redis-mailcow) - docker run -i --name mailcow-backup --rm \ - -v ${RESTORE_LOCATION}:/backup:z \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_redis.tar.gz + ARCHIVE_INFO=$(get_archive_info "backup_redis" "${RESTORE_LOCATION}") + if [[ -z "${ARCHIVE_INFO}" ]]; then + echo -e "\e[31mError: No backup file found for redis (searched for .tar.zst and .tar.gz)\e[0m" + else + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) + docker run -i --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_redis-vol-1$):/redis:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} + fi docker start $(docker ps -aqf name=redis-mailcow) ;; crypt) docker stop $(docker ps -qf name=dovecot-mailcow) - docker run -i --name mailcow-backup --rm \ - -v ${RESTORE_LOCATION}:/backup:z \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_crypt.tar.gz + ARCHIVE_INFO=$(get_archive_info "backup_crypt" "${RESTORE_LOCATION}") + if [[ -z "${ARCHIVE_INFO}" ]]; then + echo -e "\e[31mError: No backup file found for crypt (searched for .tar.zst and .tar.gz)\e[0m" + else + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) + docker run -i --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_crypt-vol-1$):/crypt:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} + fi docker start $(docker ps -aqf name=dovecot-mailcow) ;; rspamd) - if [[ $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then + ARCHIVE_INFO=$(get_archive_info "backup_rspamd" "${RESTORE_LOCATION}") + if [[ -z "${ARCHIVE_INFO}" ]]; then + echo -e "\e[31mError: No backup file found for rspamd (searched for .tar.zst and .tar.gz)\e[0m" + elif [[ $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then echo -e "\e[33mCould not find a architecture signature of the loaded backup... Maybe the backup was done before the multiarch update?" sleep 2 echo -e "Continuing anyhow. If rspamd is crashing upon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m" sleep 2 docker stop $(docker ps -qf name=rspamd-mailcow) + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) docker run -i --name mailcow-backup --rm \ -v ${RESTORE_LOCATION}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} docker start $(docker ps -aqf name=rspamd-mailcow) elif [[ $ARCH != $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') ]]; then echo -e "\e[31mThe Architecture of the backed up mailcow OS is different then your restoring mailcow OS..." @@ -250,19 +289,28 @@ function restore() { echo -e "Skipping rspamd due to compatibility issues!\e[0m" else docker stop $(docker ps -qf name=rspamd-mailcow) + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) docker run -i --name mailcow-backup --rm \ -v ${RESTORE_LOCATION}:/backup:z \ -v $(docker volume ls -qf name=^${CMPS_PRJ}_rspamd-vol-1$):/rspamd:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_rspamd.tar.gz + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} docker start $(docker ps -aqf name=rspamd-mailcow) fi ;; postfix) docker stop $(docker ps -qf name=postfix-mailcow) - docker run -i --name mailcow-backup --rm \ - -v ${RESTORE_LOCATION}:/backup:z \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:z \ - ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -Pxvf /backup/backup_postfix.tar.gz + ARCHIVE_INFO=$(get_archive_info "backup_postfix" "${RESTORE_LOCATION}") + if [[ -z "${ARCHIVE_INFO}" ]]; then + echo -e "\e[31mError: No backup file found for postfix (searched for .tar.zst and .tar.gz)\e[0m" + else + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) + docker run -i --name mailcow-backup --rm \ + -v ${RESTORE_LOCATION}:/backup:z \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_postfix-vol-1$):/postfix:z \ + ${DEBIAN_DOCKER_IMAGE} /bin/tar --use-compress-program="${DECOMPRESS_PROG}" -Pxvf /backup/${ARCHIVE_FILE} + fi docker start $(docker ps -aqf name=postfix-mailcow) ;; mysql|mariadb) @@ -305,14 +353,19 @@ function restore() { echo Restoring... && \ gunzip < backup/backup_mysql.gz | mysql -uroot && \ mysql -uroot -e SHUTDOWN;" - elif [[ -f "${RESTORE_LOCATION}/backup_mariadb.tar.gz" ]]; then - docker run --name mailcow-backup --rm \ - -v $(docker volume ls -qf name=^${CMPS_PRJ}_mysql-vol-1$):/backup_mariadb/:rw,z \ - --entrypoint= \ - -v ${RESTORE_LOCATION}:/backup:z \ - ${SQLIMAGE} /bin/bash -c "shopt -s dotglob ; \ - /bin/rm -rf /backup_mariadb/* ; \ - /bin/tar -Pxvzf /backup/backup_mariadb.tar.gz" + else + ARCHIVE_INFO=$(get_archive_info "backup_mariadb" "${RESTORE_LOCATION}") + if [[ -n "${ARCHIVE_INFO}" ]]; then + ARCHIVE_FILE=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f1) + DECOMPRESS_PROG=$(echo "${ARCHIVE_INFO}" | cut -d'|' -f2) + docker run --name mailcow-backup --rm \ + -v $(docker volume ls -qf name=^${CMPS_PRJ}_mysql-vol-1$):/backup_mariadb/:rw,z \ + --entrypoint= \ + -v ${RESTORE_LOCATION}:/backup:z \ + ${SQLIMAGE} /bin/bash -c "shopt -s dotglob ; \ + /bin/rm -rf /backup_mariadb/* ; \ + /bin/tar --use-compress-program='${DECOMPRESS_PROG}' -Pxvf /backup/${ARCHIVE_FILE}" + fi fi echo "Modifying mailcow.conf..." source ${RESTORE_LOCATION}/mailcow.conf @@ -363,8 +416,8 @@ elif [[ ${1} == "restore" ]]; then fi echo "[ 0 ] - all" - # find all files in folder with *.gz extension, print their base names, remove backup_, remove .tar (if present), remove .gz - FILE_SELECTION[0]=$(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 \( -type d -o -type f \) \( -name '*.gz' -o -name 'mysql' \) -printf '%f\n' | sed 's/backup_*//' | sed 's/\.[^.]*$//' | sed 's/\.[^.]*$//') + # find all files in folder with *.zst or *.gz extension, print their base names, remove backup_, remove .tar (if present), remove .zst/.gz + FILE_SELECTION[0]=$(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 \( -type d -o -type f \) \( -name '*.zst' -o -name '*.gz' -o -name 'mysql' \) -printf '%f\n' | sed 's/backup_*//' | sed 's/\.[^.]*$//' | sed 's/\.[^.]*$//' | sort -u) for file in $(ls -f "${FOLDER_SELECTION[${input_sel}]}"); do if [[ ${file} =~ vmail ]]; then echo "[ ${i} ] - Mail directory (/var/vmail)" diff --git a/helper-scripts/dev_tests/test_backup_and_restore.sh b/helper-scripts/dev_tests/test_backup_and_restore.sh new file mode 100755 index 000000000..3e39d0dbf --- /dev/null +++ b/helper-scripts/dev_tests/test_backup_and_restore.sh @@ -0,0 +1,301 @@ +#!/usr/bin/env bash + +# Test script for backup_and_restore.sh +# Tests backward compatibility with .tar.gz and new .tar.zst format + +set -e + +SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" && pwd )" +BACKUP_IMAGE="${BACKUP_IMAGE:-ghcr.io/mailcow/backup:latest}" +TEST_DIR="/tmp/mailcow_backup_test_$$" +THREADS=2 + +echo "=== Mailcow Backup & Restore Test Suite ===" +echo "Test directory: ${TEST_DIR}" +echo "Backup image: ${BACKUP_IMAGE}" +echo "" + +# Cleanup function +cleanup() { + echo "Cleaning up test files..." + rm -rf "${TEST_DIR}" + docker rmi mailcow-backup-test 2>/dev/null || true +} +trap cleanup EXIT + +# Create test directory structure +mkdir -p "${TEST_DIR}"/{test_data,backup_zst,backup_gz,restore_zst,restore_gz,backup_large_zst,backup_large_gz} +echo "Test data for mailcow backup compatibility test" > "${TEST_DIR}/test_data/test.txt" +echo "Additional file to verify complete restore" > "${TEST_DIR}/test_data/test2.txt" + +# Build test backup image with zstd support +echo "=== Building backup image with zstd support ===" +docker build -t mailcow-backup-test "${SCRIPT_DIR}/../data/Dockerfiles/backup/" || { + echo "ERROR: Failed to build backup image" + exit 1 +} + +# Test 1: Create .tar.zst backup +echo "" +echo "=== Test 1: Creating .tar.zst backup ===" +docker run --rm \ + -w /data \ + -v "${TEST_DIR}/test_data:/data:ro" \ + -v "${TEST_DIR}/backup_zst:/backup" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="zstd --rsyncable -T${THREADS}" \ + -cvpf /backup/backup_test.tar.zst . \ + > /dev/null +echo "✓ .tar.zst backup created: $(ls -lh ${TEST_DIR}/backup_zst/backup_test.tar.zst | awk '{print $5}')" + +# Test 2: Create .tar.gz backup +echo "" +echo "=== Test 2: Creating .tar.gz backup (legacy) ===" +docker run --rm \ + -w /data \ + -v "${TEST_DIR}/test_data:/data:ro" \ + -v "${TEST_DIR}/backup_gz:/backup" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="pigz --rsyncable -p ${THREADS}" \ + -cvpf /backup/backup_test.tar.gz . \ + > /dev/null +echo "✓ .tar.gz backup created: $(ls -lh ${TEST_DIR}/backup_gz/backup_test.tar.gz | awk '{print $5}')" + +# Test 3: Test get_archive_info function +echo "" +echo "=== Test 3: Testing get_archive_info function ===" + +# Extract and test the function directly +get_archive_info() { + local backup_name="$1" + local location="$2" + + if [[ -f "${location}/${backup_name}.tar.zst" ]]; then + echo "${backup_name}.tar.zst|zstd -d -T${THREADS}" + elif [[ -f "${location}/${backup_name}.tar.gz" ]]; then + echo "${backup_name}.tar.gz|pigz -d -p ${THREADS}" + else + echo "" + fi +} + +# Test with .tar.zst +result=$(get_archive_info "backup_test" "${TEST_DIR}/backup_zst") +if [[ "${result}" =~ "zstd" ]]; then + echo "✓ Correctly detects .tar.zst and returns zstd decompressor" +else + echo "✗ Failed to detect .tar.zst" + exit 1 +fi + +# Test with .tar.gz +result=$(get_archive_info "backup_test" "${TEST_DIR}/backup_gz") +if [[ "${result}" =~ "pigz" ]]; then + echo "✓ Correctly detects .tar.gz and returns pigz decompressor" +else + echo "✗ Failed to detect .tar.gz" + exit 1 +fi + +# Test with no file +result=$(get_archive_info "backup_test" "${TEST_DIR}") +if [[ -z "${result}" ]]; then + echo "✓ Correctly returns empty when no backup file found" +else + echo "✗ Should return empty but got: ${result}" + exit 1 +fi + +# Test 4: Restore from .tar.zst +echo "" +echo "=== Test 4: Restoring from .tar.zst ===" +docker run --rm \ + -w /restore \ + -v "${TEST_DIR}/backup_zst:/backup:ro" \ + -v "${TEST_DIR}/restore_zst:/restore" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="zstd -d -T${THREADS}" -xvpf /backup/backup_test.tar.zst \ + > /dev/null 2>&1 + +if [[ -f "${TEST_DIR}/restore_zst/test.txt" ]] && \ + [[ -f "${TEST_DIR}/restore_zst/test2.txt" ]]; then + echo "✓ Successfully restored from .tar.zst" +else + echo "✗ Failed to restore from .tar.zst" + ls -la "${TEST_DIR}/restore_zst/" || true + exit 1 +fi + +# Test 5: Restore from .tar.gz +echo "" +echo "=== Test 5: Restoring from .tar.gz (backward compatibility) ===" +docker run --rm \ + -w /restore \ + -v "${TEST_DIR}/backup_gz:/backup:ro" \ + -v "${TEST_DIR}/restore_gz:/restore" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="pigz -d -p ${THREADS}" -xvpf /backup/backup_test.tar.gz \ + > /dev/null 2>&1 + +if [[ -f "${TEST_DIR}/restore_gz/test.txt" ]] && \ + [[ -f "${TEST_DIR}/restore_gz/test2.txt" ]]; then + echo "✓ Successfully restored from .tar.gz (backward compatible)" +else + echo "✗ Failed to restore from .tar.gz" + ls -la "${TEST_DIR}/restore_gz/" || true + exit 1 +fi + +# Test 6: Verify content integrity +echo "" +echo "=== Test 6: Verifying content integrity ===" +original_content=$(cat "${TEST_DIR}/test_data/test.txt") +zst_content=$(cat "${TEST_DIR}/restore_zst/test.txt") +gz_content=$(cat "${TEST_DIR}/restore_gz/test.txt") + +if [[ "${original_content}" == "${zst_content}" ]] && \ + [[ "${original_content}" == "${gz_content}" ]]; then + echo "✓ Content integrity verified for both formats" +else + echo "✗ Content mismatch detected" + exit 1 +fi + +# Test 7: Compare compression ratios +echo "" +echo "=== Test 7: Compression comparison ===" +zst_size=$(stat -f%z "${TEST_DIR}/backup_zst/backup_test.tar.zst" 2>/dev/null || stat -c%s "${TEST_DIR}/backup_zst/backup_test.tar.zst") +gz_size=$(stat -f%z "${TEST_DIR}/backup_gz/backup_test.tar.gz" 2>/dev/null || stat -c%s "${TEST_DIR}/backup_gz/backup_test.tar.gz") +improvement=$(echo "scale=2; (${gz_size} - ${zst_size}) * 100 / ${gz_size}" | bc) + +echo " Small files - .tar.gz size: ${gz_size} bytes" +echo " Small files - .tar.zst size: ${zst_size} bytes" +echo " Small files - Improvement: ${improvement}% smaller with zstd" + +# Test 8: Error handling - missing backup file +echo "" +echo "=== Test 8: Error handling - Missing backup file ===" +result=$(get_archive_info "nonexistent_backup" "${TEST_DIR}/backup_zst") +if [[ -z "${result}" ]]; then + echo "✓ Correctly handles missing backup files" +else + echo "✗ Should return empty for missing files" + exit 1 +fi + +# Test 9: Error handling - Empty directory +echo "" +echo "=== Test 9: Error handling - Empty directory ===" +mkdir -p "${TEST_DIR}/empty_dir" +result=$(get_archive_info "backup_test" "${TEST_DIR}/empty_dir") +if [[ -z "${result}" ]]; then + echo "✓ Correctly handles empty directories" +else + echo "✗ Should return empty for empty directories" + exit 1 +fi + +# Test 10: Priority test - .tar.zst preferred over .tar.gz +echo "" +echo "=== Test 10: Format priority - .tar.zst preferred ===" +mkdir -p "${TEST_DIR}/both_formats" +touch "${TEST_DIR}/both_formats/backup_test.tar.gz" +touch "${TEST_DIR}/both_formats/backup_test.tar.zst" +result=$(get_archive_info "backup_test" "${TEST_DIR}/both_formats") +if [[ "${result}" =~ "zstd" ]]; then + echo "✓ Correctly prefers .tar.zst when both formats exist" +else + echo "✗ Should prefer .tar.zst over .tar.gz" + exit 1 +fi + +# Test 11: Large file compression test +echo "" +echo "=== Test 11: Large file compression test ===" +mkdir -p "${TEST_DIR}/large_data" +# Create ~10MB of compressible data (log-like content) +for i in {1..50000}; do + echo "[$(date '+%Y-%m-%d %H:%M:%S')] INFO: Processing email message $i from user@example.com to recipient@domain.com" >> "${TEST_DIR}/large_data/maillog.txt" + echo "[$(date '+%Y-%m-%d %H:%M:%S')] DEBUG: SMTP connection established from 192.168.1.$((i % 255))" >> "${TEST_DIR}/large_data/maillog.txt" +done 2>/dev/null + +# Get size (portable: works on Linux and macOS) +if du --version 2>/dev/null | grep -q GNU; then + original_size=$(du -sb "${TEST_DIR}/large_data" | cut -f1) +else + # macOS + original_size=$(find "${TEST_DIR}/large_data" -type f -exec stat -f%z {} \; | awk '{sum+=$1} END {print sum}') +fi +echo " Original data size: $(echo "scale=2; ${original_size} / 1024 / 1024" | bc) MB" + +# Backup with zstd +docker run --rm \ + -w /data \ + -v "${TEST_DIR}/large_data:/data:ro" \ + -v "${TEST_DIR}/backup_large_zst:/backup" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="zstd --rsyncable -T${THREADS}" \ + -cvpf /backup/backup_large.tar.zst . \ + > /dev/null 2>&1 + +# Backup with pigz +docker run --rm \ + -w /data \ + -v "${TEST_DIR}/large_data:/data:ro" \ + -v "${TEST_DIR}/backup_large_gz:/backup" \ + mailcow-backup-test \ + /bin/tar --use-compress-program="pigz --rsyncable -p ${THREADS}" \ + -cvpf /backup/backup_large.tar.gz . \ + > /dev/null 2>&1 + +zst_large_size=$(stat -f%z "${TEST_DIR}/backup_large_zst/backup_large.tar.zst" 2>/dev/null || stat -c%s "${TEST_DIR}/backup_large_zst/backup_large.tar.zst" 2>/dev/null || echo "0") +gz_large_size=$(stat -f%z "${TEST_DIR}/backup_large_gz/backup_large.tar.gz" 2>/dev/null || stat -c%s "${TEST_DIR}/backup_large_gz/backup_large.tar.gz" 2>/dev/null || echo "0") + +if [[ ${zst_large_size} -gt 0 ]] && [[ ${gz_large_size} -gt 0 ]]; then + large_improvement=$(echo "scale=2; (${gz_large_size} - ${zst_large_size}) * 100 / ${gz_large_size}" | bc) + + echo " .tar.gz compressed: $(echo "scale=2; ${gz_large_size} / 1024 / 1024" | bc) MB" + echo " .tar.zst compressed: $(echo "scale=2; ${zst_large_size} / 1024 / 1024" | bc) MB" + echo " Improvement: ${large_improvement}% smaller with zstd" +else + echo " ✗ Failed to get file sizes" + exit 1 +fi + +if [[ $(echo "${large_improvement} > 0" | bc) -eq 1 ]]; then + echo "✓ zstd provides better compression on realistic data" +else + echo "⚠ zstd compression similar or worse than gzip (unusual but not critical)" +fi + +# Test 12: Thread scaling test +echo "" +echo "=== Test 12: Multi-threading verification ===" +# This test verifies that different thread counts work (not measuring speed difference) +for thread_count in 1 4; do + THREADS=${thread_count} + result=$(get_archive_info "backup_test" "${TEST_DIR}/backup_zst") + if [[ "${result}" =~ "-T${thread_count}" ]]; then + echo "✓ Thread count ${thread_count} correctly configured" + else + echo "✗ Thread count not properly applied" + exit 1 + fi +done + +echo "" +echo "=== All tests passed! ===" +echo "" +echo "Summary:" +echo " ✓ zstd compression working" +echo " ✓ pigz compression working (legacy)" +echo " ✓ zstd decompression working" +echo " ✓ pigz decompression working (backward compatible)" +echo " ✓ Archive detection working" +echo " ✓ Content integrity verified" +echo " ✓ Format priority correct (.tar.zst preferred)" +echo " ✓ Error handling for missing files" +echo " ✓ Error handling for empty directories" +echo " ✓ Multi-threading configuration verified" +echo " ✓ Large file compression: ${large_improvement}% improvement" +echo " ✓ Small file compression: ${improvement}% improvement" From 674b41ce082990c13177684ac5fc4b72f55ecdeb Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 12 Nov 2025 10:16:54 +0100 Subject: [PATCH 084/109] updated the Contributing Guidelines --- CONTRIBUTING.md | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index fae8f1d5f..d27c09de8 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -1,11 +1,11 @@ # Contribution Guidelines -**_Last modified on 15th August 2024_** +**_Last modified on 12th November 2025_** First of all, thank you for wanting to provide a bugfix or a new feature for the mailcow community, it's because of your help that the project can continue to grow! As we want to keep mailcow's development structured we setup these Guidelines which helps you to create your issue/pull request accordingly. -**PLEASE NOTE, THAT WE MIGHT CLOSE ISSUES/PULL REQUESTS IF THEY DON'T FULLFIL OUR WRITTEN GUIDELINES WRITTEN INSIDE THIS DOCUMENT**. So please check this guidelines before you propose a Issue/Pull Request. +**PLEASE NOTE, THAT WE WILL CLOSE ISSUES/PULL REQUESTS IF THEY DON'T FULLFIL OUR WRITTEN GUIDELINES WRITTEN INSIDE THIS DOCUMENT**. So please check this guidelines before you propose a Issue/Pull Request. ## Topics @@ -27,14 +27,18 @@ However, please note the following regarding pull requests: 6. Please **ALWAYS** create the actual pull request against the staging branch and **NEVER** directly against the master branch. *If you forget to do this, our moobot will remind you to switch the branch to staging.* 7. Wait for a merge commit: It may happen that we do not accept your pull request immediately or sometimes not at all for various reasons. Please do not be disappointed if this is the case. We always endeavor to incorporate any meaningful changes from the community into the mailcow project. 8. If you are planning larger and therefore more complex pull requests, it would be advisable to first announce this in a separate issue and then start implementing it after the idea has been accepted in order to avoid unnecessary frustration and effort! +9. If your PR requires a Docker image rebuild (changes to Dockerfiles or files in data/Dockerfiles/), update the image tag in docker-compose.yml. Use the base-image versioning (e.g. ghcr.io/mailcow/sogo:5.12.4 → :5.12.5 for version bumps; append a letter for patch fixes, e.g. :5.12.4a). Follow this scheme. --- ## Issue Reporting -**_Last modified on 15th August 2024_** +**_Last modified on 12th November 2025_** If you plan to report a issue within mailcow please read and understand the following rules: +### Security disclosures / Security-related fixes +- Security vulnerabilities and security fixes must always be reported confidentially first to the contact address specified in SECURITY.md before they are integrated, published, or publicly disclosed in issues/PRs. Please wait for a response from the specified contact to ensure coordinated and responsible disclosure. + ### Issue Reporting Guidelines 1. **ONLY** use the issue tracker for bug reports or improvement requests and NOT for support questions. For support questions you can either contact the [mailcow community on Telegram](https://docs.mailcow.email/#community-support-and-chat) or the mailcow team directly in exchange for a [support fee](https://docs.mailcow.email/#commercial-support). From 62d16c9e56918863c12e2d3115244615e2cfc8bf Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 13 Nov 2025 14:59:49 +0100 Subject: [PATCH 085/109] compose: changes cronjobs to regular cron syntax + fixed sogo creds for cronjobs (#6866) * cron: restructure cron timer to time on second (instead of random) * dovecot: fix clearance for cron.creds file --- data/Dockerfiles/dovecot/docker-entrypoint.sh | 7 ++-- docker-compose.yml | 32 +++++++++---------- 2 files changed, 20 insertions(+), 19 deletions(-) diff --git a/data/Dockerfiles/dovecot/docker-entrypoint.sh b/data/Dockerfiles/dovecot/docker-entrypoint.sh index fe2341bfa..e58abbb6a 100755 --- a/data/Dockerfiles/dovecot/docker-entrypoint.sh +++ b/data/Dockerfiles/dovecot/docker-entrypoint.sh @@ -204,16 +204,17 @@ EOF # Create random master Password for SOGo SSO RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1) echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass -# Creating additional creds file for SOGo notify crons (calendars, etc) -echo -n ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/cron.creds cat < /etc/dovecot/sogo-sso.conf # Autogenerated by mailcow passdb { driver = static - args = allow_real_nets=${IPV4_NETWORK}.248/32 password={plain}${RAND_PASS} + args = allow_nets=${IPV4_NETWORK}.248/32 password={plain}${RAND_PASS} } EOF +# Creating additional creds file for SOGo notify crons (calendars, etc) (dummy user, sso password) +echo -n ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/cron.creds + if [[ "${MASTER}" =~ ^([nN][oO]|[nN])+$ ]]; then # Toggling MASTER will result in a rebuild of containers, so the quota script will be recreated cat <<'EOF' > /usr/local/bin/quota_notify.py diff --git a/docker-compose.yml b/docker-compose.yml index 0522a6a2b..fef738365 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -188,10 +188,10 @@ services: restart: always labels: ofelia.enabled: "true" - ofelia.job-exec.phpfpm_keycloak_sync.schedule: "@every 1m" + ofelia.job-exec.phpfpm_keycloak_sync.schedule: "0 * * * * *" ofelia.job-exec.phpfpm_keycloak_sync.no-overlap: "true" ofelia.job-exec.phpfpm_keycloak_sync.command: "/bin/bash -c \"php /crons/keycloak-sync.php || exit 0\"" - ofelia.job-exec.phpfpm_ldap_sync.schedule: "@every 1m" + ofelia.job-exec.phpfpm_ldap_sync.schedule: "0 * * * * *" ofelia.job-exec.phpfpm_ldap_sync.no-overlap: "true" ofelia.job-exec.phpfpm_ldap_sync.command: "/bin/bash -c \"php /crons/ldap-sync.php || exit 0\"" networks: @@ -236,13 +236,13 @@ services: - sogo-userdata-backup-vol-1:/sogo_backup labels: ofelia.enabled: "true" - ofelia.job-exec.sogo_sessions.schedule: "@every 1m" + ofelia.job-exec.sogo_sessions.schedule: "0 * * * * *" ofelia.job-exec.sogo_sessions.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool -v expire-sessions $${SOGO_EXPIRE_SESSION} || exit 0\"" - ofelia.job-exec.sogo_ealarms.schedule: "@every 1m" + ofelia.job-exec.sogo_ealarms.schedule: "0 * * * * *" ofelia.job-exec.sogo_ealarms.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-ealarms-notify -p /etc/sogo/cron.creds || exit 0\"" - ofelia.job-exec.sogo_eautoreply.schedule: "@every 5m" - ofelia.job-exec.sogo_eautoreply.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/cron.creds || exit 0\"" - ofelia.job-exec.sogo_backup.schedule: "@every 24h" + ofelia.job-exec.sogo_eautoreply.schedule: "0 */5 * * * *" + ofelia.job-exec.sogo_eautoreply.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool update-autoreply -p /etc/sogo/sieve.creds || exit 0\"" + ofelia.job-exec.sogo_backup.schedule: "0 0 0 * * *" ofelia.job-exec.sogo_backup.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu sogo /usr/sbin/sogo-tool backup /sogo_backup ALL || exit 0\"" restart: always networks: @@ -252,7 +252,7 @@ services: - sogo dovecot-mailcow: - image: ghcr.io/mailcow/dovecot:2.35 + image: ghcr.io/mailcow/dovecot:2.3.21.1 depends_on: - mysql-mailcow - netfilter-mailcow @@ -310,22 +310,22 @@ services: tty: true labels: ofelia.enabled: "true" - ofelia.job-exec.dovecot_imapsync_runner.schedule: "@every 1m" + ofelia.job-exec.dovecot_imapsync_runner.schedule: "0 * * * * *" ofelia.job-exec.dovecot_imapsync_runner.no-overlap: "true" ofelia.job-exec.dovecot_imapsync_runner.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu nobody /usr/local/bin/imapsync_runner.pl || exit 0\"" - ofelia.job-exec.dovecot_trim_logs.schedule: "@every 1m" + ofelia.job-exec.dovecot_trim_logs.schedule: "0 * * * * *" ofelia.job-exec.dovecot_trim_logs.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/trim_logs.sh || exit 0\"" - ofelia.job-exec.dovecot_quarantine.schedule: "@every 20m" + ofelia.job-exec.dovecot_quarantine.schedule: "0 */20 * * * *" ofelia.job-exec.dovecot_quarantine.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/quarantine_notify.py || exit 0\"" - ofelia.job-exec.dovecot_clean_q_aged.schedule: "@every 24h" + ofelia.job-exec.dovecot_clean_q_aged.schedule: "0 0 0 * * *" ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\"" - ofelia.job-exec.dovecot_maildir_gc.schedule: "@every 30m" + ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *" ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\"" - ofelia.job-exec.dovecot_sarules.schedule: "@every 24h" + ofelia.job-exec.dovecot_sarules.schedule: "0 0 0 * * *" ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\"" - ofelia.job-exec.dovecot_fts.schedule: "@every 24h" + ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *" ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\"" - ofelia.job-exec.dovecot_repl_health.schedule: "@every 5m" + ofelia.job-exec.dovecot_repl_health.schedule: "0 */5 * * * *" ofelia.job-exec.dovecot_repl_health.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/repl_health.sh\"" ulimits: nproc: 65535 From 7313f996d321a8e6e19a054f62d95aff4cc32711 Mon Sep 17 00:00:00 2001 From: Peter Date: Thu, 13 Nov 2025 15:16:00 +0100 Subject: [PATCH 086/109] Update to trixie (#6907) --- data/Dockerfiles/backup/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/backup/Dockerfile b/data/Dockerfiles/backup/Dockerfile index 7f989c399..9ff6bbb13 100644 --- a/data/Dockerfiles/backup/Dockerfile +++ b/data/Dockerfiles/backup/Dockerfile @@ -1,3 +1,3 @@ -FROM debian:bookworm-slim +FROM debian:trixie-slim RUN apt update && apt install pigz zstd -y --no-install-recommends \ No newline at end of file From ae3ef391ee4bed52727274e04dca5f71091124a7 Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Thu, 13 Nov 2025 15:16:44 +0100 Subject: [PATCH 087/109] Remove deprecated 'X-XSS-Protection' header (#6871) --- data/conf/nginx/templates/sites-default.conf.j2 | 1 - 1 file changed, 1 deletion(-) diff --git a/data/conf/nginx/templates/sites-default.conf.j2 b/data/conf/nginx/templates/sites-default.conf.j2 index 23fe7b788..f3d734528 100644 --- a/data/conf/nginx/templates/sites-default.conf.j2 +++ b/data/conf/nginx/templates/sites-default.conf.j2 @@ -14,7 +14,6 @@ ssl_session_tickets off; add_header Strict-Transport-Security "max-age=15768000;"; add_header X-Content-Type-Options nosniff; -add_header X-XSS-Protection "1; mode=block"; add_header X-Robots-Tag none; add_header X-Download-Options noopen; add_header X-Frame-Options "SAMEORIGIN" always; From 7b29c1f30401942ed39950a514fd59e0b8b4694d Mon Sep 17 00:00:00 2001 From: Patrik Kernstock Date: Thu, 13 Nov 2025 15:19:11 +0100 Subject: [PATCH 088/109] Disable nginx server_tokens in http context (#6873) --- data/conf/nginx/templates/nginx.conf.j2 | 1 + 1 file changed, 1 insertion(+) diff --git a/data/conf/nginx/templates/nginx.conf.j2 b/data/conf/nginx/templates/nginx.conf.j2 index 4b32ff15b..08a85a144 100644 --- a/data/conf/nginx/templates/nginx.conf.j2 +++ b/data/conf/nginx/templates/nginx.conf.j2 @@ -13,6 +13,7 @@ events { http { include /etc/nginx/mime.types; default_type application/octet-stream; + server_tokens off; log_format main '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent "$http_referer" ' From 0413d268552b845916b94eda54bc3dba0ee12798 Mon Sep 17 00:00:00 2001 From: Josh <75700a85-1205-4740-aebf-4413a352e81b@otake.pw> Date: Thu, 13 Nov 2025 07:05:01 -0800 Subject: [PATCH 089/109] Allow making spam aliases permanent (#6888) * Allow making spam aliases permanent * added german translation * updated Spamalias Twig + Rename in Spam Alias * compose: update image tags to align to vendor version --------- Co-authored-by: DerLinkman --- data/Dockerfiles/phpfpm/docker-entrypoint.sh | 2 +- data/Dockerfiles/postfix/postfix.sh | 4 +-- data/web/inc/functions.mailbox.inc.php | 37 ++++++++++++++------ data/web/inc/init_db.inc.php | 5 +-- data/web/js/site/user.js | 22 ++++++++++-- data/web/lang/lang.de-de.json | 7 ++-- data/web/lang/lang.en-gb.json | 5 ++- data/web/lang/lang.es-es.json | 7 +++- data/web/lang/lang.ja-jp.json | 3 ++ data/web/templates/user/SpamAliases.twig | 14 ++++---- docker-compose.yml | 4 +-- 11 files changed, 80 insertions(+), 30 deletions(-) diff --git a/data/Dockerfiles/phpfpm/docker-entrypoint.sh b/data/Dockerfiles/phpfpm/docker-entrypoint.sh index 0d09ac5fc..d7fa15556 100755 --- a/data/Dockerfiles/phpfpm/docker-entrypoint.sh +++ b/data/Dockerfiles/phpfpm/docker-entrypoint.sh @@ -167,7 +167,7 @@ DELIMITER // CREATE EVENT clean_spamalias ON SCHEDULE EVERY 1 DAY DO BEGIN - DELETE FROM spamalias WHERE validity < UNIX_TIMESTAMP(); + DELETE FROM spamalias WHERE validity < UNIX_TIMESTAMP() AND permanent = 0; END; // DELIMITER ; diff --git a/data/Dockerfiles/postfix/postfix.sh b/data/Dockerfiles/postfix/postfix.sh index 0a6494ed6..0a8ed736e 100755 --- a/data/Dockerfiles/postfix/postfix.sh +++ b/data/Dockerfiles/postfix/postfix.sh @@ -390,7 +390,7 @@ hosts = unix:/var/run/mysqld/mysqld.sock dbname = ${DBNAME} query = SELECT goto FROM spamalias WHERE address='%s' - AND validity >= UNIX_TIMESTAMP() + AND (validity >= UNIX_TIMESTAMP() OR permanent != 0) EOF if [ ! -f /opt/postfix/conf/dns_blocklists.cf ]; then @@ -524,4 +524,4 @@ if [[ $? != 0 ]]; then else postfix -c /opt/postfix/conf start sleep 126144000 -fi \ No newline at end of file +fi diff --git a/data/web/inc/functions.mailbox.inc.php b/data/web/inc/functions.mailbox.inc.php index 7638c9bbf..d8e4e178a 100644 --- a/data/web/inc/functions.mailbox.inc.php +++ b/data/web/inc/functions.mailbox.inc.php @@ -49,6 +49,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { // Default to 1 yr $_data["validity"] = 8760; } + if (isset($_data["permanent"]) && filter_var($_data["permanent"], FILTER_VALIDATE_BOOL)) { + $permanent = 1; + } + else { + $permanent = 0; + } $domain = $_data['domain']; $description = $_data['description']; $valid_domains[] = mailbox('get', 'mailbox_details', $username)['domain']; @@ -65,13 +71,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { return false; } $validity = strtotime("+" . $_data["validity"] . " hour"); - $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `description`, `goto`, `validity`) VALUES - (:address, :description, :goto, :validity)"); + $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `description`, `goto`, `validity`, `permanent`) VALUES + (:address, :description, :goto, :validity, :permanent)"); $stmt->execute(array( ':address' => readable_random_string(rand(rand(3, 9), rand(3, 9))) . '.' . readable_random_string(rand(rand(3, 9), rand(3, 9))) . '@' . $domain, ':description' => $description, ':goto' => $username, - ':validity' => $validity + ':validity' => $validity, + ':permanent' => $permanent )); $_SESSION['return'][] = array( 'type' => 'success', @@ -2103,15 +2110,23 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { ); continue; } - if (empty($_data['validity'])) { + if (empty($_data['validity']) && empty($_data['permanent'])) { continue; } - $validity = round((int)time() + ($_data['validity'] * 3600)); - $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = :validity WHERE + if (isset($_data['permanent']) && filter_var($_data['permanent'], FILTER_VALIDATE_BOOL)) { + $permanent = 1; + $validity = 0; + } + else if (isset($_data['validity'])) { + $permanent = 0; + $validity = round((int)time() + ($_data['validity'] * 3600)); + } + $stmt = $pdo->prepare("UPDATE `spamalias` SET `validity` = :validity, `permanent` = :permanent WHERE `address` = :address"); $stmt->execute(array( ':address' => $address, - ':validity' => $validity + ':validity' => $validity, + ':permanent' => $permanent )); $_SESSION['return'][] = array( 'type' => 'success', @@ -4584,10 +4599,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { `description`, `validity`, `created`, - `modified` + `modified`, + `permanent` FROM `spamalias` WHERE `goto` = :username - AND `validity` >= :unixnow"); + AND (`validity` >= :unixnow + OR `permanent` != 0)"); $stmt->execute(array(':username' => $_data, ':unixnow' => time())); $tladata = $stmt->fetchAll(PDO::FETCH_ASSOC); return $tladata; @@ -5162,7 +5179,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) { $stmt = $pdo->prepare("SELECT COALESCE(SUM(`quota`), 0) as `in_use` FROM `mailbox` WHERE (`kind` = '' OR `kind` = NULL) AND `domain` = :domain AND `username` != :username"); $stmt->execute(array(':domain' => $row['domain'], ':username' => $_data)); $MailboxUsage = $stmt->fetch(PDO::FETCH_ASSOC); - $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`address`), 0) AS `sa_count` FROM `spamalias` WHERE `goto` = :address AND `validity` >= :unixnow"); + $stmt = $pdo->prepare("SELECT IFNULL(COUNT(`address`), 0) AS `sa_count` FROM `spamalias` WHERE `goto` = :address AND (`validity` >= :unixnow OR `permanent` != 0)"); $stmt->execute(array(':address' => $_data, ':unixnow' => time())); $SpamaliasUsage = $stmt->fetch(PDO::FETCH_ASSOC); $mailboxdata['max_new_quota'] = ($DomainQuota['quota'] * 1048576) - $MailboxUsage['in_use']; diff --git a/data/web/inc/init_db.inc.php b/data/web/inc/init_db.inc.php index b8ab85253..ffaf12093 100644 --- a/data/web/inc/init_db.inc.php +++ b/data/web/inc/init_db.inc.php @@ -4,7 +4,7 @@ function init_db_schema() try { global $pdo; - $db_version = "07102025_1015"; + $db_version = "10312025_0525"; $stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); @@ -554,7 +554,8 @@ function init_db_schema() "description" => "TEXT NOT NULL", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", - "validity" => "INT(11)" + "validity" => "INT(11)", + "permanent" => "TINYINT(1) NOT NULL DEFAULT '0'" ), "keys" => array( "primary" => array( diff --git a/data/web/js/site/user.js b/data/web/js/site/user.js index 10960c5d9..5eecf2080 100644 --- a/data/web/js/site/user.js +++ b/data/web/js/site/user.js @@ -175,6 +175,10 @@ jQuery(function($){ '
'; item.chkbox = ''; item.address = escapeHtml(item.address); + item.validity = { + value: item.validity, + permanent: item.permanent + }; } else { item.chkbox = ''; @@ -218,9 +222,21 @@ jQuery(function($){ title: lang.alias_valid_until, data: 'validity', defaultContent: '', - createdCell: function(td, cellData) { - createSortableDate(td, cellData) - } + render: function (data, type) { + var date = new Date(data.value ? data.value * 1000 : 0); + switch (type) { + case "sort": + if (data.permanent) { + return 0; + } + return date.getTime(); + default: + if (data.permanent) { + return lang.forever; + } + return date.toLocaleDateString(LOCALE, DATETIME_FORMAT); + } + }, }, { title: lang.created_on, diff --git a/data/web/lang/lang.de-de.json b/data/web/lang/lang.de-de.json index dbc6b2f93..762c055af 100644 --- a/data/web/lang/lang.de-de.json +++ b/data/web/lang/lang.de-de.json @@ -987,7 +987,7 @@ "sogo_visible": "Alias Sichtbarkeit in SOGo", "sogo_visible_n": "Alias in SOGo verbergen", "sogo_visible_y": "Alias in SOGo anzeigen", - "spam_aliases": "Temp. Alias", + "spam_aliases": "Spam-Alias", "stats": "Statistik", "status": "Status", "sync_jobs": "Synchronisationen", @@ -1281,7 +1281,9 @@ "encryption": "Verschlüsselung", "excludes": "Ausschlüsse", "expire_in": "Ungültig in", + "expire_never": "Niemals ungültig", "fido2_webauthn": "FIDO2/WebAuthn", + "forever": "Für immer", "force_pw_update": "Das Passwort für diesen Benutzer muss geändert werden, damit die Zugriffssperre auf die Groupware-Komponenten wieder freigeschaltet wird.", "from": "von", "generate": "generieren", @@ -1346,7 +1348,8 @@ "sogo_profile_reset": "SOGo-Profil zurücksetzen", "sogo_profile_reset_help": "Das Profil wird inklusive aller Kalender- und Kontaktdaten unwiederbringlich gelöscht.", "sogo_profile_reset_now": "Profil jetzt zurücksetzen", - "spam_aliases": "Temporäre E-Mail-Aliasse", + "spam_aliases": "Spam E-Mail-Aliasse", + "spam_aliases_info": "Ein Spam-Alias ist eine temporäre E-Mailadresse, die benutzt werden kann, um eine echte E-Mail Adressen zu schützen.
Optional kann eine Ablaufzeit gesetzt werden, sodass der Alias nach dem definierten Zeitraum automatisch deaktiviert wird, was missbrauchte oder geleakte Adressen effektiv entsorgt.", "spam_score_reset": "Auf Server-Standard zurücksetzen", "spamfilter": "Spamfilter", "spamfilter_behavior": "Bewertung", diff --git a/data/web/lang/lang.en-gb.json b/data/web/lang/lang.en-gb.json index d46e4606c..1e8525957 100644 --- a/data/web/lang/lang.en-gb.json +++ b/data/web/lang/lang.en-gb.json @@ -1288,7 +1288,9 @@ "encryption": "Encryption", "excludes": "Excludes", "expire_in": "Expire in", + "expire_never": "Never Expire", "fido2_webauthn": "FIDO2/WebAuthn", + "forever": "Forever", "force_pw_update": "You must set a new password to be able to access groupware related services.", "from": "from", "generate": "generate", @@ -1355,7 +1357,8 @@ "sogo_profile_reset": "Reset SOGo profile", "sogo_profile_reset_help": "This will destroy a user's SOGo profile and delete all contact and calendar data irretrievable.", "sogo_profile_reset_now": "Reset profile now", - "spam_aliases": "Temporary email aliases", + "spam_aliases": "Spam email aliases", + "spam_aliases_info": "A spam alias is a temporary email address that can be used to protect real email addresses.
Optionally, an expiration time can be set so that the alias is automatically deactivated after the defined period, effectively disposing of abused or leaked addresses.", "spam_score_reset": "Reset to server default", "spamfilter": "Spam filter", "spamfilter_behavior": "Rating", diff --git a/data/web/lang/lang.es-es.json b/data/web/lang/lang.es-es.json index f357b9a80..7d86973ac 100644 --- a/data/web/lang/lang.es-es.json +++ b/data/web/lang/lang.es-es.json @@ -1084,6 +1084,7 @@ "aliases_send_as_all": "No verificar permisos del remitente para los siguientes dominios (y sus aliases)", "change_password": "Cambiar contraseña", "create_syncjob": "Crear nuevo trabajo de sincronización", + "created_on": "Creado", "daily": "Cada día", "day": "Día", "description": "Descripción", @@ -1095,6 +1096,9 @@ "edit": "Editar", "encryption": "Cifrado", "excludes": "Excluye", + "expire_in": "Expirará en", + "expire_never": "Nunca expirará", + "forever": "Siempre", "hour": "Hora", "hourly": "Cada hora", "hours": "Horas", @@ -1115,7 +1119,8 @@ "shared_aliases": "Alias compartidos", "shared_aliases_desc": "Los alias compartidos no se ven afectados por la configuración específica del usuario, como el filtro de correo no deseado o la política de cifrado. Los filtros de spam correspondientes solo pueden ser realizados por un administrador como una política de dominio.", "sogo_profile_reset": "Resetear perfil SOGo", - "spam_aliases": "Alias de email temporales", + "spam_aliases": "Alias de email de spam", + "spam_aliases_info": "Un alias de spam es una dirección de correo electrónico temporal que se puede usar para proteger direcciones de correo electrónico reales.
Opcionalmente, se puede establecer un tiempo de expiración para que el alias se desactive automáticamente después del período definido, eliminando efectivamente las direcciones abusadas o filtradas.", "spamfilter": "Filtro anti-spam", "spamfilter_behavior": "Clasificación", "spamfilter_bl": "Lista negra", diff --git a/data/web/lang/lang.ja-jp.json b/data/web/lang/lang.ja-jp.json index 74c04248c..6dfa5d87b 100644 --- a/data/web/lang/lang.ja-jp.json +++ b/data/web/lang/lang.ja-jp.json @@ -1187,6 +1187,7 @@ "created_on": "作成日", "daily": "毎日", "day": "日", + "description": "説明", "delete_ays": "削除プロセスを確認してください。", "direct_aliases": "直接エイリアスアドレス", "direct_aliases_desc": "直接エイリアスアドレスは、スパムフィルターおよびTLSポリシー設定の影響を受けます。", @@ -1201,7 +1202,9 @@ "encryption": "暗号化", "excludes": "除外", "expire_in": "有効期限まで", + "expire_never": "有効期限なし", "fido2_webauthn": "FIDO2/WebAuthn", + "forever": "有効期限なし", "force_pw_update": "グループウェア関連サービスにアクセスするには、新しいパスワードを必ず設定する必要があります。", "from": "送信元", "generate": "生成", diff --git a/data/web/templates/user/SpamAliases.twig b/data/web/templates/user/SpamAliases.twig index 83b056c34..466c283c1 100644 --- a/data/web/templates/user/SpamAliases.twig +++ b/data/web/templates/user/SpamAliases.twig @@ -8,6 +8,7 @@
+

{{ lang.user.spam_aliases_info|raw }}

@@ -18,12 +19,13 @@ {{ lang.mailbox.toggle_all }} {{ lang.mailbox.quick_actions }} diff --git a/docker-compose.yml b/docker-compose.yml index fef738365..f7390c797 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -117,7 +117,7 @@ services: - rspamd php-fpm-mailcow: - image: ghcr.io/mailcow/phpfpm:1.94 + image: ghcr.io/mailcow/phpfpm:8.2.29 command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" depends_on: - redis-mailcow @@ -339,7 +339,7 @@ services: - dovecot postfix-mailcow: - image: ghcr.io/mailcow/postfix:1.81 + image: ghcr.io/mailcow/postfix:3.7.11 depends_on: mysql-mailcow: condition: service_started From 98320061410e6795debe93456a5362edd0c3f379 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 17 Nov 2025 23:23:07 +0100 Subject: [PATCH 090/109] Translations update from Weblate (#6916) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.si-si.json Co-authored-by: Matjaž Tekavec * [Web] Updated lang.ru-ru.json Co-authored-by: Habetdin <15926758+Habetdin@users.noreply.github.com> * [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json Co-authored-by: Monika Bark Co-authored-by: Peter Co-authored-by: milkmaker --------- Co-authored-by: Matjaž Tekavec Co-authored-by: Habetdin <15926758+Habetdin@users.noreply.github.com> Co-authored-by: Monika Bark Co-authored-by: Peter --- data/web/lang/lang.pl-pl.json | 157 ++++++++++++++++++++++++++-------- data/web/lang/lang.ru-ru.json | 38 ++++++-- data/web/lang/lang.si-si.json | 13 +-- 3 files changed, 159 insertions(+), 49 deletions(-) diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index b08b115a8..61a17a749 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -85,7 +85,7 @@ "delete2": "Usuń wiadomości w miejscu docelowym, które nie znajdują się w źródle", "destination": "Miejsce docelowe", "disable_login": "Nie pozwalaj na logowanie(poczta przychodząca jest nadal akceptowana)", - "domain_matches_hostname": "Domena %s pasuje do nazwy hosta", + "domain_matches_hostname": "Domena pasuje do nazwy hosta", "dry": "Symulacja synchronizacji", "gal": "Globalna lista adresów", "gal_info": "GAL zawiera wszystkie obiekty domeny i nie może być edytowany przez żadnego użytkownika. Wolne/zajęte logi w SOGo bedą nidostępne, jeśli są wyłączone! Uruchom ponownie SOGo, aby zastosować zmiany.", @@ -139,7 +139,7 @@ "f2b_max_attempts": "Max. ilość prób", "f2b_parameters": "Parametry Fail2ban", "f2b_retry_window": "Spróbuj ponownie (s) dla max. ilości prób", - "f2b_whitelist": "Biała lista sieci/hosty", + "f2b_whitelist": "Dozwolone sieci/hosty", "filter_table": "Tabela filtru", "forwarding_hosts": "Hosty przekazujące", "forwarding_hosts_add_hint": "Możesz albo wyszczególnić adresy IPv4/IPv6, sieci w notacji CIDR, nazwy hostów (które zostaną rozłożone na adresy IP), albo nazwy domen (które zostaną rozłożone na adresy IP poprzez sprawdzanie rekordów SPF lub, w razie ich braku, rekordów MX).", @@ -205,7 +205,7 @@ "convert_html_to_text": "Konwertuj HTML na zwykły tekst", "copy_to_clipboard": "Tekst skopiowany do schowka!", "cors_settings": "Ustawienia CORS", - "credentials_transport_warning": "Ostrzeżenie: Dodanie nowego wpisu mapy transportu spowoduje aktualizację danych uwierzytelniających dla wszystkich wpisów z pasującą kolumną hop.", + "credentials_transport_warning": "Ostrzeżenie: Dodanie nowego wpisu mapy transportu spowoduje aktualizację danych uwierzytelniających dla wszystkich wpisów z pasującą kolumną hop.", "customer_id": "Identyfikator klienta", "customize": "Dostosuj", "login_page": "Strona logowania", @@ -226,7 +226,7 @@ "f2b_ban_time_increment": "Czas zakazu jest zwiększany z każdym zakazem", "f2b_blacklist": "Lista odrzuconych sieci/hostów", "f2b_filter": "Filtry Regex", - "f2b_list_info": "Odrzucony host lub sieć zawsze będzie przewyższać jednostkę zezwalającą.Zastosowanie aktualizacji listy zajmie kilka sekund.", + "f2b_list_info": "Odrzucony host lub sieć zawsze będzie przewyższać jednostkę zezwalającą.Zastosowanie aktualizacji listy zajmie kilka sekund.", "f2b_manage_external": "Zarządzaj Fail2Ban zewnętrznie", "f2b_manage_external_info": "Fail2ban nadal będzie utrzymywać listę banów, ale nie będzie aktywnie ustalać zasad blokowania ruchu. Użyj wygenerowane listy banów poniżej, aby zewnętrznie zablokować ruch.", "f2b_max_ban_time": "Max. czas bana (s)", @@ -240,7 +240,7 @@ "generate": "Generuj", "guid": "GUID - unikalny identyfikator instancji", "guid_and_license": "GUID & licencja", - "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.
\n\nKażdy hash jest oznaczony indywidualnym kolorem.", + "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.
\n\n Każdy hash jest oznaczony indywidualnym kolorem.", "help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)", "html": "HTML", "iam": "Dostawca tożsamości", @@ -310,7 +310,7 @@ "oauth2_add_client": "Dodaj klienta OAuth2", "oauth2_client_id": "ID klienta", "oauth2_client_secret": "Sekret klienta", - "oauth2_info": "Implementacja OAuth2 obsługuje typ grantu \"Kod autoryzacji\" i wydaje tokeny odświeżania.
\nSerwer automatycznie wydaje również nowe tokeny odświeżania, po użyciu tokena odświeżania.

\n• Domyślnym zakresem jest profil. Tylko użytkownicy skrzynek pocztowych mogą być uwierzytelniani w OAuth2. Jeśli parametr zakresu zostanie pominięty, wraca do profil.
\n\nParametr state musi zostać wysłany przez klienta w ramach żądania autoryzacji.

>\nŚcieżki zapytań do API OAuth2:
\n
    \nPunkt końcowy autoryzacji: /autoryzuj\nPunkt końcowy tokena: /autoth/token\nStrona zasobów: /prawo/profil>\n
\nRegeneracja tajemnicy klienta nie spowoduje wygaśnięcia istniejących kodów autoryzacyjnych, ale nie odnowi ich tokena.

\nOdwołanie tokenów klienta spowoduje natychmiastowe zakończenie wszystkich aktywnych sesji. Wszyscy klienci muszą się ponownie uwierzytelnić.", + "oauth2_info": "Implementacja OAuth2 obsługuje typ grantu \"Kod autoryzacji\" i wydaje tokeny odświeżania.
\nSerwer automatycznie wydaje również nowe tokeny odświeżania, po użyciu tokena odświeżania.

\n• Domyślnym zakresem jest profil. Tylko użytkownicy skrzynek pocztowych mogą być uwierzytelniani w OAuth2. Jeśli parametr zakresu zostanie pominięty, wraca do profil.
\n\nParametr state musi zostać wysłany przez klienta w ramach żądania autoryzacji.

>\nŚcieżki zapytań do API OAuth2:
\n
    \nPunkt końcowy autoryzacji\n/oauth/authorize
  • Token endpoint: /oauth/token
  • Resource page: /oauth/profile
  • \n
\nRegeneracja tajemnicy klienta nie spowoduje wygaśnięcia istniejących kodów autoryzacyjnych, ale nie odnowi ich tokena.

\nOdwołanie tokenów klienta spowoduje natychmiastowe zakończenie wszystkich aktywnych sesji. Wszyscy klienci muszą się ponownie uwierzytelnić.", "oauth2_redirect_uri": "Przekieruj URI", "oauth2_renew_secret": "Wygeneruj sekret nowego klienta", "oauth2_revoke_tokens": "Unieważnij wszystkie tokeny klienta", @@ -368,7 +368,7 @@ "rsetting_desc": "Krótki opis", "rsetting_no_selection": "Proszę zaznaczyć regułę", "rsetting_none": "Brak dostępnych reguł", - "rsettings_insert_preset": "Wstaw przykład presetowany \"%s\"", + "rsettings_insert_preset": "Wstaw przykładowy preset", "rsettings_preset_1": "Wyłącz wszystkie z wyjątkiem DKIM i limitu stawek dla uwierzytelnionych użytkowników", "rsettings_preset_2": "Administratorzy poczty pozwalają na spam", "rsettings_preset_3": "Zezwalaj tylko określonym nadawcom na skrzynkę pocztową (tj. używaj tylko jako wewnętrznej skrzynki pocztowej)", @@ -418,21 +418,21 @@ "alias_domain_invalid": "Alias domeny nieprawidłowy", "alias_empty": "Alias nie może być pusty", "alias_goto_identical": "Alias i Idź do nie mogą być identyczne", - "alias_invalid": "Alias nieprawidłowy", + "alias_invalid": "Adres aliasu jest nieprawidłowy", "aliasd_targetd_identical": "Alias domeny nie może być identyczny z domeną docelową", "aliases_in_use": "Maks. liczba aliasów musi być większa od lub równa %d", "description_invalid": "Nieprawidłowy opis źródła", "dkim_domain_or_sel_invalid": "Nieprawidłowa domena lub selektor DKIM", - "domain_exists": "Domena %s już istnieje", + "domain_exists": "Domena już istnieje", "domain_invalid": "Nazwa domeny jest pusta lub nieprawidłowa", "domain_not_empty": "Nie można usunąć niepustej domeny", - "domain_not_found": "Nie znaleziono domeny %s", - "domain_quota_m_in_use": "Limit domeny musi być większy lub równy do %s MiB", + "domain_not_found": "Nie znaleziono domeny", + "domain_quota_m_in_use": "Limit domeny musi być większy lub równy do MiB", "goto_empty": "Adres alias musi zawierać co najmniej jeden prawidłowy adres goto", "goto_invalid": "Adres Idź do jest nieprawidłowy", - "is_alias": "%s został już podany jako alias", - "is_alias_or_mailbox": "%s podano wcześniej jako alias lub skrzynkę", - "is_spam_alias": "%s podano wcześniej jako alias dla spam", + "is_alias": "został już podany jako alias", + "is_alias_or_mailbox": "jest już znany jako alias, skrzynka pocztowa lub adres aliasu rozwinięty z domeny aliasu.", + "is_spam_alias": "jest już znany jako tymczasowy adres aliasu (adres aliasu antyspamowego).", "last_key": "Nie można usunąć ostatniego klucza, zamiast tego należy wyłączyć TFA.", "login_failed": "Logowanie nie powiodło się", "mailbox_invalid": "Nieprawidłowa nazwa skrzynki", @@ -456,34 +456,34 @@ "sender_acl_invalid": "ACL Nadawcy jest nieprawidłowy", "target_domain_invalid": "Domena Idź do jest nieprawidłowa", "targetd_not_found": "Nie znaleziono domeny docelowej", - "username_invalid": "Nie można użyć nazwy użytkownika", + "username_invalid": "Nie można użyć tej nazwy użytkownika", "validity_missing": "Proszę wyznaczyć termin ważności", "to_invalid": "Pole odbiorca nie może być puste", "app_name_empty": "Nazwa aplikacji nie może być pusta", - "app_passwd_id_invalid": "Identyfikator hasła aplikacji %s jest niepoprawny", + "app_passwd_id_invalid": "Identyfikator hasła aplikacji jest niepoprawny", "authsource_in_use": "Nie można zmienić ani usunąć dostawcy tożsamości, ponieważ jest używany przez co najmniej jednego użytkownika.", "bcc_empty": "Miejsce docelowe BCC nie może być puste", - "bcc_exists": "Mapa BCC %s istnieje dla typu %s", - "bcc_must_be_email": "Miejsce docelowe BCC %s nie jest prawidłowym adresem e-mail", + "bcc_exists": "Mapa BCC istnieje już dla tego typu", + "bcc_must_be_email": "Miejsce docelowe BCC nie jest prawidłowym adresem e-mail", "comment_too_long": "Komentarz zbyt długi, maksymalnie 160 dozwolonych znaków.", "cors_invalid_method": "Podano nieprawidłową metodę Allow-Method", "cors_invalid_origin": "Podano nieprawidłową wartość Allow-Origin", "defquota_empty": "Domyślny limit skrzynki pocztowej nie może wynosić 0", "demo_mode_enabled": "Tryb demo jest włączony", - "dkim_domain_or_sel_exists": "Klucz DKIM dla \"%s\" istnieje i nie zostanie nadpisany", + "dkim_domain_or_sel_exists": "Klucz DKIM już istnieje i nie zostanie nadpisany", "domain_cannot_match_hostname": "Domena nie może być taka sama jak nazwa hosta", "extended_sender_acl_denied": "brak ACL do ustawiania adresów nadawcy zewnętrznego", - "extra_acl_invalid": "Adres nadawcy zewnętrznego \"%s\" jest nieważny", - "extra_acl_invalid_domain": "Nadawca zewnętrzny \"%s\" używa nieprawidłowej domeny", - "fido2_verification_failed": "Weryfikacja FIDO2 nie powiodła się: %s", + "extra_acl_invalid": "Adres nadawcy zewnętrznego jest nieprawidłowy", + "extra_acl_invalid_domain": "Nadawca zewnętrzny używa nieprawidłowej domeny", + "fido2_verification_failed": "Weryfikacja FIDO2 nie powiodła się", "file_open_error": "Nie można otworzyć pliku do zapisu", "filter_type": "Niewłaściwy typ filtra", "from_invalid": "Nadawca nie może być pusty", "generic_server_error": "Wystąpił nieoczekiwany błąd serwera. Skontaktuj się z administratorem.", - "global_filter_write_error": "Nie można zapisać pliku filtra: %s", - "global_map_invalid": "Id mapy globalnej %s nieprawidłowe", - "global_map_write_error": "Nie można napisać globalnej mapy ID %s: %s", - "ham_learn_error": "Błąd uczenia ham: %s", + "global_filter_write_error": "Nie można zapisać pliku filtra", + "global_map_invalid": "Id mapy globalnej nieprawidłowe", + "global_map_write_error": "Nie można zapisać globalnej mapy ID", + "ham_learn_error": "Błąd uczenia ham", "iam_test_connection": "Połączenie nie powiodło się", "imagick_exception": "Błąd: wyjątek Imagick podczas odczytu obrazu", "img_dimensions_exceeded": "Obraz przekracza maksymalny rozmiar obrazu", @@ -491,14 +491,14 @@ "img_size_exceeded": "Obraz przekracza maksymalny rozmiar pliku", "img_tmp_missing": "Nie można zweryfikować pliku obrazu: Nie znaleziono pliku tymczasowego", "invalid_bcc_map_type": "Nieprawidłowy typ mapy BCC", - "invalid_destination": "Format docelowy \"%s\" jest nieprawidłowy", + "invalid_destination": "Format docelowy jest nieprawidłowy", "invalid_filter_type": "Nieprawidłowy typ filtra", - "invalid_host": "Nieprawidłowy określony host: %s", + "invalid_host": "Nieprawidłowy określony host", "invalid_mime_type": "Niepoprawny typ mime", "invalid_nexthop": "Następny format hop jest nieprawidłowy", "invalid_nexthop_authenticated": "Następny hop już istnieje z innymi danymi logowania — zaktualizuj najpierw istniejące dane uwierzytelniające dla tego hopa", - "invalid_recipient_map_new": "Określony nieprawidłowy nowy odbiorca: %s", - "invalid_recipient_map_old": "Określony nieprawidłowy pierwotny odbiorca: %s", + "invalid_recipient_map_new": "Określony nieprawidłowy nowy odbiorca", + "invalid_recipient_map_old": "Określony nieprawidłowy pierwotny odbiorca", "invalid_reset_token": "Nieprawidłowy token resetu", "ip_list_empty": "Lista dozwolonych adresów IP nie może być pusta", "mailbox_defquota_exceeds_mailbox_maxquota": "Domyślny limit skrzynki pocztowej przekracza maksymalny dozwolony limit", @@ -589,7 +589,7 @@ "previous": "Poprzednia strona", "quota_mb": "Limit wielkośći (MiB)", "relay_all": "Przekaż wszystkim odbiorcom", - "relay_all_info": "Jeśli decydujesz się nie przekazywać wszystkim odbiorcom, musisz dodać (\"ślepą\")skrzynkę dla każdego poszczególnego odbiorcy, któremu należy przekazać.", + "relay_all_info": "↪ Jeśli zdecydujesz się nie przekazywać wszystkim odbiorcom, musisz dodać (\"ślepą\")skrzynkę dla każdego poszczególnego odbiorcy, któremu należy przekazać.", "relay_domain": "Domena przekaźnikowa", "remove": "Usuń", "resource": "Zasób", @@ -637,7 +637,7 @@ "extended_sender_acl": "Adresy nadawców zewnętrznych", "extended_sender_acl_info": "Klucz DKIM dla domeny powinien zostać zaimportowany, jeśli jest dostępny.\nPamiętaj, aby dodać ten serwer do odpowiadającego rekordu SPF typu TXT.\nKiedy domena lub domena aliasu zostanie dodana do tego serwera i pokrywa się z zewnętrznym adresem, zewnętrzny adres zostanie usunięty.", "force_pw_update": "Wymuszenie aktualizacji hasła przy następnym logowaniu", - "force_pw_update_info": "Ten użytkownik będzie mógł logować się wyłącznie do %s. Hasła aplikacyjne pozostają aktywne.", + "force_pw_update_info": "Ten użytkownik będzie mógł logować się wyłącznie tutaj %s. Hasła aplikacyjne pozostają aktywne.", "footer_exclude": "Wyklucz ze stopki", "gal": "Globalna lista adresowa", "gal_info": "GAL zawiera wszystkie obiekty domeny i nie może być edytowana przez żadnego użytkownika. Informacje o dostępności (free/busy) w SOGo są niedostępne, jeśli funkcja jest wyłączona!Uruchom ponownie SOGo, aby zastosować zmiany.", @@ -674,7 +674,11 @@ "spam_score": "Ustaw własny poziom punktacji spamu", "timeout1": "Limit czasu połączenia z serwerem zdalnym", "timeout2": "Limit czasu połączenia z serwerem lokalnym", - "validate_save": "Zatwierdź i zapisz" + "validate_save": "Zatwierdź i zapisz", + "pushover_info": "Ustawienia powiadomień push będą stosowane do wszystkich czystych (nie-spamowych) dostarczanych wiadomości w tym aliasów (współdzielonych, niewspółdzielonych, oznaczonych).", + "mailbox_quota_def": "Domyślny limit skrzynki pocztowej", + "mailbox_relayhost_info": "Dotyczy wyłącznie skrzynki pocztowej i bezpośrednich aliasów, nadpisuje ustawienie serwera pośredniczącego (relayhost) dla domeny.", + "maxbytespersecond": "Max. Ilość bajtów na sekundę
(0 = unlimited)" }, "footer": { "cancel": "Anuluj", @@ -847,12 +851,32 @@ "rejected": "Odrzucony", "release": "Zwolnij", "release_body": "Dołączyliśmy Twoją wiadomość jako plik eml do tej wiadomości.", - "release_subject": "Potencjalnie szkodliwa pozycja kwarantanny %s" + "release_subject": "Potencjalnie szkodliwa pozycja kwarantanny %s", + "show_item": "Pokaż element", + "spam": "Spam", + "spam_score": "Wskaźnik", + "subj": "Temat", + "table_size": "Rozmiar tabeli", + "table_size_show_n": "Pokaż %s elementy", + "text_from_html_content": "Zawartość (przekonwertowany HTML)", + "text_plain_content": "Zawartość (tekst zwykły)", + "type": "Typ" }, "queue": { "queue_manager": "Menedżer kolejki", "delete": "Usuń wszystko", - "ays": "Potwierdź, że chcesz usunąć wszystkie elementy z bieżącej kolejki." + "ays": "Potwierdź, że chcesz usunąć wszystkie elementy z bieżącej kolejki.", + "flush": "Opróżnij kolejkę wiadomości", + "info": "Kolejka poczty zawiera wszystkie wiadomości e-mail oczekujące na dostarczenie.\nJeśli wiadomość e-mail pozostaje w kolejce przez dłuższy czas, system automatycznie ją usuwa.
\nKomunikat błędu dla danej wiadomości zawiera informacje o przyczynie, dla której nie mogła zostać dostarczona.", + "legend": "Funkcje zarządzania kolejką poczty", + "deliver_mail": "Dostarcz", + "deliver_mail_legend": "Próby ponownego dostarczenia wybranych wiadomości.", + "hold_mail": "Wstrzymane", + "hold_mail_legend": "Wstrzymuję wybrane maile. (Zapobiega dalszym próbom dostarczenia)", + "show_message": "Pokaż wiadomość", + "unban": "Usuń zablokowanie w kolejce", + "unhold_mail": "Zwolnij wiadomość", + "unhold_mail_legend": "Zwalnia wybrane wiadomości do dostarczenia (wymaga wcześniejszego wstrzymania)." }, "start": { "help": "Pokaż/Ukryj panel pomocy", @@ -878,7 +902,7 @@ "f2b_modified": "Zmiany w Fail2ban zostały zapisane", "forwarding_host_added": "Dodano hosta przekazującego %s", "forwarding_host_removed": "Usunięto hosta przekazującego %s", - "item_deleted": "", + "item_deleted": "Element %s skutecznie usunięte", "items_deleted": "Elementy %s skutecznie usunięte", "mailbox_added": "Dodano skrzynkę %s", "mailbox_modified": "Zapisano zmiany w skrzynce %s", @@ -895,7 +919,59 @@ "verified_fido2_login": "Zweryfikowany login FIDO2", "verified_totp_login": "Zweryfikowany login TOTP", "verified_webauthn_login": "Zweryfikowany login WebAuthn", - "verified_yotp_login": "Zweryfikowany login Yubico OTP" + "verified_yotp_login": "Zweryfikowany login Yubico OTP", + "acl_saved": "ACL dla obiektu %s zapisany", + "admin_added": "Administrator %s został dodany", + "admin_api_modified": "Zmiany w API zostały zapisane", + "admin_removed": "Administrator %s został usunięty", + "app_links": "Zapisane zmiany w linkach aplikacji", + "app_passwd_added": "Dodano nowe hasło aplikacji", + "app_passwd_removed": "Usunięto ID hasła aplikacji %s", + "bcc_deleted": "Wpisy map BCC usunięte: %s", + "bcc_edited": "Wpis mapy BCC %s edytowany", + "bcc_saved": "Wpis mapy BCC zapisany", + "cors_headers_edited": "Ustawienia CORS zostały zapisane", + "custom_login_modified": "Dostosowanie logowania zostało pomyślnie zapisane", + "db_init_complete": "Inicjalizacja bazy danych zakończona", + "delete_filter": "Filtry %s ID usunięte", + "delete_filters": "Usunięte filtry: %s", + "deleted_syncjob": "Usunięte syncjob ID %s", + "deleted_syncjobs": "Usunięte syncjobs: %s”.", + "domain_add_dkim_available": "Klucz DKIM już istniał", + "dkim_duplicated": "Klucz DKIM dla domeny %s został skopiowany do %s", + "domain_footer_modified": "Zmiany w stopce domeny %s zostały zapisane", + "dovecot_restart_success": "Dovecot został pomyślnie zrestartowany", + "f2b_banlist_refreshed": "ID listy banów został pomyślnie odświeżony.", + "global_filter_written": "Filtr został pomyślnie zapisany do pliku", + "hash_deleted": "Hash usunięty", + "iam_test_connection": "Połączenie powiodło się", + "ip_check_opt_in_modified": "Sprawdzenie adresu IP zostało pomyślnie zapisane", + "item_released": "Pozycja %s zwolniona", + "items_released": "Wybrane elementy zostały zwolnione", + "learned_ham": "Pomyślnie nauczono ID %s jako ham", + "license_modified": "Zmiany w licencji zostały zapisane", + "logged_in_as": "Zalogowany jako %s", + "mailbox_renamed": "Nazwa skrzynki pocztowej została zmieniona z %s na %s", + "nginx_reloaded": "Nginx został przeładowany", + "password_policy_saved": "Polityka haseł została pomyślnie zapisana", + "password_changed_success": "Hasło zostało pomyślnie zmienione", + "pushover_settings_edited": "Ustawienia Pushover pomyślnie ustawione, proszę zweryfikować dane uwierzytelniające.", + "qlearn_spam": "Identyfikator wiadomości %s został nauczony jako spam i usunięty", + "queue_command_success": "Polecenie kolejki zostało pomyślnie wykonane", + "recipient_map_entry_deleted": "Id mapy odbiorcy %s został usunięty", + "recipient_map_entry_saved": "Wpis mapy odbiorcy \"%s\" został zapisany", + "recovery_email_sent": "E-mail do odzyskiwania wysłany do %s", + "relayhost_added": "Wpis mapy %s został dodany", + "relayhost_removed": "Wpis mapy %s został usunięty", + "reset_main_logo": "Reset do domyślnego logo", + "rl_saved": "Limit szybkości dla obiektu %s został zapisany", + "rspamd_ui_pw_set": "Hasło do Rspamd UI pomyślnie ustawione", + "saved_settings": "Zapisane ustawienia", + "settings_map_added": "Dodano ustawienia (wpis mapy)", + "settings_map_removed": "Usunięte ustawienia mapy ID %s", + "sogo_profile_reset": "Profil SOGo dla użytkownika/ów został zresetowany", + "template_added": "Dodano szablon", + "template_modified": "Zmiany w szablonie/ach zostały zapisane" }, "tfa": { "api_register": "%s używa Yubico Cloud API. Proszę pobrać klucz API dla Twojego klucza tutaj", @@ -1197,5 +1273,12 @@ "set_fido2_touchid": "Zarejestruj Touch ID w Apple M1", "set_fn": "Ustaw przyjazną nazwę w FIDO", "start_fido2_validation": "Rozpocznij walidację FIDO2" + }, + "ratelimit": { + "disabled": "Wyłączone", + "second": "wiadomości / sekundę", + "minute": "wiadomości / minutę", + "hour": "wiadomości / godzinę", + "day": "wiadomości/ dzień" } } diff --git a/data/web/lang/lang.ru-ru.json b/data/web/lang/lang.ru-ru.json index b0180256d..e7d825639 100644 --- a/data/web/lang/lang.ru-ru.json +++ b/data/web/lang/lang.ru-ru.json @@ -109,7 +109,9 @@ "timeout2": "Тайм-аут для подключения к локальному хосту", "username": "Имя пользователя", "validate": "Проверить", - "validation_success": "Проверка прошла успешно" + "validation_success": "Проверка прошла успешно", + "internal": "Внутренний", + "internal_info": "Внутренние псевдонимы доступны только из самого домена или доменов-псевдонимов." }, "admin": { "access": "Настройки доступа", @@ -550,7 +552,11 @@ "generic_server_error": "На сервере произошла непредвиденная ошибка. Пожалуйста, свяжитесь с вашим администратором.", "authsource_in_use": "Поставщик идентификационных данных не может быть изменен или удален, так как в данный момент он используется одним или несколькими пользователями.", "iam_test_connection": "Ошибка соединения", - "required_data_missing": "Отсутствуют необходимые данные %s" + "required_data_missing": "Отсутствуют необходимые данные %s", + "max_age_invalid": "Максимальный возраст %s недействителен", + "mode_invalid": "Режим %s недействителен", + "mx_invalid": "Запись MX %s недействительна", + "version_invalid": "Версия %s недействительна" }, "datatables": { "collapse_all": "Свернуть все", @@ -762,7 +768,20 @@ "title": "Изменение объекта", "unchanged_if_empty": "Если без изменений - оставьте пустым", "username": "Имя пользователя", - "validate_save": "Подтвердить и сохранить" + "validate_save": "Подтвердить и сохранить", + "internal": "Внутренний", + "internal_info": "Внутренние псевдонимы доступны только из самого домена или доменов-псевдонимов.", + "mta_sts": "MTA-STS", + "mta_sts_info": "MTA-STS — это стандарт, который обязывает почтовые серверы использовать TLS с подлинными сертификатами для доставки электронной почты.
Он используется, когда DANE невозможен из-за неиспользуемого или неподдерживаемого DNSSEC.
Примечание: если принимающий домен поддерживает DANE с DNSSEC, всегда предпочитается DANE — MTA-STS действует только как резервный вариант.", + "mta_sts_version": "Версия", + "mta_sts_version_info": "Определяет версию стандарта MTA-STS – на данный момент существует только STSv1.", + "mta_sts_mode": "Режим", + "mta_sts_mode_info": "Есть три режима на выбор:
  • testing – политика только наблюдается, нарушения не имеют последствий.
  • enforce – политика соблюдается строго, соединения без подлинного TLS отклоняются.
  • none – политика опубликована, но не применяется.
", + "mta_sts_max_age": "Максимальный возраст", + "mta_sts_max_age_info": "Время в секундах, в течение которого принимающие почтовые серверы могут кэшировать эту политику перед повторной загрузкой.", + "mta_sts_mx": "Сервер MX", + "mta_sts_mx_info": "Разрешает отправку только на явно указанные имена хостов почтовых серверов; отправляющий MTA проверяет, соответствует ли DNS-имя MX-хоста списку политик, и разрешает доставку только с подлинным TLS-сертификатом (защита от MITM).", + "mta_sts_mx_notice": "Можно указать несколько MX-серверов (через запятую)." }, "fido2": { "confirm": "Подтвердить", @@ -832,7 +851,8 @@ "login_admintext": "Войти как администратор", "login_user": "Вход для пользователей", "login_dadmin": "Вход для администраторов домена", - "login_admin": "Вход для администраторов" + "login_admin": "Вход для администраторов", + "email": "Email-адрес" }, "mailbox": { "action": "Действия", @@ -1008,7 +1028,8 @@ "waiting": "В ожидании", "weekly": "Раз в неделю", "yes": "✓", - "iam": "Поставщик идентификационных данных" + "iam": "Поставщик идентификационных данных", + "internal": "Внутренний" }, "oauth2": { "access_denied": "Пожалуйста, войдите в систему как владелец почтового аккаунта, чтобы получить доступ через OAuth2.", @@ -1331,7 +1352,7 @@ "sogo_profile_reset": "Сбросить профиль SOGo", "sogo_profile_reset_help": "Внимание: это удалит настройки профиля SOGo вместе с всеми контактами, календарями и фильтрами безвозвратно.", "sogo_profile_reset_now": "Сбросить профиль сейчас", - "spam_aliases": "Временные псевдонимы электронной почты", + "spam_aliases": "Псевдонимы для спама", "spam_score_reset": "Сброс на настройки по умолчанию", "spamfilter": "Спам фильтр", "spamfilter_behavior": "Фильтрация спама", @@ -1387,7 +1408,10 @@ "authentication": "Аутентификация", "tfa_info": "Двухфакторная аутентификация помогает защитить вашу учетную запись. Если вы включите эту функцию, вам понадобятся пароли приложений для входа в приложения или службы, которые не поддерживают двухфакторную аутентификацию (например, почтовые клиенты).", "protocols": "Протоколы", - "overview": "Обзор" + "overview": "Обзор", + "expire_never": "Никогда не истекает", + "forever": "Навсегда", + "spam_aliases_info": "Псевдоним для спама — это временный адрес электронной почты, который можно использовать для защиты реальных адресов.
При желании можно установить срок действия, по истечении которого псевдоним будет автоматически деактивирован, что позволяет эффективно избавляться от адресов, которые были использованы не по назначению или стали доступны посторонним лицам." }, "warning": { "cannot_delete_self": "Вы не можете удалить сами себя", diff --git a/data/web/lang/lang.si-si.json b/data/web/lang/lang.si-si.json index 4b1c78fae..918fb8b1a 100644 --- a/data/web/lang/lang.si-si.json +++ b/data/web/lang/lang.si-si.json @@ -297,7 +297,7 @@ "forwarding_hosts_add_hint": "Lahko vpišete IPv4/IPv6 naslove, mreže v CIDR obliki, imena gostiteljev (kateri se prevedejo v IP naslove) ali imena domen (katera se prevedejo v IP naslove glede na poizvedbo po SPF zapisih, v primeru manjkajočih zapisov pa MX zapisih).", "forwarding_hosts_hint": "Dohodna sporočila so brezpogojno sprejeta od katerih koli gostiteljev v tem seznamu. Ti gostitelji se ne bodo preverjali po DNSBL seznamih in ne bodo dodani v listo sivih. Prejeta neželena pošta s teh gostiteljev ni nikoli zavrnjena, opcijsko pa se lahko premakne v mapo neželene pošte. Najpogostejša uporaba za to je navedba poštnih strežnikov, iz katerih ste nastavili pravilo za posredovanje pošte na vaš mailcow strežnik.", "license_info": "Licenca ni zahtevana, a pomaga pri nadaljnjem razvoju.
Registrirajte svoj GUID tukaj ali Kupite podporo za svojo namestitev Mailcow.", - "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (.*\\.google\\.com za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka).", + "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (.*\\.google\\.com za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka)", "main_name": "Naziv \"mailcow UI\"", "merged_vars_hint": "Sive vrstice so združene iz vars.(local.)inc.php in jih ni mogoče spremeniti.", "oauth2_info": "Implementacija OAuth2 podpira vrsto odobritve »Avtorizacijska koda« in izda osvežilne žetone.
\nStrežnik samodejno izda tudi nove osvežilne žetone, ko je žeton za osvežitev uporabljen.

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

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

\nPreklic žetonov odjemalca bo povzročil takojšnjo prekinitev vseh aktivnih sej. Vse stranke se morajo ponovno overiti.", @@ -414,7 +414,7 @@ "needs_restart": "potreben je ponovni zagon" }, "danger": { - "alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati.", + "alias_goto_identical": "Vzdevek in ciljni naslov se ne smeta ujemati", "aliasd_targetd_identical": "Vzdevek domene ne sme biti enak ciljni domeni: %s", "bcc_exists": "Za tip %s obstaja BCC preslikava %s", "dkim_domain_or_sel_exists": "DKIM ključ za \"%s\" obstaja in ne bo prepisan", @@ -651,7 +651,7 @@ "pushover_title": "Naslov obvestila", "domains": "Domene", "extended_sender_acl_info": "Uvoziti je treba ključ domene DKIM, če je na voljo.
\n Ne pozabite dodati tega strežnika v ustrezni zapis SPF TXT.
\n Kadar koli je temu strežniku dodana domena ali vzdevek domene, ki se prekriva z zunanjim naslovom, se zunanji naslov odstrani.
\n Uporabite @domain.tld, da omogočite pošiljanje kot *@domain.tld.", - "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (.*\\.google\\.com za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka).", + "lookup_mx": "Cilj je regularni izraz, ki se ujema z imenom MX (.*\\.google\\.com za usmerjanje vse pošte, usmerjene na MX, ki se konča na google.com, prek tega skoka)", "maxbytespersecond": "Največ bajtov na sekundo
(0 = neomejeno)", "pushover_sender_array": "Upoštevaj samo sledeče e-poštne naslove pošiljateljev (ločeni z vejico)", "mbox_rl_info": "Ta omejitev se uporabi za prijavno ime SASL in se ujema z naslovom \"od\", ki ga uporablja prijavljeni uporabnik. Omejitev poštnega nabiralnika preglasi omejitev za celotno domeno.", @@ -1359,7 +1359,7 @@ "sogo_profile_reset": "Ponastavi profil SOGo", "sogo_profile_reset_help": "S tem boste uničili uporabnikov profil SOGo in nepovratno izbrisali vse stike in podatke koledarja.", "sogo_profile_reset_now": "Ponastavi profil zdaj", - "spam_aliases": "Začasni vzdevki e-pošte", + "spam_aliases": "Vzdevki neželene e-pošte", "spam_score_reset": "Ponastavi na privzete nastavitve strežnika", "spamfilter": "Filter neželene pošte", "spamfilter_behavior": "Ocena", @@ -1407,7 +1407,10 @@ "years": "leta", "waiting": "Čakanje", "q_all": "Vse kategorije", - "syncjob_EX_OK": "Uspeh" + "syncjob_EX_OK": "Uspeh", + "expire_never": "Nikoli ne poteče", + "forever": "Za vedno", + "spam_aliases_info": "Vzdevek za neželeno pošto je začasni e-poštni naslov, ki ga je mogoče uporabiti za zaščito pravih e-poštnih naslovov.
Po želji je mogoče nastaviti čas poteka veljavnosti, tako da se vzdevek po določenem obdobju samodejno deaktivira, s čimer se učinkovito znebite zlorabljenih ali razkritih naslovov." }, "warning": { "cannot_delete_self": "Prijavljenega uporabnika ni mogoče izbrisati", From 6f9ee2d15135e910672fa6d98a4095195d357f97 Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Fri, 21 Nov 2025 10:55:12 +0100 Subject: [PATCH 091/109] chore(deps): update actions/checkout action to v6 (#6920) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/image_builds.yml | 2 +- .github/workflows/pr_to_nightly.yml | 2 +- .github/workflows/rebuild_backup_image.yml | 2 +- .github/workflows/update_postscreen_access_list.yml | 2 +- 4 files changed, 4 insertions(+), 4 deletions(-) diff --git a/.github/workflows/image_builds.yml b/.github/workflows/image_builds.yml index a5ebb902f..c8ec7ccae 100644 --- a/.github/workflows/image_builds.yml +++ b/.github/workflows/image_builds.yml @@ -27,7 +27,7 @@ jobs: - "watchdog-mailcow" runs-on: ubuntu-latest steps: - - uses: actions/checkout@v5 + - uses: actions/checkout@v6 - name: Setup Docker run: | curl -sSL https://get.docker.com/ | CHANNEL=stable sudo sh diff --git a/.github/workflows/pr_to_nightly.yml b/.github/workflows/pr_to_nightly.yml index d234be3fe..548fabde6 100644 --- a/.github/workflows/pr_to_nightly.yml +++ b/.github/workflows/pr_to_nightly.yml @@ -8,7 +8,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout repository - uses: actions/checkout@v5 + uses: actions/checkout@v6 with: fetch-depth: 0 - name: Run the Action diff --git a/.github/workflows/rebuild_backup_image.yml b/.github/workflows/rebuild_backup_image.yml index a8679d980..10edd5cd0 100644 --- a/.github/workflows/rebuild_backup_image.yml +++ b/.github/workflows/rebuild_backup_image.yml @@ -13,7 +13,7 @@ jobs: packages: write steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Set up QEMU uses: docker/setup-qemu-action@v3 diff --git a/.github/workflows/update_postscreen_access_list.yml b/.github/workflows/update_postscreen_access_list.yml index eed07876e..80b218c1b 100644 --- a/.github/workflows/update_postscreen_access_list.yml +++ b/.github/workflows/update_postscreen_access_list.yml @@ -15,7 +15,7 @@ jobs: runs-on: ubuntu-latest steps: - name: Checkout - uses: actions/checkout@v5 + uses: actions/checkout@v6 - name: Generate postscreen_access.cidr run: | From 514fefd2edcf97c083820afe44901109ab8b8533 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 24 Nov 2025 16:50:03 +0100 Subject: [PATCH 092/109] Translations update from Weblate (#6924) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [Web] Updated lang.ca-es.json Co-authored-by: Pere Montpeó Co-authored-by: milkmaker * [Web] Updated lang.gr-gr.json Co-authored-by: Chris Co-authored-by: milkmaker * [Web] Updated lang.cs-cz.json Co-authored-by: Filip Hajny * [Web] Updated lang.pl-pl.json [Web] Updated lang.pl-pl.json Co-authored-by: Monika Bark Co-authored-by: milkmaker --------- Co-authored-by: Pere Montpeó Co-authored-by: Chris Co-authored-by: Filip Hajny Co-authored-by: Monika Bark --- data/web/lang/lang.ca-es.json | 31 +++++++++++++++-- data/web/lang/lang.cs-cz.json | 29 +++++++++------- data/web/lang/lang.gr-gr.json | 3 +- data/web/lang/lang.pl-pl.json | 65 +++++++++++++++++++---------------- 4 files changed, 82 insertions(+), 46 deletions(-) diff --git a/data/web/lang/lang.ca-es.json b/data/web/lang/lang.ca-es.json index ba84543a2..5b8e9b64d 100644 --- a/data/web/lang/lang.ca-es.json +++ b/data/web/lang/lang.ca-es.json @@ -19,7 +19,16 @@ "spam_alias": "Àlies temporals", "spam_score": "Puntuació de correu brossa", "tls_policy": "Política TLS", - "unlimited_quota": "Quota ilimitada per bústies de correo" + "unlimited_quota": "Quota ilimitada per bústies de correo", + "delimiter_action": "Acció delimitadora", + "domain_relayhost": "Canviar relayhost per un domini", + "extend_sender_acl": "Permetre extendre l'ACL del remitent per adreces externes", + "mailbox_relayhost": "Canvia el host de reenviament per una bústia", + "pushover": "Pushover", + "pw_reset": "Permetre el restabliment de la contrasenya de l'usuari mailcow", + "ratelimit": "Límit de peticions", + "smtp_ip_access": "Canvia hosts permesos per SMTP", + "sogo_access": "Permetre la gestió d'accés a SOGo" }, "add": { "activate_filter_warn": "All other filters will be deactivated, when active is checked.", @@ -73,7 +82,25 @@ "validate": "Validar", "validation_success": "Validated successfully", "app_name": "Nom de l'aplicació", - "app_password": "Afegir contrasenya a l'aplicació" + "app_password": "Afegir contrasenya a l'aplicació", + "app_passwd_protocols": "Protocols autoritzats per la contrasenya de l'aplicació", + "bcc_dest_format": "La destinació c/o ha de ser una única adreça de correu vàlida.
Si necessiteu enviar una còpia a diverses adreces, creeu un àlies i utilitzeu-lo aquí.", + "comment_info": "Els comentaris privats no són visibles per l'usuari, mentre que els comentaris públics apareixen com una descripció emergent a la informació de l'usuari", + "custom_params": "Paràmetres personalitzats", + "custom_params_hint": "Correcte: --param=xy, incorrecte: --param xy", + "destination": "Destí", + "disable_login": "No permetre l'inici de sessió (els missatges entrants continuen sent acceptats)", + "domain_matches_hostname": "El domini %s coincideix amb el nom del servidor", + "dry": "Simular la sincronització", + "gal": "Llista d'adreces global", + "generate": "genereu", + "inactive": "Inactiu", + "internal": "Intern", + "internal_info": "Els àlies interns són només accessibles des del mateix domini o els àlies de dominis.", + "mailbox_quota_def": "Quota per defecte de la bústia", + "nexthop": "Següent salt", + "private_comment": "Comentari privat", + "public_comment": "Comentari púlbic" }, "admin": { "access": "Accés", diff --git a/data/web/lang/lang.cs-cz.json b/data/web/lang/lang.cs-cz.json index b3068ab0f..b178720a9 100644 --- a/data/web/lang/lang.cs-cz.json +++ b/data/web/lang/lang.cs-cz.json @@ -149,7 +149,7 @@ "arrival_time": "Čas zařazení do fronty (čas na serveru)", "authed_user": "Přihlášený uživatel", "ays": "Opravdu chcete pokračovat?", - "ban_list_info": "Seznam blokovaných IP adres je zobrazen níže: síť (zbývající čas blokování) - [akce].
IP adresy zařazené pro odblokování budou z aktivního seznamu odebrány během několika sekund.
Červeně označené položky jsou pernamentní bloky z blacklistu.", + "ban_list_info": "Viz seznam zablokovaných IP níže: síť (zbývající doba zablokování) - [akce].
IP adresy zařazené pro odblokování budou z aktivního seznamu odebrány během pár sekund.
Červeně označeny jsou položky z trvalých seznamů.", "change_logo": "Změnit logo", "logo_normal_label": "Normální", "logo_dark_label": "Inverzní pro tmavý režim", @@ -183,16 +183,16 @@ "empty": "Žádné výsledky", "excludes": "Vyloučit tyto příjemce", "f2b_ban_time": "Doba blokování (s)", - "f2b_blacklist": "Sítě/hostitelé na blacklistu", + "f2b_blacklist": "Sítě či hostitelé na seznamu zákazů", "f2b_filter": "Regex filtre", - "f2b_list_info": "Síť nebo hostitelé na blacklistu mají vždy větší váhu než položky na whitelistu. Každá úprava seznamů trvá pár sekund.", + "f2b_list_info": "Sítě či hostitelé na seznamu zákazů mají vždy větší váhu než položky na seznamu povolení. Každá úprava seznamu trvá pár sekund.", "f2b_max_attempts": "Max. pokusů", "f2b_netban_ipv4": "Rozsah IPv4 podsítě k zablokování (8-32)", "f2b_netban_ipv6": "Rozsah IPv6 podsítě k zablokování (8-128)", "f2b_parameters": "Parametry automatického firewallu", "f2b_regex_info": "Záznamy které se berou v úvahu: SOGo, Postfix, Dovecot, PHP-FPM.", "f2b_retry_window": "Časový horizont pro maximum pokusů (s)", - "f2b_whitelist": "Sítě/hostitelé na whitelistu", + "f2b_whitelist": "Sítě či hostitelé na seznamu povolení", "filter_table": "Tabulka filtrů", "forwarding_hosts": "Předávající servery", "forwarding_hosts_add_hint": "Lze zadat IPv4/IPv6 adresy, sítě ve formátu CIDR, názvy serverů (budou převedeny na IP adresy) nebo názvy domén (budou převedeny na IP pomocí SPF záznamů, příp. MX záznamů).", @@ -304,7 +304,7 @@ "rspamd_com_settings": "Název nastavení se vygeneruje automaticky, viz ukázky nastavení níže. Více informací viz Rspamd dokumentace", "rspamd_global_filters": "Mapa globálních filtrů", "rspamd_global_filters_agree": "Budu opatrný!", - "rspamd_global_filters_info": "Mapa globálních filtrů obsahuje jiné globální black- a whitelisty.", + "rspamd_global_filters_info": "Mapa globálních filtrů obsahuje různé seznamy povolených a zakázaných serverů", "rspamd_global_filters_regex": "Názvy stačí k vysvětlení. Položky musejí obsahovat jen platné regulární výrazy ve tvaru \"/vyraz/parametry\" (e.g. /.+@domena\\.tld/i).
\n Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.
\n Rspamd se pokusí po každé změně načíst mapu znovu. V případě potíží restartujte Rspamd, aby se konfigurace načetla explicitně.", "rspamd_settings_map": "Nastavení Rspamd", "sal_level": "Úroveň 'Moo'", @@ -733,7 +733,7 @@ "sogo_visible_info": "Tato volba určuje objekty, jež lze zobrazit v SOGo (sdílené nebo nesdílené aliasy, jež ukazuje alespoň na jednu schránku).", "spam_alias": "Vytvořit nebo změnit dočasné aliasy", "spam_filter": "Spam filtr", - "spam_policy": "Přidat nebo odebrat položky whitelistu/blacklistu", + "spam_policy": "Přidat nebo odebrat položky seznamu", "spam_score": "Nastavte vlastní skóre spamu", "subfolder2": "Synchronizace do podsložky v cílovém umístění
(prázdné = nepoužívat podsložku)", "syncjob": "Upravit synchronizační úlohu", @@ -883,7 +883,7 @@ "bcc": "BCC", "bcc_destination": "Cíl kopie", "bcc_destinations": "Cíl kopií", - "bcc_info": "
Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.
\n Místní cíl se nedozví, selže-li doručení na cíl BCC.", + "bcc_info": "Skrytá kopie (mapa BCC) se používá pro tiché předávání kopií všech zpráv na jinou adresu. Mapa příjemců se použije, funguje-li je místní cíl jako adresát zprávy. Totéž platí pro mapy odesílatelů.
\n Místní cíl se nedozví, selže-li doručení na cíl BCC.", "bcc_local_dest": "Týká se", "bcc_map": "Skrytá kopie", "bcc_map_type": "Typ skryté kopie", @@ -1060,7 +1060,7 @@ "notified": "Oznámeno", "qhandler_success": "Požadavek úspěšně přijat. Můžete nyní zavřít okno.", "qid": "Rspamd QID", - "qinfo": "Karanténní systém uloží odmítnutou poštu do databáze (odesílatel se nedozví, že pošta byla doručena) jakož i pošta, která bude jako kopie doručena do složky Nevyžádaná pošta. \r\n
\"Naučit jako spam a smazat\" naučí zprávu jako spam přes Bayesian theorem a současně vypočítá fuzzy hashes pro odmítnutí podobných zpráv v budoucnosti. \r\n
Prosím, berte na vědomí, že naučení více zpráv může být - záleží na vašem systému - časově náročné .
Položky na černé listině jsou z karantény vyloučeny.", + "qinfo": "Karanténa uloží do databáze odmítnutou poštu (odesílatel se nedozví, že pošta byla doručena) jakož i poštu, jež se jako kopie doručuje do složky Nevyžádaná pošta.\n
\"Naučit jako spam a smazat\" předá zprávu systému k naučení bayesiánskou analýzou jako spam a současně stanoví fuzzy hashe pro odmítání podobných zpráv v budoucnosti.\n
Vezměte na vědomí, že učení více zpráv může být podle výkonnosti systému zabrat více času.
Položky na seznamu zákazů jsou z karantény vyloučeny.", "qitem": "Položka v karanténě", "quarantine": "Karanténa", "quick_actions": "Akce", @@ -1347,12 +1347,12 @@ "sogo_profile_reset": "Resetovat profil SOGo", "sogo_profile_reset_help": "Tato volba odstraní uživatelský profil SOGo a nenávratně vymaže všechna data.", "sogo_profile_reset_now": "Resetovat profil", - "spam_aliases": "Dočasné e-mailové aliasy", + "spam_aliases": "Spam aliasy", "spam_score_reset": "Obnovit výchozí nastavení serveru", "spamfilter": "Filtr spamu", "spamfilter_behavior": "Hodnocení", - "spamfilter_bl": "Seznam zakázaných adres (blacklist)", - "spamfilter_bl_desc": "Zakázané emailové adresy budou vždy klasifikovány jako spam a odmítnuty. Odmítnutá pošta nebude uložena do karantény. Lze použít zástupné znaky (*). Filtr se použije pouze na přímé aliasy (s jednou cílovou poštovní schránkou), s výjimkou doménových košů a samotné poštovní schránky.", + "spamfilter_bl": "Seznam zákazů", + "spamfilter_bl_desc": "Zakázané emailové adresy budou vždy klasifikovány jako spam a odmítnuty. Odmítnutá pošta se neukládá do karantény. Lze použít zástupné znaky (*). Filtr se použije pouze na přímé aliasy (s jednou cílovou poštovní schránkou), s výjimkou doménových košů a samotné poštovní schránky.", "spamfilter_default_score": "Výchozí hodnoty", "spamfilter_green": "Zelená: tato zpráva není spam", "spamfilter_hint": "První hodnota představuje \"nízké spam skóre\" a druhá \"vysoké spam skóre\".", @@ -1363,7 +1363,7 @@ "spamfilter_table_empty": "Žádná data k zobrazení", "spamfilter_table_remove": "smazat", "spamfilter_table_rule": "Pravidlo", - "spamfilter_wl": "Seznam povolených adres (whitelist)", + "spamfilter_wl": "Seznam povolení", "spamfilter_wl_desc": "Povolené emailové adresy nebudou nikdy klasifikovány jako spam. Lze použít zástupné znaky (*). Filtr se použije pouze na přímé aliasy (s jednou cílovou mailovou schránkou), s výjimkou doménových košů a samotné mailové schránky.", "spamfilter_yellow": "Žlutá: tato zpráva může být spam, bude označena jako spam a přesunuta do složky nevyžádané pošty", "status": "Stav", @@ -1407,7 +1407,10 @@ "authentication": "Autentifikace", "overview": "Přehled", "protocols": "Protokoly", - "value": "Hodnota" + "value": "Hodnota", + "expire_never": "Nikdy nevyprší", + "forever": "Navždy", + "spam_aliases_info": "Spam alias je dočasná adresa, již lze použít k ochraně skutečných adres.
Případně lze nastavit také dobu platnosti, po níž je alias automaticky deaktivován, čímž se řeší případy zneužitých či odcizených adres." }, "warning": { "cannot_delete_self": "Nelze smazat právě přihlášeného uživatele", diff --git a/data/web/lang/lang.gr-gr.json b/data/web/lang/lang.gr-gr.json index df9127aec..83008e63d 100644 --- a/data/web/lang/lang.gr-gr.json +++ b/data/web/lang/lang.gr-gr.json @@ -6,7 +6,8 @@ "weeks": "Εβδομάδες", "with_app_password": "με κωδικό εφαρμογής", "year": "χρόνος", - "years": "χρόνια" + "years": "χρόνια", + "value": "Τιμή" }, "warning": { "cannot_delete_self": "Αδυναμία διαγραφής συνδεδεμένου χρήστη", diff --git a/data/web/lang/lang.pl-pl.json b/data/web/lang/lang.pl-pl.json index 61a17a749..41cf10283 100644 --- a/data/web/lang/lang.pl-pl.json +++ b/data/web/lang/lang.pl-pl.json @@ -173,7 +173,7 @@ "active_rspamd_settings_map": "Aktywne ustawienia mapy", "add_admin": "Dodaj administratora", "add_relayhost": "Dodaj transport zależny od nadawcy", - "add_relayhost_hint": "Miej na uwadze, że dane uwierzytelniające, jeśli takie istnieją, będą przechowywane w postaci zwykłego tekstu", + "add_relayhost_hint": "Miej na uwadze, że dane uwierzytelniające, jeśli takie istnieją, będą przechowywane w postaci zwykłego tekstu.", "add_row": "Dodaj wiersz", "add_settings_rule": "Dodaj regułę ustawień", "add_transport": "Dodaj transport", @@ -240,7 +240,7 @@ "generate": "Generuj", "guid": "GUID - unikalny identyfikator instancji", "guid_and_license": "GUID & licencja", - "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.
\n\n Każdy hash jest oznaczony indywidualnym kolorem.", + "hash_remove_info": "Usunięcie hasha z limitem współczynnika (jeśli nadal istnieje) spowoduje całkowite zresetowanie jego licznika.
\n\n\n\n Każdy hash jest oznaczony indywidualnym kolorem.", "help_text": "Zastąp tekst pomocy poniżej maski logowania (dozwolone HTML)", "html": "HTML", "iam": "Dostawca tożsamości", @@ -266,7 +266,7 @@ "iam_port": "Port", "iam_realm": "Realm", "iam_redirect_url": "Przekierowanie Url", - "iam_rest_flow": "Mailpassword Flow", + "iam_rest_flow": "Procedura uwierzytelniania hasła pocztowego", "iam_server_url": "Adres URL serwera", "iam_sso": "Pojedyncze logowanie", "iam_sync_interval": "Interwał synchronizacji / importu (min)", @@ -362,7 +362,7 @@ "reset_limit": "Usuń hash", "reset_password_vars": "{{link}} Wygenerowany link do resetu hasła
{{username}} Nazwa skrzynki pocztowej użytkownika, który poprosił o zresetowanie hasła
{{username2}} Nazwa skrzynki pocztowej do odzyskiwania
{{date}} Data złożenia żądania resetowania hasła
{{token_lifetime}}Żywotność tokena w minutach
{{hostname}} Nazwa hosta mailcow", "restore_template": "Pozostaw puste, aby przywrócić szablon domyślny.", - "routing": "Routing", + "routing": "Routowanie", "rsetting_add_rule": "Dodaj regułę", "rsetting_content": "Zawartość reguły", "rsetting_desc": "Krótki opis", @@ -390,7 +390,7 @@ "title": "Tytuł", "title_name": "Tytuł strony internetowej \"mailcow UI\"", "to_top": "Powrót na górę", - "transport_dest_format": "Regex lub syntax: example.org, .example.org, *, box@example.org\n(wiele wartości można rozdzielić przecinkami)", + "transport_dest_format": "Regex lub syntax: example.org, .example.org, *, box@example.org(wiele wartości można rozdzielić przecinkami)", "transport_maps": "Mapy transportu", "transport_test_rcpt_info": "• Użyj null@hosted.mailcow.de aby przetestować przekazywanie do nieznanego miejsca docelowego.", "transports_hint": "• Wpis mapy transportowej overrules mapa transportowa zależna od nadawcy
.
\nNajlepiej stosować transporty oparte na MX •.
\nUstawienia zasad Outbound TLS dotyczące użytkownika są ignorowane i mogą być egzekwowane tylko przez wpisy mapy zasad TLS\n• Usługa transportu dla zdefiniowanych transportów jest zawsze \"smtp:\" i dlatego uruchomi TLS, gdy będzie oferowana. Wrapped TLS (SMTPS) nie jest obsługiwany.
\nAdresy pasujące do \"/localhost$/\" będą zawsze transportowane przez \"lokalne:\", dlatego miejsce docelowe \"*\" nie będzie miało zastosowania do tych adresów.
\n• Aby określić poświadczenia dla przykładowego następnego hopa \"[host]:25\", Postfix zawsze kolejkuje zapytania o \"host\" przed wyszukaniem \"[host]:25\". Takie zachowanie uniemożliwia jednoczesne użycie \"host\" i \"[host]:25.", @@ -432,7 +432,7 @@ "goto_invalid": "Adres Idź do jest nieprawidłowy", "is_alias": "został już podany jako alias", "is_alias_or_mailbox": "jest już znany jako alias, skrzynka pocztowa lub adres aliasu rozwinięty z domeny aliasu.", - "is_spam_alias": "jest już znany jako tymczasowy adres aliasu (adres aliasu antyspamowego).", + "is_spam_alias": "jest już znany jako tymczasowy adres aliasu (adres aliasu antyspamowego)", "last_key": "Nie można usunąć ostatniego klucza, zamiast tego należy wyłączyć TFA.", "login_failed": "Logowanie nie powiodło się", "mailbox_invalid": "Nieprawidłowa nazwa skrzynki", @@ -465,10 +465,10 @@ "bcc_empty": "Miejsce docelowe BCC nie może być puste", "bcc_exists": "Mapa BCC istnieje już dla tego typu", "bcc_must_be_email": "Miejsce docelowe BCC nie jest prawidłowym adresem e-mail", - "comment_too_long": "Komentarz zbyt długi, maksymalnie 160 dozwolonych znaków.", + "comment_too_long": "Komentarz zbyt długi, maksymalnie 160 dozwolonych znaków", "cors_invalid_method": "Podano nieprawidłową metodę Allow-Method", "cors_invalid_origin": "Podano nieprawidłową wartość Allow-Origin", - "defquota_empty": "Domyślny limit skrzynki pocztowej nie może wynosić 0", + "defquota_empty": "Domyślny limit skrzynki pocztowej nie może wynosić 0.", "demo_mode_enabled": "Tryb demo jest włączony", "dkim_domain_or_sel_exists": "Klucz DKIM już istnieje i nie zostanie nadpisany", "domain_cannot_match_hostname": "Domena nie może być taka sama jak nazwa hosta", @@ -496,20 +496,20 @@ "invalid_host": "Nieprawidłowy określony host", "invalid_mime_type": "Niepoprawny typ mime", "invalid_nexthop": "Następny format hop jest nieprawidłowy", - "invalid_nexthop_authenticated": "Następny hop już istnieje z innymi danymi logowania — zaktualizuj najpierw istniejące dane uwierzytelniające dla tego hopa", + "invalid_nexthop_authenticated": "Następny hop już istnieje z innymi danymi logowania, zaktualizuj najpierw istniejące dane uwierzytelniające dla tego hopa.", "invalid_recipient_map_new": "Określony nieprawidłowy nowy odbiorca", "invalid_recipient_map_old": "Określony nieprawidłowy pierwotny odbiorca", "invalid_reset_token": "Nieprawidłowy token resetu", "ip_list_empty": "Lista dozwolonych adresów IP nie może być pusta", "mailbox_defquota_exceeds_mailbox_maxquota": "Domyślny limit skrzynki pocztowej przekracza maksymalny dozwolony limit", - "malformed_username": "Nieprawidłowy format nazwy użytkownika.", + "malformed_username": "Nieprawidłowy format nazwy użytkownika", "map_content_empty": "Zawartość mapy nie może być pusta", "max_age_invalid": "Nieprawidłowa wartość maksymalnego wieku: %s", "mode_invalid": "Tryb %s jest nieprawidłowy", "mx_invalid": "Rekord MX %s jest nieprawidłowy", "mysql_error": "Błąd MySQL: %s", "network_host_invalid": "Nieprawidłowa sieć lub host: %s", - "next_hop_interferes": "%s powoduje konflikt z nexthop %s.", + "next_hop_interferes": "%s powoduje konflikt z nexthopem %s", "next_hop_interferes_any": "Istniejący next hop koliduje z %s.”", "nginx_reload_failed": "Nie udało się przeładować Nginx: %s", "no_user_defined": "Brak zdefiniowanego użytkownika", @@ -523,17 +523,17 @@ "recovery_email_failed": "Nie można wysłać e-maila odzyskiwania. Skontaktuj się ze swoim administratorem.", "redis_error": "Błąd Redis: %s", "relayhost_invalid": "Wpis mapy %s jest niepoprawny", - "release_send_failed": "Nie udało się zwolnić wiadomości: %s.", + "release_send_failed": "Nie udało się zwolnić wiadomości: %s", "required_data_missing": "Brakuje wymaganych danych %s", "reset_f2b_regex": "Filtr Regex nie mógł zostać zresetowany na czas, spróbuj ponownie lub poczekaj jeszcze kilka sekund i przeładuj stronę.", - "reset_token_limit_exceeded": "Limit tokenów Reset został przekroczony. Spróbuj ponownie później", + "reset_token_limit_exceeded": "Limit tokenów Reset został przekroczony. Spróbuj ponownie później.", "rl_timeframe": "Nieprawidłowo ustawiony przedział czasu limitu", "rspamd_ui_pw_length": "Hasło do Rspamd UI powinno mieć co najmniej 6 znaków długości", "script_empty": "Skrypt nie może być pusty", "set_acl_failed": "Nie udało się ustawić ACL", "settings_map_invalid": "Ustawienia id mapy %s są nieprawidłowe", "sieve_error": "Błąd podczas analizy skryptu Sieve: %s", - "spam_learn_error": "Błąd uczenia spamu: %s.", + "spam_learn_error": "Błąd uczenia spamu: %s", "subject_empty": "Temat nie może być pusty", "targetd_relay_domain": "Domena docelowa %s jest skonfigurowana jako domena przekazująca relay", "template_exists": "Szablon %s już istnieje", @@ -608,7 +608,7 @@ "advanced_settings": "Ustawienia zaawansowane", "allow_from_smtp": "Zezwalaj tylko tym adresom IP na używanie SMTP", "allow_from_smtp_info": "Pozostaw puste, aby zezwolić na wszystkich nadawców.
adresy IPv4/IPv6 i sieci.", - "allowed_protocols": "Dozwolone protokoły dla bezpośredniego dostępu użytkownika (nie wpływa na protokoły haseł aplikacji).", + "allowed_protocols": "Dozwolone protokoły dla bezpośredniego dostępu użytkownika (nie wpływa na protokoły haseł aplikacji)", "app_name": "Nazwa aplikacji", "app_passwd": "Hasło do aplikacji", "app_passwd_protocols": "Dozwolone protokoły dla hasła aplikacji", @@ -616,10 +616,10 @@ "bcc_dest_format": "Miejscem docelowym BCC musi być jeden prawidłowy adres e-mail.
Jeśli chcesz wysłać kopię na wiele adresów, utwórz alias i użyj go tutaj.", "client_id": "Id klienta", "client_secret": "Tajny klucz klienta(sekret)", - "comment_info": "Komentarz prywatny nie jest widoczny dla użytkownika, natomiast komentarz publiczny jest wyświetlany jako podpowiedź po najechaniu kursorem w widoku użytkownika.", + "comment_info": "Komentarz prywatny nie jest widoczny dla użytkownika, natomiast komentarz publiczny jest wyświetlany jako podpowiedź po najechaniu kursorem w widoku użytkownika", "created_on": "Stworzony na", "custom_attributes": "Niestandardowe atrybuty", - "delete2": "Usunąć wiadomości na koncie docelowym, które nie występują na koncie źródłowym?", + "delete2": "Usuń wiadomości na koncie docelowym, które nie występują na koncie źródłowym", "disable_login": "Zablokuj logowanie (przychodząca poczta nadal będzie przyjmowana)", "domain_footer": "Stopka dla całej domeny", "domain_footer_html": "Stopka HTML", @@ -627,10 +627,10 @@ "domain_footer_info_vars": { "auth_user": "{= auth_user =} - Uwierzytelniona nazwa użytkownika określona przez MTA", "from_user": "{= from_user =} – część użytkownika (local-part) adresu nadawcy; np. dla „moo@mailcow.tld\n” zwróci „moo”", - "from_name": "{= from_name =} – nazwa nadawcy (From name) z nagłówka wiadomości; np. dla „Mailcow ” zwróci „Mailcow”.", + "from_name": "{= from_name =} – nazwa nadawcy (From name) z nagłówka wiadomości; np. dla \"Mailcow <moo@mailcow.tld>\" zwróci \"Mailcow\"", "from_addr": "{= from_addr =} – pełny adres nadawcy (z części envelope)", - "from_domain": "{= from_domain =} – część domenowa adresu nadawcy (z envelope).", - "custom": "{= foo =} - jeśli skrzynka pocztowa ma niestandardowy atrybut „foo” o wartości „bar”, zwraca „bar”." + "from_domain": "{= from_domain =} – część domenowa adresu nadawcy (z envelope)", + "custom": "{= foo =} - jeśli skrzynka pocztowa ma niestandardowy atrybut „foo” o wartości „bar”, zwraca „bar”" }, "domain_footer_plain": "Stopka w formacie tekstowym(PLAIN)", "domain_footer_skip_replies": "Nie dodawaj stopki do odpowiedzi na e-maile", @@ -646,7 +646,7 @@ "internal": "Wewnętrzny", "internal_info": "Aliasów wewnętrznych można używać tylko w obrębie własnej domeny lub domen aliasów.", "last_modified": "Ostatnio modyfikowany", - "lookup_mx": "Destination to wyrażenie regularne dopasowujące nazwę serwera MX (np. .*.google.com — aby kierować całą pocztę wysyłaną do MX kończących się na google.com przez ten hop).", + "lookup_mx": "Destination to wyrażenie regularne dopasowujące nazwę serwera MX (np. .*.google.com — aby kierować całą pocztę wysyłaną do MX kończących się na google.com przez ten hop)", "pushover_title": "Tytuł powiadomienia", "pushover_sound": "Dźwięk powiadomienia", "pushover_vars": "Gdy nie zdefiniowano żadnego filtra nadawcy, brane będą pod uwagę wszystkie wiadomości. Filtry oparte na wyrażeniach regularnych (regex) oraz dokładne dopasowania nadawców można definiować indywidualnie — będą one przetwarzane kolejno, niezależnie od siebie. Dostępne zmienne do użycia w treści i tytule (należy pamiętać o zasadach ochrony danych osobowych).", @@ -675,10 +675,15 @@ "timeout1": "Limit czasu połączenia z serwerem zdalnym", "timeout2": "Limit czasu połączenia z serwerem lokalnym", "validate_save": "Zatwierdź i zapisz", - "pushover_info": "Ustawienia powiadomień push będą stosowane do wszystkich czystych (nie-spamowych) dostarczanych wiadomości w tym aliasów (współdzielonych, niewspółdzielonych, oznaczonych).", + "pushover_info": "Ustawienia powiadomień push będą miały zastosowanie do wszystkich czystych (niespamowych) wiadomości dostarczanych do %s, w tym aliasów (współdzielonych, niewspółdzielonych, oznaczonych)", "mailbox_quota_def": "Domyślny limit skrzynki pocztowej", "mailbox_relayhost_info": "Dotyczy wyłącznie skrzynki pocztowej i bezpośrednich aliasów, nadpisuje ustawienie serwera pośredniczącego (relayhost) dla domeny.", - "maxbytespersecond": "Max. Ilość bajtów na sekundę
(0 = unlimited)" + "maxbytespersecond": "Max. Ilość bajtów na sekundę
(0 = unlimited)", + "mailbox_rename": "Zmień nazwę skrzynki pocztowej", + "mailbox_rename_agree": "Stworzyłem kopię zapasową.", + "mailbox_rename_warning": "WAŻNE! Utwórz kopię zapasową przed zmianą nazwy skrzynki pocztowej.", + "mailbox_rename_alias": "Tworzenie aliasów automatycznie", + "mailbox_rename_title": "Nowa nazwa lokalnej skrzynki pocztowej" }, "footer": { "cancel": "Anuluj", @@ -725,7 +730,7 @@ "other_logins": "lub zaloguj za pomocą", "email": "Adres e-mail", "back_to_mailcow": "Wróć do mailcow", - "fido2_webauthn": "FIDO2/WebAuthn Login", + "fido2_webauthn": "Logowanie FIDO2/WebAuthn", "invalid_pass_reset_token": "Token resetowania hasła jest nieprawidłowy lub wygasł.
Proszę poprosić o nowy link do resetowania hasła.", "login_user": "Logowanie użytkownika", "login_dadmin": "Logowanie administratora domeny", @@ -868,7 +873,7 @@ "ays": "Potwierdź, że chcesz usunąć wszystkie elementy z bieżącej kolejki.", "flush": "Opróżnij kolejkę wiadomości", "info": "Kolejka poczty zawiera wszystkie wiadomości e-mail oczekujące na dostarczenie.\nJeśli wiadomość e-mail pozostaje w kolejce przez dłuższy czas, system automatycznie ją usuwa.
\nKomunikat błędu dla danej wiadomości zawiera informacje o przyczynie, dla której nie mogła zostać dostarczona.", - "legend": "Funkcje zarządzania kolejką poczty", + "legend": "Funkcje zarządzania kolejką poczty:", "deliver_mail": "Dostarcz", "deliver_mail_legend": "Próby ponownego dostarczenia wybranych wiadomości.", "hold_mail": "Wstrzymane", @@ -1110,7 +1115,7 @@ "email_and_dav": "E-maile, kalendarze i kontakty", "empty": "Brak wyników", "expire_in": "wygasa w", - "fido2_webauthn": "FIDO2/WebAuthn", + "fido2_webauthn": "FIDO2/WebAuthn (standard uwierzytelniania)", "from": "od", "generate": "generuj", "last_mail_login": "Ostatni login na skrzynkę pocztową", @@ -1163,7 +1168,7 @@ "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Nie można połączyć się ze zdalnym serwerem", "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Niewłaściwa nazwa użytkownika lub hasło", "text": "Tekst", - "tfa_info": "Uwierzytelnianie dwuskładnikowe pomaga chronić Twoje konto.\nJeśli je włączysz, będziesz potrzebować haseł aplikacji, aby logować się do programów lub usług, które nie obsługują uwierzytelniania dwuskładnikowego (np. klientów poczty).", + "tfa_info": "Uwierzytelnianie dwuskładnikowe pomaga chronić Twoje konto. Jeśli je włączysz, będziesz potrzebować haseł aplikacji, aby logować się do programów lub usług, które nie obsługują uwierzytelniania dwuskładnikowego (np. klientów poczty).", "title": "Tytuł", "value": "Wartość", "verify": "Zweryfikuj", @@ -1190,7 +1195,7 @@ "decimal": ".", "emptyTable": "Brak danych w tabeli", "expand_all": "Rozszerz wszystko", - "info": "Wyświetlanie od START do END z TOTAL wpisów.", + "info": "Wyświetlanie od START do END z TOTAL wpisów", "infoEmpty": "Wyświetlanie od 0 do 0 z 0 wpisów", "infoFiltered": "(filtrowane z _MAX_ suma wpisów)", "thousands": ",", @@ -1221,7 +1226,7 @@ "current_time": "Czas systemowy", "disk_usage": "Użycie dysku", "docs": "Dokumentacja", - "error_show_ip": "Nie można ustalić publicznych adresów IP.", + "error_show_ip": "Nie można ustalić publicznych adresów IP", "external_logs": "Logi zewnętrzne", "history_all_servers": "Historia (wszystkie serwery)", "in_memory_logs": "Logi w pamięci", @@ -1253,7 +1258,7 @@ "dns_records": "Rekordy DNS", "dns_records_24hours": "Pamiętaj, że zmiany wprowadzone w DNS mogą zająć nawet do 24 godzin, zanim ich aktualny stan zostanie poprawnie odzwierciedlony na tej stronie.\nTa sekcja ma na celu ułatwienie Ci konfiguracji rekordów DNS oraz sprawdzenie, czy wszystkie rekordy zostały prawidłowo zapisane w DNS.", "dns_records_data": "Poprawne dane", - "dns_records_docs": "Proszę skonsultuj również dokumnetację", + "dns_records_docs": "Proszę skonsultuj również dokumnetację.", "dns_records_name": "Nazwa", "dns_records_status": "Aktualny stan", "dns_records_type": "Typ", From b873812588ce293ed878b9cbca123e48896e171f Mon Sep 17 00:00:00 2001 From: milkmaker Date: Sat, 29 Nov 2025 13:20:02 +0100 Subject: [PATCH 093/109] [Web] Updated lang.gr-gr.json (#6930) Co-authored-by: ChD Computers --- data/web/lang/lang.gr-gr.json | 165 ++++++++++++++++++++++++++++++++++ 1 file changed, 165 insertions(+) diff --git a/data/web/lang/lang.gr-gr.json b/data/web/lang/lang.gr-gr.json index 83008e63d..a070ea820 100644 --- a/data/web/lang/lang.gr-gr.json +++ b/data/web/lang/lang.gr-gr.json @@ -17,5 +17,170 @@ "hash_not_found": "Η κατακερματισμένη τιμή (hash value) δεν βρέθηκε ή έχει είδη διαγραφεί.", "ip_invalid": "Παραλείφθηκε μη έγκυρη διεύθυνση IP: %s", "is_not_primary_alias": "Παραλείφθηκε μη πρωτεύον ψευδώνυμο %s" + }, + "acl": { + "alias_domains": "Προσθήκη ψευδωνύμων τομέων", + "app_passwds": "Διαχείριση κωδικών εφαρμογής", + "bcc_maps": "χαρτογράφηση BCC", + "delimiter_action": "Ενέργεια οριοθέτη", + "domain_desc": "Αλλαγή περιγραφής τομέα", + "domain_relayhost": "Αλλαγή του διακομιστή αναμετάδοσης για ένα τομέα", + "eas_reset": "Επαναφορά συσκευών EAS", + "extend_sender_acl": "Να επιτρέπεται η επέκταση ACL του αποστολέα με εξωτερικές διευθύνσεις", + "filters": "Φίλτρα", + "login_as": "Είσοδος ως χρήστης e-mail", + "mailbox_relayhost": "Αλλαγή διακομιστή αναμετάδοσης για ένα γραμματοκιβώτιο", + "prohibited": "Απαγορεύεται από την ACL", + "protocol_access": "Αλλαγή πρόσβασης πρωτοκόλλου", + "pushover": "Pushover", + "pw_reset": "Επιτρέψτε την επαναφορά κωδικού πρόσβασης του χρήστη", + "quarantine": "Ενέργειες καραντίνας", + "quarantine_attachments": "Συνημμένα καραντίνας", + "quarantine_category": "Αλλαγή κατηγορίας ειδοποιήσεων καραντίνας", + "quarantine_notification": "Αλλαγή ειδοποιήσεων καραντίνας", + "ratelimit": "Όριο τιμής", + "recipient_maps": "Χάρτες παραληπτών", + "smtp_ip_access": "Αλλαγή επιτρεπόμενων διακομιστών SMTP", + "sogo_access": "Επιτρέψτε τη διαχείριση της πρόσβασης στο SOGo", + "sogo_profile_reset": "Επαναφορά του προφίλ SOGo", + "spam_alias": "Προσωρινά ψευδώνυμα", + "spam_policy": "Λίστα απορρίψεων/Λίστα επιτρεπόμενων", + "spam_score": "Βαθμολογία ανεπιθύμητης αλληλογραφίας", + "syncjobs": "Εργασίες συγχρονισμού", + "tls_policy": "Πολιτική TLS", + "unlimited_quota": "Απεριόριστο όριο για γραμματοκιβώτια" + }, + "add": { + "activate_filter_warn": "Όλα τα άλλα φίλτρα θα απενεργοποιηθούν, όταν επιλεγεί η επιλογή \"ενεργό\".", + "active": "Ενεργό", + "add": "Προσθήκη", + "add_domain_only": "Προσθήκη μόνο του τομέα", + "add_domain_restart": "Προσθήκη του τομέα και επανεκκίνηση του SOGo", + "alias_address": "Διευθύνσεις ψευδωνύμων", + "alias_address_info": "Πλήρης διεύθυνση(εις) e-mail ή @example.com, για να λαμβάνετε ΟΛΑ τα μηνύματα ενός τομέα (χωρισμένα με κόμα). μόνο τομείς του mailcow.", + "alias_domain": "Ψευδώνυμο τομέα", + "alias_domain_info": "Μόνο έγκυρα ονόματα τομέα (χωρισμένα με κόμα).", + "app_name": "Όνομα εφαρμογής", + "app_password": "Προσθήκη κωδικού εφαρμογής", + "app_passwd_protocols": "Επιτρεπόμενα πρωτόκολλα για κωδικούς εφαρμογών", + "automap": "Αυτόματη αντιστοίχηση φακέλων (\"Απεσταλμένα μηνύματα\", \"Απεσταλμένα\" => \"Στάλθηκαν\" κ.τ.λ.)", + "backup_mx_options": "Επιλογές αναμετάδοσης", + "bcc_dest_format": "Η BCC διεύθυνση πρέπει να είναι μία και έγκυρη διεύθυνση e-mail.
Αν θέλετε να στείλετε αντίγραφα σε πολλούς παραλήπτες, δημιουργήστε ένα ψευδόνυμο για όλους και χρησιμοποιήστε το εδώ.", + "comment_info": "Τα προσωπικά σχόλια δεν είναι ορατά στον χρήστη. Τα δημόσια σχόλια εμφανίζονται ως tooltips.", + "custom_params": "Προσαρμοσμένες παράμετροι", + "custom_params_hint": "Σωστή σύνταξη: --param=xy, λάθος σύνταξη: --param xy", + "delete1": "Διαγραφή όταν ολοκληρωθεί", + "delete2": "Διαγραφή μηνυμάτων στον προορισμό που δεν βρίσκονται στην πηγή", + "delete2duplicates": "Διαγραφή διπλότυπων στον προορισμό", + "description": "Περιγραφή", + "destination": "Προορισμός", + "disable_login": "Απαγόρευση εισόδου (η εισερχόμενη αλληλογραφία εξακολουθεί να γίνεται δεκτή)", + "domain": "Τομέας", + "domain_matches_hostname": "Ο τομέας %s είναι ο ίδιος με το όνομα του διακομιστή", + "domain_quota_m": "Συνολικό όριο τομέα (MiB)", + "dry": "Προσομοίωση συγχρονισμού", + "enc_method": "Μέθοδος κρυπτογράφησης", + "exclude": "Εξαίρεση αντικειμένων (regex)", + "full_name": "Πλήρες όνομα", + "gal": "Κοινόχρηστη λίστα διευθύνσεων" + }, + "danger": { + "unknown": "Παρουσιάστηκε κάποιο άγωνστο σφάλμα", + "unknown_tfa_method": "Άγνωστη μέθοδος TFA", + "unlimited_quota_acl": "Το απεριόριστο όριο απαγορεύεται από την ACL", + "username_invalid": "Το όνομα χρήστη %s δεν μπορεί να χρησιμοποιηθεί", + "validity_missing": "Παρακαλώ ορίστε μία περίοδο εγκυρότητας", + "value_missing": "Παρακαλώ συμπληρώστε όλα τα δεδομένα", + "version_invalid": "Η έκδοση %s δεν είναι έγκυρη", + "yotp_verification_failed": "Η επαλήθευση μέσω Yubico OTP απέτυχε: %s" + }, + "datatables": { + "collapse_all": "Σύμπτυξη όλων", + "decimal": ".", + "emptyTable": "Δεν υπάρχουν εγγραφές", + "expand_all": "Επέκταση όλων", + "info": "Εμφανίζονται _START_ εώς _END_ από _TOTAL_ εγγραφές", + "infoEmpty": "Εμφανίζονται 0 εώς 0 από 0 εγγραφές", + "infoFiltered": "(φιλτραρισμένες από _MAX_ συνολικές εγγραφές)", + "thousands": ",", + "lengthMenu": "Εμφάνιση _MENU_ εγγραφών", + "loadingRecords": "Γίνεται φόρτωση...", + "processing": "Παρακαλώ περιμένετε...", + "search": "Αναζήτηση:", + "zeroRecords": "Δε βρέθηκαν εγγραφές", + "paginate": { + "first": "Πρώτη", + "last": "Τελευταία", + "next": "Επόμενη", + "previous": "Προηγούμενη" + }, + "aria": { + "sortAscending": ": ενεργοποίηση αύξουσας ταξινόμησης", + "sortDescending": ": ενεργοποίηση φθίνουσας ταξινόμησης" + } + }, + "debug": { + "architecture": "Αρχιτεκτονική", + "chart_this_server": "Γράφημα (αυτός ο διακομιστής)", + "containers_info": "Πληροφορίες για τον container", + "container_running": "Εκτελείται", + "container_disabled": "Ο container έχει σταματήσει ή απενεργοποιηθεί", + "container_stopped": "Σταματημένος", + "cores": "Πυρήνες", + "current_time": "Ώρα συστήματος", + "disk_usage": "Χρήση αποθ. χώρου", + "docs": "Έγγραφα", + "error_show_ip": "Δεν είναι δυνατή η επίλυση της δημόσιας IP διεύθυνσης", + "external_logs": "Εξωτερικά αρχεία καταγραφής", + "history_all_servers": "Ιστορικό (Όλοι οι διακομιστές)", + "in_memory_logs": "Αρχεία καταγραφής στη μνήμη", + "last_modified": "Τελευταία τροποποίηση", + "log_info": "

mailcow in-memory logs are collected in Redis lists and trimmed to LOG_LINES (%d) every minute to reduce hammering.\n
In-memory logs are not meant to be persistent. All applications that log in-memory, also log to the Docker daemon and therefore to the default logging driver.\n
The in-memory log type should be used for debugging minor issues with containers.

\n

External logs are collected via API of the given application.

\n

Static logs are mostly activity logs, that are not logged to the Dockerd but still need to be persistent (except for API logs).

", + "login_time": "Ώρα", + "logs": "Αρχεία καταγραφής", + "memory": "Μνήμη", + "online_users": "Συνδεδεμένοι χρήστες", + "restart_container": "Επανεκκίνηση", + "service": "Υπηρεσία", + "show_ip": "Εμφάνιση δημόσιας IP", + "size": "Μέγεθος", + "started_at": "Ξεκίνησε στις", + "started_on": "Ξεκίνησε στις", + "static_logs": "Στατικά αρχεία καταγραφής", + "success": "Επιτυχία", + "system_containers": "Σύστημα και Containers", + "timezone": "Ζώνη ώρας", + "uptime": "Χρόνος λειτουργίας", + "update_available": "Υπάρχει διαθέσιμη ενημέρωση", + "no_update_available": "Έχετε τη τελευταία έκδοση του συστήματος", + "update_failed": "Δεν ήταν δυνατός ο έλεγχος για ενημερώσεις", + "username": "Όνομα χρήστη", + "wip": "Currently Work in Progress" + }, + "diagnostics": { + "cname_from_a": "Value derived from A/AAAA record. This is supported as long as the record points to the correct resource.", + "dns_records": "Εγγραφές DNS", + "dns_records_24hours": "Παρακαλώ σημειώστε ότι οι αλλαγές στο DNS μπορεί να χρειαστούν μέχρι 24 ώρες για να ενημερωθούν σωστά και να εμφανιστούν σε αυτή τη σελίδα. Ο σκοπός της είναι να δείτε πως μπορείτε να ρυθμίσετε σωστά τις εγγραφές DNS και να ελέγξετε αν είναι σωστές.", + "dns_records_data": "Σωστά δεδομένα", + "dns_records_docs": "Παρακαλώ συμβουλευτείτε επίσης την τεκμηρίωση.", + "dns_records_name": "Όνομα", + "dns_records_status": "Τρέχουσα κατάσταση", + "dns_records_type": "Τύπος", + "optional": "Αυτή η εγγραφή είναι προαιρετική." + }, + "edit": { + "acl": "ACL (Δικαίωμα)", + "active": "Ενεργό", + "admin": "Επεξεργασία διαχειριστή", + "advanced_settings": "Ρυθμίσεις για προχωρημένους", + "alias": "Επεξεργασία ψευδώνυμου", + "allow_from_smtp": "Επέτρεψε μόνο σε αυτές τις IPs να χρησιμοποιήσουν το SMTP", + "allow_from_smtp_info": "Αφήστε το κενό για να επιτρέψετε όλους τους αποστολείς.
IPv4/IPv6 διευθύνσεις και δίκτυα.", + "allowed_protocols": "Επιτρεπόμενα πρωτόκολλα για απ' ευθείας πρόσβαση από τους χρήστες (δεν επηρεάζει τα πρωτόκολλα κωδικών πρόσβασης εφαρμογής)", + "app_name": "Όνομα εφαρμογής", + "app_passwd": "Κωδικός πρόσβασης εφαρμογής", + "app_passwd_protocols": "Επιτρέπομενα πρωτόκολλα για τον κωδικό εφαρμογής", + "automap": "Αυτόματη αντιστοίχηση φακέλων (\"Απεσταλμένα μηνύματα\", \"Απεσταλμένα\" => \"Στάλθηκαν\" κ.τ.λ.)", + "backup_mx_options": "Επιλογές αναμετάδοσης" } } From 3d6253a2b25e6ca844b24c9666f67532e2d85c4a Mon Sep 17 00:00:00 2001 From: milkmaker Date: Mon, 1 Dec 2025 08:48:22 +0100 Subject: [PATCH 094/109] update postscreen_access.cidr (#6933) --- data/conf/postfix/postscreen_access.cidr | 59 ++++++++---------------- 1 file changed, 18 insertions(+), 41 deletions(-) diff --git a/data/conf/postfix/postscreen_access.cidr b/data/conf/postfix/postscreen_access.cidr index 3511c6ae4..694b98636 100644 --- a/data/conf/postfix/postscreen_access.cidr +++ b/data/conf/postfix/postscreen_access.cidr @@ -1,6 +1,6 @@ -# Whitelist generated by Postwhite v3.4 on Sat Nov 1 00:21:43 UTC 2025 +# Whitelist generated by Postwhite v3.4 on Mon Dec 1 00:24:43 UTC 2025 # https://github.com/stevejenkins/postwhite/ -# 2161 total rules +# 2186 total rules 2a00:1450:4000::/36 permit 2a01:111:f400::/48 permit 2a01:111:f403:2800::/53 permit @@ -29,7 +29,9 @@ 2a01:b747:3005:200::/56 permit 2a01:b747:3006:200::/56 permit 2a02:a60:0:5::/64 permit +2a0f:f640::/56 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 @@ -63,6 +65,7 @@ 13.111.191.0/24 permit 13.216.7.111 permit 13.216.54.180 permit +13.247.164.219 permit 15.200.21.50 permit 15.200.44.248 permit 15.200.201.185 permit @@ -394,23 +397,15 @@ 64.207.219.143 permit 64.233.160.0/19 permit 65.52.80.137 permit -65.54.51.64/26 permit -65.54.61.64/26 permit 65.54.121.120/29 permit -65.54.190.0/24 permit -65.54.241.0/24 permit 65.55.29.77 permit 65.55.33.64/28 permit -65.55.34.0/24 permit 65.55.42.224/28 permit 65.55.52.224/27 permit 65.55.78.128/25 permit 65.55.81.48/28 permit -65.55.90.0/24 permit 65.55.94.0/25 permit -65.55.111.0/24 permit 65.55.113.64/26 permit -65.55.116.0/25 permit 65.55.126.0/25 permit 65.55.174.0/25 permit 65.55.178.128/27 permit @@ -631,7 +626,6 @@ 74.208.4.220 permit 74.208.4.221 permit 74.209.250.0/24 permit -75.2.70.75 permit 76.223.128.0/19 permit 76.223.176.0/20 permit 77.238.176.0/24 permit @@ -660,18 +654,12 @@ 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 -82.165.159.4 permit 82.165.159.12 permit 82.165.159.13 permit 82.165.159.14 permit -82.165.159.34 permit -82.165.159.35 permit 82.165.159.40 permit 82.165.159.41 permit 82.165.159.42 permit -82.165.159.45 permit 82.165.159.130 permit 82.165.159.131 permit 85.9.206.169 permit @@ -1221,7 +1209,6 @@ 98.139.245.208/30 permit 98.139.245.212/31 permit 99.78.197.208/28 permit -99.83.190.102 permit 103.9.96.0/22 permit 103.28.42.0/24 permit 103.151.192.0/23 permit @@ -1454,6 +1441,16 @@ 134.170.143.0/24 permit 134.170.174.0/24 permit 135.84.216.0/22 permit +136.143.160.0/24 permit +136.143.161.0/24 permit +136.143.162.0/24 permit +136.143.176.0/24 permit +136.143.177.0/24 permit +136.143.178.49 permit +136.143.182.0/23 permit +136.143.184.0/24 permit +136.143.188.0/24 permit +136.143.190.0/23 permit 136.146.128.0/20 permit 136.147.128.0/20 permit 136.147.135.0/24 permit @@ -1525,9 +1522,6 @@ 155.248.220.138 permit 155.248.234.149 permit 155.248.237.141 permit -157.55.0.192/26 permit -157.55.1.128/26 permit -157.55.2.0/25 permit 157.55.9.128/25 permit 157.55.11.0/25 permit 157.55.49.0/25 permit @@ -1625,13 +1619,11 @@ 170.10.132.56/29 permit 170.10.132.64/29 permit 170.10.133.0/24 permit -172.217.32.0/21 permit -172.253.56.0/21 permit -172.253.112.0/20 permit 173.0.84.0/29 permit 173.0.84.224/27 permit 173.0.94.244/30 permit 173.194.0.0/16 permit +173.194.0.0/17 permit 173.203.79.182 permit 173.203.81.39 permit 173.224.161.128/25 permit @@ -1771,6 +1763,7 @@ 194.97.212.12 permit 194.106.220.0/23 permit 194.113.24.0/22 permit +194.113.42.0/26 permit 194.154.193.192/27 permit 195.4.92.0/23 permit 195.54.172.0/23 permit @@ -1784,6 +1777,7 @@ 198.61.254.21 permit 198.61.254.231 permit 198.178.234.57 permit +198.202.211.1 permit 198.244.48.0/20 permit 198.244.56.107 permit 198.244.56.108 permit @@ -1894,7 +1888,6 @@ 207.46.52.79 permit 207.46.58.128/25 permit 207.46.116.128/29 permit -207.46.117.0/24 permit 207.46.132.128/27 permit 207.46.198.0/25 permit 207.46.200.0/27 permit @@ -2000,19 +1993,11 @@ 212.82.111.228/31 permit 212.82.111.230 permit 212.123.28.40 permit -212.227.15.3 permit -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 212.227.15.19 permit -212.227.15.25 permit -212.227.15.26 permit -212.227.15.29 permit 212.227.15.44 permit 212.227.15.45 permit 212.227.15.46 permit @@ -2020,17 +2005,11 @@ 212.227.15.50 permit 212.227.15.52 permit 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 @@ -2115,8 +2094,6 @@ 216.205.24.0/24 permit 216.221.160.0/19 permit 216.239.32.0/19 permit -217.72.192.77 permit -217.72.192.78 permit 217.77.141.52 permit 217.77.141.59 permit 217.175.194.0/24 permit From 6c106b4e4dfffc2bd6fc87b60f7dbe12eb917d63 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Tue, 2 Dec 2025 16:40:36 +0100 Subject: [PATCH 095/109] [Web] Updated lang.fr-fr.json (#6936) Co-authored-by: Neuronnexion --- data/web/lang/lang.fr-fr.json | 30 ++++++++++++++++++++++++------ 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 07ac641b8..107988bac 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -109,7 +109,9 @@ "bcc_dest_format": "La destination Cci doit être une seule adresse de courriel valide.
Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.", "tags": "Etiquettes", "app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application", - "dry": "Simuler la synchronisation" + "dry": "Simuler la synchronisation", + "internal": "Interne", + "internal_info": "Les alias internes sont accessibles uniquement depuis le domaine ou les alias du domaine." }, "admin": { "access": "Accès", @@ -407,7 +409,8 @@ "iam_host": "Hôte", "iam_host_info": "Saisissez un ou plusieurs hôtes LDAP, séparés par des virgules.", "iam_import_users": "Importer des utilisateurs", - "filter": "Filtrer" + "filter": "Filtrer", + "needs_restart": "nécessite un redémarrage" }, "danger": { "access_denied": "Accès refusé ou données de formulaire non valides", @@ -548,7 +551,11 @@ "generic_server_error": "Une erreur de serveur inattendue s'est produite. Veuillez contacter votre administrateur.", "authsource_in_use": "Le fournisseur d'identité ne peut pas être modifié ou supprimé car il est actuellement utilisé par un ou plusieurs utilisateurs.", "iam_test_connection": "Échec de la connexion", - "required_data_missing": "La donnée requise %s est manquante" + "required_data_missing": "La donnée requise %s est manquante", + "max_age_invalid": "L'âge maximum %s est invalide", + "mode_invalid": "Le mode %s est invalide", + "mx_invalid": "L'enregistrement MX %s est invalide", + "version_invalid": "La version %s est invalide" }, "debug": { "chart_this_server": "Graphique (ce serveur)", @@ -734,7 +741,16 @@ "mailbox_rename_alias": "Créer un alias automatiquement", "sogo_access": "Redirection directe vers SOGo", "pushover": "Pushover", - "pushover_sound": "Son" + "pushover_sound": "Son", + "internal": "Interne", + "internal_info": "Les alias internes sont accessibles uniquement depuis le domaine ou les alias du domaine.", + "mta_sts": "MTA-STS", + "mta_sts_version": "Version", + "mta_sts_version_info": "Défini la version du standard MTA-STS – actuellement seul STSv1 est valide.", + "mta_sts_mode": "Mode", + "mta_sts_max_age": "Âge maximum", + "mta_sts_mx": "Serveur MX", + "mta_sts_mx_notice": "Plusieurs serveurs MX peuvent être spécifiés (séparés par des virgules)." }, "footer": { "cancel": "Annuler", @@ -789,7 +805,8 @@ "login_linkstext": "L'identifiant n'est pas correct ?", "login_usertext": "Se connecter en tant qu'utilisateur", "login_domainadmintext": "Se connecter en tant qu'administrateur du domaine", - "login_admintext": "Se connecter en tant qu'administrateur" + "login_admintext": "Se connecter en tant qu'administrateur", + "email": "Adresse de courriel" }, "mailbox": { "action": "Action", @@ -965,7 +982,8 @@ "syncjob_check_log": "Vérifier le journal", "recipient": "Destinataire", "open_logs": "Afficher les journaux", - "iam": "Fournisseur d'identité" + "iam": "Fournisseur d'identité", + "internal": "Interne" }, "oauth2": { "access_denied": "Veuillez vous connecter en tant que propriétaire de la boîte de réception pour accorder l’accès via Oauth2.", From 470cfb00263551e205cbaf7908dedcf26364ce4a Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 13:53:05 +0100 Subject: [PATCH 096/109] chore(deps): update actions/stale action to v10.1.1 (#6937) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .github/workflows/close_old_issues_and_prs.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/close_old_issues_and_prs.yml b/.github/workflows/close_old_issues_and_prs.yml index 85094394a..f3306b7df 100644 --- a/.github/workflows/close_old_issues_and_prs.yml +++ b/.github/workflows/close_old_issues_and_prs.yml @@ -14,7 +14,7 @@ jobs: pull-requests: write steps: - name: Mark/Close Stale Issues and Pull Requests 🗑️ - uses: actions/stale@v10.1.0 + uses: actions/stale@v10.1.1 with: repo-token: ${{ secrets.STALE_ACTION_PAT }} days-before-stale: 60 From 9950914086124be1c9abe9dd35aefa7d3b64ffab Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 3 Dec 2025 16:26:22 +0100 Subject: [PATCH 097/109] core: improved docker compose version check --- _modules/scripts/core.sh | 74 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/_modules/scripts/core.sh b/_modules/scripts/core.sh index f776c6212..576967a48 100644 --- a/_modules/scripts/core.sh +++ b/_modules/scripts/core.sh @@ -38,45 +38,45 @@ get_docker_version(){ } get_compose_type(){ - if docker compose > /dev/null 2>&1; then - if docker compose version --short | grep -e "^2." -e "^v2." > /dev/null 2>&1; then - COMPOSE_VERSION=native - COMPOSE_COMMAND="docker compose" - if [[ "$caller" == "update.sh" ]]; then - sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' "$SCRIPT_DIR/mailcow.conf" - fi - echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" - echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" - sleep 2 - echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" - else - echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 - fi - elif docker-compose > /dev/null 2>&1; then - if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then - if docker-compose version --short | grep "^2." > /dev/null 2>&1; then - COMPOSE_VERSION=standalone - COMPOSE_COMMAND="docker-compose" - if [[ "$caller" == "update.sh" ]]; then - sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' "$SCRIPT_DIR/mailcow.conf" - fi - echo -e "\e[33mFound Docker Compose Standalone.\e[0m" - echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" - sleep 2 - echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" - else - echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 - fi - fi + if docker compose > /dev/null 2>&1; then + if docker compose version --short | grep -e "^[2-9]\." -e "^v[2-9]\." -e "^[1-9][0-9]\." -e "^v[1-9][0-9]\." > /dev/null 2>&1; then + COMPOSE_VERSION=native + COMPOSE_COMMAND="docker compose" + if [[ "$caller" == "update.sh" ]]; then + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' "$SCRIPT_DIR/mailcow.conf" + fi + echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" + sleep 2 + echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" else - echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 + echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 fi + elif docker-compose > /dev/null 2>&1; then + if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then + if docker-compose version --short | grep -e "^[2-9]\." -e "^[1-9][0-9]\." > /dev/null 2>&1; then + COMPOSE_VERSION=standalone + COMPOSE_COMMAND="docker-compose" + if [[ "$caller" == "update.sh" ]]; then + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' "$SCRIPT_DIR/mailcow.conf" + fi + echo -e "\e[33mFound Docker Compose Standalone.\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" + sleep 2 + echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" + else + echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" + echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 + fi + fi + else + echo -e "\e[31mCannot find Docker Compose.\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 + fi } detect_bad_asn() { From 9a2887cf46074d1cb9ad17be5a3bbcdf662fd1cf Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 3 Dec 2025 16:26:22 +0100 Subject: [PATCH 098/109] core: improved docker compose version check --- _modules/scripts/core.sh | 74 ++++++++++++++++++++-------------------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/_modules/scripts/core.sh b/_modules/scripts/core.sh index f776c6212..576967a48 100644 --- a/_modules/scripts/core.sh +++ b/_modules/scripts/core.sh @@ -38,45 +38,45 @@ get_docker_version(){ } get_compose_type(){ - if docker compose > /dev/null 2>&1; then - if docker compose version --short | grep -e "^2." -e "^v2." > /dev/null 2>&1; then - COMPOSE_VERSION=native - COMPOSE_COMMAND="docker compose" - if [[ "$caller" == "update.sh" ]]; then - sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' "$SCRIPT_DIR/mailcow.conf" - fi - echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" - echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" - sleep 2 - echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" - else - echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 - fi - elif docker-compose > /dev/null 2>&1; then - if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then - if docker-compose version --short | grep "^2." > /dev/null 2>&1; then - COMPOSE_VERSION=standalone - COMPOSE_COMMAND="docker-compose" - if [[ "$caller" == "update.sh" ]]; then - sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' "$SCRIPT_DIR/mailcow.conf" - fi - echo -e "\e[33mFound Docker Compose Standalone.\e[0m" - echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" - sleep 2 - echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" - else - echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" - echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 - fi - fi + if docker compose > /dev/null 2>&1; then + if docker compose version --short | grep -e "^[2-9]\." -e "^v[2-9]\." -e "^[1-9][0-9]\." -e "^v[1-9][0-9]\." > /dev/null 2>&1; then + COMPOSE_VERSION=native + COMPOSE_COMMAND="docker compose" + if [[ "$caller" == "update.sh" ]]; then + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' "$SCRIPT_DIR/mailcow.conf" + fi + echo -e "\e[33mFound Docker Compose Plugin (native).\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m" + sleep 2 + echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m" else - echo -e "\e[31mCannot find Docker Compose.\e[0m" - echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" - exit 1 + echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" + echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 fi + elif docker-compose > /dev/null 2>&1; then + if ! [[ $(alias docker-compose 2> /dev/null) ]] ; then + if docker-compose version --short | grep -e "^[2-9]\." -e "^[1-9][0-9]\." > /dev/null 2>&1; then + COMPOSE_VERSION=standalone + COMPOSE_COMMAND="docker-compose" + if [[ "$caller" == "update.sh" ]]; then + sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' "$SCRIPT_DIR/mailcow.conf" + fi + echo -e "\e[33mFound Docker Compose Standalone.\e[0m" + echo -e "\e[33mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m" + sleep 2 + echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m" + else + echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m" + echo -e "\e[31mPlease update/install manually regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 + fi + fi + else + echo -e "\e[31mCannot find Docker Compose.\e[0m" + echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/install/\e[0m" + exit 1 + fi } detect_bad_asn() { From 930ca76ea768f6205c5041905afbc9e226cb3105 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 3 Dec 2025 16:54:26 +0100 Subject: [PATCH 099/109] update: moved _modules initialization and update at the beginning of update script --- update.sh | 47 +++++++++++++++++++++-------------------------- 1 file changed, 21 insertions(+), 26 deletions(-) diff --git a/update.sh b/update.sh index 4ec0e7e40..74eb8ff2c 100755 --- a/update.sh +++ b/update.sh @@ -20,11 +20,28 @@ fi BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)" MODULE_DIR="${SCRIPT_DIR}/_modules" +# Calculate hash before fetch +if [[ -d "${MODULE_DIR}" && -n "$(ls -A "${MODULE_DIR}" 2>/dev/null)" ]]; then + MODULES_HASH_BEFORE=$(find "${MODULE_DIR}" -type f -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | awk '{print $1}') +else + MODULES_HASH_BEFORE="EMPTY" +fi + +echo -e "\e[33mFetching latest _modules from origin/${BRANCH}…\e[0m" +git fetch origin "${BRANCH}" +git checkout "origin/${BRANCH}" -- _modules + if [[ ! -d "${MODULE_DIR}" || -z "$(ls -A "${MODULE_DIR}")" ]]; then - echo -e "\e[33m_modules is missing or empty – fetching all Modules from origin/${BRANCH}…\e[0m" - git fetch origin "${BRANCH}" - git checkout "origin/${BRANCH}" -- _modules - echo -e "\e[33mDone. Please restart the script...\e[0m" + echo -e "\e[31mError: _modules is still missing or empty after fetch!\e[0m" + exit 2 +fi + +# Calculate hash after fetch +MODULES_HASH_AFTER=$(find "${MODULE_DIR}" -type f -exec sha256sum {} \; 2>/dev/null | sort | sha256sum | awk '{print $1}') + +# Check if modules changed +if [[ "${MODULES_HASH_BEFORE}" != "${MODULES_HASH_AFTER}" ]]; then + echo -e "\e[33m_modules have been updated. Please restart the update script.\e[0m" exit 2 fi @@ -320,28 +337,6 @@ if [ ! "$DEV" ]; then chmod +x update.sh EXIT_COUNT+=1 fi - - MODULE_DIR="$(dirname "$0")/_modules" - echo -e "\e[32mChecking for updates in _modules...\e[0m" - if [ ! -d "${MODULE_DIR}" ] || [ -z "$(ls -A "${MODULE_DIR}")" ]; then - echo -e "\e[33m_modules missing or empty — fetching from origin...\e[0m" - git checkout "origin/${BRANCH}" -- _modules - else - OLD_SUM="$(find "${MODULE_DIR}" -type f -exec sha1sum {} \; | sort | sha1sum)" - git fetch origin - git checkout "origin/${BRANCH}" -- _modules - NEW_SUM="$(find "${MODULE_DIR}" -type f -exec sha1sum {} \; | sort | sha1sum)" - - if [[ "${OLD_SUM}" != "${NEW_SUM}" ]]; then - EXIT_COUNT+=1 - fi - fi - - if [ ${EXIT_COUNT} -ge 1 ]; then - echo "Changes for the update Script, please run this script again, exiting!" - exit 2 - fi - fi if [ ! "$FORCE" ]; then From 32a6ecddb614acee1f2a70f2f0e1d0d23d5221ae Mon Sep 17 00:00:00 2001 From: "renovate[bot]" <29139614+renovate[bot]@users.noreply.github.com> Date: Wed, 3 Dec 2025 23:30:46 +0100 Subject: [PATCH 100/109] chore(deps): update alpine docker tag to v3.23 (#6940) Signed-off-by: milkmaker Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> --- .../EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml b/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml index a0b63b3a6..5ef729a48 100644 --- a/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml +++ b/helper-scripts/docker-compose.override.yml.d/EXTERNAL_MYSQL_SOCKET/docker-compose.override.yml @@ -25,6 +25,6 @@ services: - /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock mysql-mailcow: - image: alpine:3.22 + image: alpine:3.23 command: /bin/true restart: "no" From 4e3294b273abf112a7ae3acf77d3ad6357ec700a Mon Sep 17 00:00:00 2001 From: milkmaker Date: Wed, 3 Dec 2025 23:31:37 +0100 Subject: [PATCH 101/109] [Web] Updated lang.fr-fr.json (#6941) [Web] Updated lang.fr-fr.json [Web] Updated lang.fr-fr.json Co-authored-by: Neuronnexion --- data/web/lang/lang.fr-fr.json | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index 107988bac..cf3ba7831 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -16,7 +16,7 @@ "quarantine_notification": "Modifier la notification de quarantaine", "quarantine_category": "Modifier la catégorie de la notification de quarantaine", "ratelimit": "Limite d'envoi", - "recipient_maps": "Cartes destinataire", + "recipient_maps": "Cartes des destinataires", "smtp_ip_access": "Changer les hôtes autorisés pour SMTP", "sogo_access": "Autoriser la gestion des accès à SOGo", "sogo_profile_reset": "Réinitialiser le profil SOGo", @@ -444,7 +444,7 @@ "global_filter_write_error": "Impossible d’écrire le fichier de filtre : %s", "global_map_invalid": "ID de carte globale %s non valide", "global_map_write_error": "Impossible d’écrire l’ID de la carte globale %s : %s", - "goto_empty": "Une adresse alias doit contenir au moins une adresse 'goto'valide", + "goto_empty": "Une adresse alias doit contenir au moins une adresse 'goto' valide", "goto_invalid": "Adresse Goto %s non valide", "ham_learn_error": "Erreur d'apprentissage Ham : %s", "imagick_exception": "Erreur : Exception Imagick lors de la lecture de l’image", @@ -700,7 +700,7 @@ "spam_score": "Définir un score spam personnalisé", "subfolder2": "Synchronisation dans le sous-dossier sur la destination
(vide = ne pas utiliser de sous-dossier)", "syncjob": "Modifier la tâche de synchronisation", - "target_address": "Adresse(s) Goto(séparé(s) par des virgules)", + "target_address": "Adresse(s) Goto (séparé(s) par des virgules)", "target_domain": "Domaine cible", "timeout1": "Délai de connexion à l’hôte distant", "timeout2": "Délai de connexion à l’hôte local", @@ -750,7 +750,11 @@ "mta_sts_mode": "Mode", "mta_sts_max_age": "Âge maximum", "mta_sts_mx": "Serveur MX", - "mta_sts_mx_notice": "Plusieurs serveurs MX peuvent être spécifiés (séparés par des virgules)." + "mta_sts_mx_notice": "Plusieurs serveurs MX peuvent être spécifiés (séparés par des virgules).", + "mta_sts_info": "MTA-STS est un standard qui oblige la délivrance des courriels entre les serveurs de courriels à utiliser TLS avec des certificats valides.
Il est utilisé quand DANE n'est pas possible à cause d'un manque ou d'un non support de DNSSEC.
Note : Si le domaine du destinataire supporte DANE avec DNSSEC, DANE est toujours préféré – MTA-STS sert seulement en secours.", + "mta_sts_mode_info": "Il y a trois modes parmi lesquels choisir :
  • testing – la politique est seulement surveillée, les violations n'ont pas d'impact.
  • enforce – la politique est appliquée strictement, les connexions sans TLS valide sont rejetées.
  • none – la politique est publiée mais non appliquée.
", + "mta_sts_max_age_info": "Durée en secondes pendant laquelle les serveurs de courriel peuvent mettre en cache cette politique avant de revérifier.", + "mta_sts_mx_info": "Autoriser l'envoi uniquement aux noms d'hôtes des serveurs de courriels indiqués explicitement ; le MTA émetteur vérifie si le nom d'hôte DNS du MX correspond à la liste de la politique, et autorise la délivrance seulement avec un certificat TLS valide (protège contre le MITM)." }, "footer": { "cancel": "Annuler", @@ -913,7 +917,7 @@ "recipient_map_new_info": "La destination de la carte du destinataire doit être une adresse de courriel valide ou un nom de domaine.", "recipient_map_old": "Destinataire original", "recipient_map_old_info": "La destination originale des cartes des destinataires doit être une adresse de courriel valide ou un nom de domaine.", - "recipient_maps": "Cartes des bénéficiaires", + "recipient_maps": "Cartes des destinataires", "relay_all": "Relayer tous les destinataires", "remove": "Supprimer", "resources": "Ressources", @@ -1240,7 +1244,7 @@ "email_and_dav": "Courriel, calendriers et contacts", "encryption": "Chiffrement", "excludes": "Exclus", - "expire_in": "Expire dans", + "expire_in": "Expirer dans", "force_pw_update": "Vous devez définir un nouveau mot de passe pour pouvoir accéder aux services liés aux logiciels de groupe.", "generate": "générer", "hour": "heure", @@ -1368,7 +1372,10 @@ "mailbox_general": "Général", "mailbox_settings": "Paramètres", "tfa_info": "L'authentification à deux facteurs permet de protéger votre compte. Si vous l'activez, vous aurez besoin de mots de passe d'application pour vous connecter à des applications ou des services qui ne prennent pas en charge l'authentification à deux facteurs (par exemple les clients e-mails).", - "overview": "Vue d'ensemble" + "overview": "Vue d'ensemble", + "expire_never": "Ne jamais expirer", + "forever": "Pour toujours", + "spam_aliases_info": "Un alias de spam est une adresse de courriel temporaire qui peut être utilisée pour protéger les véritables adresses de courriel.
De manière optionnelle, une durée d'expiration peut être définie afin que l'alias soit automatiquement désactivé après la période définie, éliminant ainsi les adresses étant abusées ou ayant fuité." }, "warning": { "cannot_delete_self": "Impossible de supprimer l’utilisateur connecté", From 79171ea6f546f561eeca83790623ca6077325b50 Mon Sep 17 00:00:00 2001 From: milkmaker Date: Fri, 5 Dec 2025 14:40:45 +0100 Subject: [PATCH 102/109] [Web] Updated lang.fr-fr.json (#6943) Co-authored-by: Neuronnexion --- data/web/lang/lang.fr-fr.json | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/data/web/lang/lang.fr-fr.json b/data/web/lang/lang.fr-fr.json index cf3ba7831..af0df47c9 100644 --- a/data/web/lang/lang.fr-fr.json +++ b/data/web/lang/lang.fr-fr.json @@ -410,7 +410,8 @@ "iam_host_info": "Saisissez un ou plusieurs hôtes LDAP, séparés par des virgules.", "iam_import_users": "Importer des utilisateurs", "filter": "Filtrer", - "needs_restart": "nécessite un redémarrage" + "needs_restart": "nécessite un redémarrage", + "iam": "Fournisseur d'identité" }, "danger": { "access_denied": "Accès refusé ou données de formulaire non valides", @@ -1375,7 +1376,9 @@ "overview": "Vue d'ensemble", "expire_never": "Ne jamais expirer", "forever": "Pour toujours", - "spam_aliases_info": "Un alias de spam est une adresse de courriel temporaire qui peut être utilisée pour protéger les véritables adresses de courriel.
De manière optionnelle, une durée d'expiration peut être définie afin que l'alias soit automatiquement désactivé après la période définie, éliminant ainsi les adresses étant abusées ou ayant fuité." + "spam_aliases_info": "Un alias de spam est une adresse de courriel temporaire qui peut être utilisée pour protéger les véritables adresses de courriel.
De manière optionnelle, une durée d'expiration peut être définie afin que l'alias soit automatiquement désactivé après la période définie, éliminant ainsi les adresses étant abusées ou ayant fuité.", + "authentication": "Authentification", + "protocols": "Protocoles" }, "warning": { "cannot_delete_self": "Impossible de supprimer l’utilisateur connecté", From ef010aa39c7e6e8ad228bd32165612a8749ed62b Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Mon, 8 Dec 2025 15:08:25 +0100 Subject: [PATCH 103/109] Update CONTRIBUTING.md Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- CONTRIBUTING.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index d27c09de8..5e194b20d 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -5,7 +5,7 @@ First of all, thank you for wanting to provide a bugfix or a new feature for the As we want to keep mailcow's development structured we setup these Guidelines which helps you to create your issue/pull request accordingly. -**PLEASE NOTE, THAT WE WILL CLOSE ISSUES/PULL REQUESTS IF THEY DON'T FULLFIL OUR WRITTEN GUIDELINES WRITTEN INSIDE THIS DOCUMENT**. So please check this guidelines before you propose a Issue/Pull Request. +**PLEASE NOTE, THAT WE WILL CLOSE ISSUES/PULL REQUESTS IF THEY DON'T FULFILL OUR WRITTEN GUIDELINES WRITTEN INSIDE THIS DOCUMENT**. So please check this guidelines before you propose a Issue/Pull Request. ## Topics From f8eed8c78698ce492f176641bb75ccbeefd24546 Mon Sep 17 00:00:00 2001 From: Khurram Malik Date: Tue, 9 Dec 2025 11:54:20 +0100 Subject: [PATCH 104/109] fix(api): add missing break in CORS switch block causing save to hang (#6926) --- data/web/json_api.php | 1 + 1 file changed, 1 insertion(+) diff --git a/data/web/json_api.php b/data/web/json_api.php index 4d7159ad2..565246e58 100644 --- a/data/web/json_api.php +++ b/data/web/json_api.php @@ -1992,6 +1992,7 @@ if (isset($_GET['query'])) { break; case "cors": process_edit_return(cors('edit', $attr)); + break; case "identity-provider": process_edit_return(identity_provider('edit', $attr)); break; From dbb9e474b0d171ddaee959c2cc30eb12691be836 Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Tue, 9 Dec 2025 13:25:50 +0100 Subject: [PATCH 105/109] pf-tlspol: upgrade to 1.8.22 (#6951) * postfix-tlspol: upgrade to 1.8.20 * pf-tlspol: update to 1.8.22 --- data/Dockerfiles/postfix-tlspol/Dockerfile | 2 +- docker-compose.yml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/postfix-tlspol/Dockerfile b/data/Dockerfiles/postfix-tlspol/Dockerfile index c32f86f57..68f6ecced 100644 --- a/data/Dockerfiles/postfix-tlspol/Dockerfile +++ b/data/Dockerfiles/postfix-tlspol/Dockerfile @@ -4,7 +4,7 @@ WORKDIR /src ENV CGO_ENABLED=0 \ GO111MODULE=on \ NOOPT=1 \ - VERSION=1.8.14 + VERSION=1.8.22 RUN git clone --branch v${VERSION} https://github.com/Zuplu/postfix-tlspol && \ cd /src/postfix-tlspol && \ diff --git a/docker-compose.yml b/docker-compose.yml index f7390c797..75d00af34 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -382,7 +382,7 @@ services: - postfix postfix-tlspol-mailcow: - image: ghcr.io/mailcow/postfix-tlspol:1.0 + image: ghcr.io/mailcow/postfix-tlspol:1.8.22 depends_on: unbound-mailcow: condition: service_healthy From c11ed5dd1e899173500161ebf52e572de42917ca Mon Sep 17 00:00:00 2001 From: Copilot <198982749+Copilot@users.noreply.github.com> Date: Fri, 12 Dec 2025 12:34:20 +0100 Subject: [PATCH 106/109] Prevent duplicate/plaintext login announcement rendering (#6963) * Initial plan * Fix duplicate login announcement display Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> --------- Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com> Co-authored-by: DerLinkman <62480600+DerLinkman@users.noreply.github.com> --- data/web/templates/base.twig | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/web/templates/base.twig b/data/web/templates/base.twig index a8d0f6f39..98fdd86e4 100644 --- a/data/web/templates/base.twig +++ b/data/web/templates/base.twig @@ -144,7 +144,7 @@
-{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri %} +{% if ui_texts.ui_announcement_text and ui_texts.ui_announcement_active and not is_root_uri and mailcow_cc_username %}
{{ ui_texts.ui_announcement_text }}
From e76f5237edcccd8fdcc613e22f9d9b84265459db Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Thu, 11 Dec 2025 13:29:11 +0100 Subject: [PATCH 107/109] ofelia: revert fixed cron syntax for sa-rules download --- docker-compose.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docker-compose.yml b/docker-compose.yml index 75d00af34..ae9a18d98 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -321,7 +321,7 @@ services: ofelia.job-exec.dovecot_clean_q_aged.command: "/bin/bash -c \"[[ $${MASTER} == y ]] && /usr/local/bin/gosu vmail /usr/local/bin/clean_q_aged.sh || exit 0\"" ofelia.job-exec.dovecot_maildir_gc.schedule: "0 */30 * * * *" ofelia.job-exec.dovecot_maildir_gc.command: "/bin/bash -c \"source /source_env.sh ; /usr/local/bin/gosu vmail /usr/local/bin/maildir_gc.sh\"" - ofelia.job-exec.dovecot_sarules.schedule: "0 0 0 * * *" + ofelia.job-exec.dovecot_sarules.schedule: "@every 24h" ofelia.job-exec.dovecot_sarules.command: "/bin/bash -c \"/usr/local/bin/sa-rules.sh\"" ofelia.job-exec.dovecot_fts.schedule: "0 0 0 * * *" ofelia.job-exec.dovecot_fts.command: "/bin/bash -c \"/usr/local/bin/gosu vmail /usr/local/bin/optimize-fts.sh\"" From d977ddb5017e27f817f09310dcb7056449cb88fd Mon Sep 17 00:00:00 2001 From: DerLinkman Date: Wed, 10 Dec 2025 08:43:04 +0100 Subject: [PATCH 108/109] backup: add image prefetch function to verify latest image is used --- helper-scripts/backup_and_restore.sh | 38 ++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) diff --git a/helper-scripts/backup_and_restore.sh b/helper-scripts/backup_and_restore.sh index 7b75272cf..2e65f1343 100755 --- a/helper-scripts/backup_and_restore.sh +++ b/helper-scripts/backup_and_restore.sh @@ -91,6 +91,44 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then exit 1 fi +# Add image prefetch function +function prefetch_image() { + echo "Checking Docker image: ${DEBIAN_DOCKER_IMAGE}" + + # Get local image digest if it exists + local local_digest=$(docker image inspect ${DEBIAN_DOCKER_IMAGE} --format='{{index .RepoDigests 0}}' 2>/dev/null | cut -d'@' -f2) + + # Get remote image digest without pulling + local remote_digest=$(docker manifest inspect ${DEBIAN_DOCKER_IMAGE} 2>/dev/null | grep -oP '"digest":\s*"\K[^"]+' | head -1) + + if [[ -z "${remote_digest}" ]]; then + echo "Warning: Unable to check remote image" + if [[ -n "${local_digest}" ]]; then + echo "Using cached version" + echo + return 0 + else + echo "Error: Image ${DEBIAN_DOCKER_IMAGE} not found locally or remotely" + exit 1 + fi + fi + + if [[ "${local_digest}" != "${remote_digest}" ]]; then + echo "Image update available, pulling ${DEBIAN_DOCKER_IMAGE}" + if docker pull ${DEBIAN_DOCKER_IMAGE} 2>/dev/null; then + echo "Successfully pulled ${DEBIAN_DOCKER_IMAGE}" + else + echo "Error: Failed to pull ${DEBIAN_DOCKER_IMAGE}" + exit 1 + fi + else + echo "Image is up to date (${remote_digest:0:12}...)" + fi + echo +} + +# Prefetch the image early in the script +prefetch_image function backup() { DATE=$(date +"%Y-%m-%d-%H-%M-%S") From e8d9315d4ad6ae886b8146f618df1813db546254 Mon Sep 17 00:00:00 2001 From: Ashitaka <65665184+Ashitaka57@users.noreply.github.com> Date: Wed, 10 Dec 2025 11:41:06 +0100 Subject: [PATCH 109/109] Merge pull request #6905 from Ashitaka57/6646-pbkdf2-sha512-verify-hash Support for PBKDF2-SHA512 hash algorithm in verify_hash() (FreeIPA compatibility) (issue 6646) --- data/web/inc/functions.inc.php | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php index 81b3f7e08..1947ec465 100644 --- a/data/web/inc/functions.inc.php +++ b/data/web/inc/functions.inc.php @@ -814,6 +814,32 @@ function verify_hash($hash, $password) { $hash = $components[4]; return hash_equals(hash_pbkdf2('sha1', $password, $salt, $rounds), $hash); + case "PBKDF2-SHA512": + // Handle FreeIPA-style hash: {PBKDF2-SHA512}10000$$ + $components = explode('$', $hash); + if (count($components) !== 3) return false; + + // 1st part: iteration count (integer) + $iterations = intval($components[0]); + if ($iterations <= 0) return false; + + // 2nd part: salt (base64-encoded) + $salt = $components[1]; + // 3rd part: hash (base64-encoded) + $stored_hash_b64 = $components[2]; + + // Decode salt and hash from base64 + $salt_bin = base64_decode($salt, true); + $hash_bin = base64_decode($stored_hash_b64, true); + if ($salt_bin === false || $hash_bin === false) return false; + // Get length of hash in bytes + $hash_len = strlen($hash_bin); + if ($hash_len === 0) return false; + + // Calculate PBKDF2-SHA512 hash for provided password + $test_hash = hash_pbkdf2('sha512', $password, $salt_bin, $iterations, $hash_len, true); + return hash_equals($hash_bin, $test_hash); + case "PLAIN-MD4": return hash_equals(hash('md4', $password), $hash);