Compare commits

..

7 Commits

Author SHA1 Message Date
DerLinkman
816b5cdb60 declare better sieve script paths per user (for after and before) 2026-03-04 15:19:44 +01:00
DerLinkman
fb7bbc3fd8 dovecot: fix smaller config changes 2026-03-04 15:19:44 +01:00
DerLinkman
8e93a48ac0 dovecot: rechanged id type from uuid to string 2026-03-04 15:19:43 +01:00
DerLinkman
05fbd549f8 dovecot: change dict declarations for before scripts 2026-03-04 15:19:43 +01:00
DerLinkman
58a26dc966 dovecot: changes to config aligning to 2.4 2026-03-04 15:19:43 +01:00
DerLinkman
9d54fbcc3e dovecot: migrated config to 2.4 + config splitting 2026-03-04 15:19:42 +01:00
DerLinkman
8063b671cb indev: dovecot 2.4 config migration 2026-03-04 15:19:14 +01:00
42 changed files with 765 additions and 786 deletions

View File

@@ -19,7 +19,7 @@ jobs:
uses: docker/setup-qemu-action@v4
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v4
uses: docker/setup-buildx-action@v3
- name: Login to GHCR
if: github.event_name != 'pull_request'
@@ -30,7 +30,7 @@ jobs:
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push
uses: docker/build-push-action@v7
uses: docker/build-push-action@v6
with:
context: .
platforms: linux/amd64,linux/arm64

View File

@@ -64,7 +64,7 @@ adapt_new_options() {
sed -i --follow-symlinks '$a\' mailcow.conf
for option in ${CONFIG_ARRAY[@]}; do
if grep -q "^#\?${option}=" mailcow.conf; then
if grep -q "${option}" mailcow.conf; then
continue
fi
@@ -302,7 +302,7 @@ adapt_new_options() {
;;
ACME_DNS_PROVIDER)
echo '# DNS provider for DNS-01 challenge (e.g. dns_cf, dns_azure, dns_gd, etc.)' >> mailcow.conf
echo '# See the dns-01 provider documentation for more information.' >> mailcow.conf
echo '# See the dns-101 provider documentation for more information.' >> mailcow.conf
echo 'ACME_DNS_PROVIDER=dns_xxx' >> mailcow.conf
;;
ACME_ACCOUNT_EMAIL)

View File

@@ -7,7 +7,7 @@ else
__dns_loader_standalone=0
fi
CONFIG_PATH="${ACME_DNS_CONFIG_FILE:-/etc/acme/dns-01.conf}"
CONFIG_PATH="${ACME_DNS_CONFIG_FILE:-/etc/acme/dns-101.conf}"
if [[ ! -f "${CONFIG_PATH}" ]]; then
if [[ $__dns_loader_standalone -eq 1 ]]; then

View File

@@ -12,7 +12,7 @@ CERT_DOMAINS=(${DOMAINS[@]})
CERT_DOMAIN=${CERT_DOMAINS[0]}
ACME_BASE=/var/lib/acme
# Load optional DNS provider secrets from /etc/acme/dns-01.conf
# Load optional DNS provider secrets from /etc/acme/dns-101.conf
if [[ -f /srv/load-dns-config.sh ]]; then
source /srv/load-dns-config.sh
if declare -F log_f >/dev/null; then

View File

@@ -1,4 +1,4 @@
FROM alpine:3.21
FROM alpine:3.22
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"

View File

@@ -44,90 +44,109 @@ if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
else
QUOTA_TABLE=quota2replica
fi
cat <<EOF > /etc/dovecot/conf.d/12-mysql.conf
# Autogenerated by mailcow - DO NOT TOUCH!
mysql /var/run/mysqld/mysqld.sock {
dbname=${DBNAME}
user=${DBUSER}
password=${DBPASS}
ssl = no
}
EOF
cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-quota.conf
# Autogenerated by mailcow
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
map {
pattern = priv/quota/storage
table = ${QUOTA_TABLE}
dict_map priv/quota/storage {
sql_table = ${QUOTA_TABLE}
username_field = username
value_field = bytes
value_field bytes {
}
}
map {
pattern = priv/quota/messages
table = ${QUOTA_TABLE}
dict_map priv/quota/messages {
sql_table = ${QUOTA_TABLE}
username_field = username
value_field = messages
value_field messages {
}
}
EOF
# Create dict used for sieve pre and postfilters
cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf
# Autogenerated by mailcow
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
map {
pattern = priv/sieve/name/\$script_name
table = sieve_before
dict_map priv/sieve/name/\$script_name {
sql_table = sieve_before
username_field = username
value_field = id
fields {
script_name = \$script_name
value_field id {
}
# The script name field in the table to query
key_field script_name {
value = \$script_name
}
}
map {
pattern = priv/sieve/data/\$id
table = sieve_before
dict_map priv/sieve/data/\$id {
sql_table = sieve_before
username_field = username
value_field = script_data
fields {
id = \$id
value_field script_data {
}
key_field id {
value = \$id
}
}
EOF
cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf
# Autogenerated by mailcow
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
map {
pattern = priv/sieve/name/\$script_name
table = sieve_after
dict_map priv/sieve/name/\$script_name {
sql_table = sieve_after
username_field = username
value_field = id
fields {
script_name = \$script_name
value_field id {
}
key_field script_name {
value = \$script_name
}
}
map {
pattern = priv/sieve/data/\$id
table = sieve_after
dict_map priv/sieve/data/\$id {
sql_table = sieve_after
username_field = username
value_field = script_data
fields {
id = \$id
value_field script_data {
}
key_field id {
value = \$id
}
}
EOF
echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone
if [[ "${ACL_ANYONE}" == "allow" ]]; then
echo -n "yes" > /etc/dovecot/acl_anyone
else
echo -n "no" > /etc/dovecot/acl_anyone
fi
if [[ "${SKIP_FTS}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo -e "\e[33mDetecting SKIP_FTS=y... not enabling Flatcurve (FTS) then...\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication lazy_expunge' > /etc/dovecot/mail_plugins
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify listescape replication mail_log' > /etc/dovecot/mail_plugins_imap
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
echo -n 'quota quota_clone acl mail_crypt mail_crypt_acl mail_log mail_compress notify lazy_expunge' > /etc/dovecot/mail_plugins
echo -n 'quota quota_clone imap_quota imap_acl acl imap_sieve mail_crypt mail_crypt_acl mail_compress notify mail_log' > /etc/dovecot/mail_plugins_imap
echo -n 'quota quota_clone sieve acl mail_crypt mail_crypt_acl mail_compress notify' > /etc/dovecot/mail_plugins_lmtp
else
echo -e "\e[32mDetecting SKIP_FTS=n... enabling Flatcurve (FTS)\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication lazy_expunge' > /etc/dovecot/mail_plugins
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins_imap
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_flatcurve notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
echo -n 'quota quota_clone acl mail_crypt mail_crypt_acl mail_log mail_compress notify fts fts_flatcurve lazy_expunge' > /etc/dovecot/mail_plugins
echo -n 'quota quota_clone imap_quota imap_acl acl imap_sieve mail_crypt mail_crypt_acl mail_compress notify mail_log fts fts_flatcurve' > /etc/dovecot/mail_plugins_imap
echo -n 'quota quota_clone sieve acl mail_crypt mail_crypt_acl mail_compress fts fts_flatcurve notify' > /etc/dovecot/mail_plugins_lmtp
fi
chmod 644 /etc/dovecot/mail_plugins /etc/dovecot/mail_plugins_imap /etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl
cat <<EOF > /etc/dovecot/sql/dovecot-dict-sql-userdb.conf
# Autogenerated by mailcow
driver = mysql
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
user_query = SELECT CONCAT(JSON_UNQUOTE(JSON_VALUE(attributes, '$.mailbox_format')), mailbox_path_prefix, '%d/%n/${MAILDIR_SUB}:VOLATILEDIR=/var/volatile/%u:INDEX=/var/vmail_index/%u') AS mail, '%s' AS protocol, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND (active = '1' OR active = '2')
query = SELECT CONCAT(JSON_UNQUOTE(JSON_VALUE(attributes, '$.mailbox_format')), mailbox_path_prefix, '%{user | domain }}/%{user | username }/Maildir:VOLATILEDIR=/var/volatile/%{user}:INDEX=/var/vmail_index/%{user}') AS mail, '%{protocol}' AS protocol, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%{user}' AND (active = '1' OR active = '2')
iterate_query = SELECT username FROM mailbox WHERE active = '1' OR active = '2';
EOF
@@ -158,8 +177,8 @@ for cert_dir in /etc/ssl/mail/*/ ; do
domains=($(cat ${cert_dir}domains))
for domain in ${domains[@]}; do
echo 'local_name '${domain}' {' >> /etc/dovecot/sni.conf;
echo ' ssl_cert = <'${cert_dir}'cert.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_key = <'${cert_dir}'key.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_server_cert_file = '${cert_dir}'cert.pem' >> /etc/dovecot/sni.conf;
echo ' ssl_server_key_file = '${cert_dir}'key.pem' >> /etc/dovecot/sni.conf;
echo '}' >> /etc/dovecot/sni.conf;
done
done
@@ -183,11 +202,13 @@ else
fi
cat <<EOF > /etc/dovecot/shared_namespace.conf
# Autogenerated by mailcow
namespace {
namespace shared {
type = shared
separator = /
prefix = Shared/%%u/
location = maildir:%%h${MAILDIR_SUB_SHARED}:INDEX=~${MAILDIR_SUB_SHARED}/Shared/%%u
prefix = Shared/\$user/
mail_driver = maildir
mail_path = %{owner_home}${MAILDIR_SUB_SHARED}
mail_index_private_path = ~${MAILDIR_SUB_SHARED}/Shared/%{owner_user}
subscriptions = no
list = children
}
@@ -197,7 +218,7 @@ EOF
cat <<EOF > /etc/dovecot/sogo_trusted_ip.conf
# Autogenerated by mailcow
remote ${IPV4_NETWORK}.248 {
disable_plaintext_auth = no
auth_allow_cleartext = yes
}
EOF
@@ -206,9 +227,13 @@ 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
cat <<EOF > /etc/dovecot/sogo-sso.conf
# Autogenerated by mailcow
passdb {
driver = static
args = allow_nets=${IPV4_NETWORK}.248/32 password={plain}${RAND_PASS}
passdb static {
fields {
allow_real_nets=${IPV4_NETWORK}.248/32
}
password={plain}${RAND_PASS}
}
EOF
@@ -236,9 +261,9 @@ fi
if [[ "${SKIP_FTS}" =~ ^([nN][oO]|[nN])+$ ]]; then
echo -e "\e[94mConfiguring FTS Settings...\e[0m"
echo -e "\e[94mSetting FTS Memory Limit (per process) to ${FTS_HEAP} MB\e[0m"
sed -i "s/vsz_limit\s*=\s*[0-9]*\s*MB*/vsz_limit=${FTS_HEAP} MB/" /etc/dovecot/conf.d/fts.conf
sed -i "s/vsz_limit\s*=\s*[0-9]*\s*MB*/vsz_limit=${FTS_HEAP} MB/" /etc/dovecot/conf.d/35-fts.conf
echo -e "\e[94mSetting FTS Process Limit to ${FTS_PROCS}\e[0m"
sed -i "s/process_limit\s*=\s*[0-9]*/process_limit=${FTS_PROCS}/" /etc/dovecot/conf.d/fts.conf
sed -i "s/process_limit\s*=\s*[0-9]*/process_limit=${FTS_PROCS}/" /etc/dovecot/conf.d/35-fts.conf
fi
# 401 is user dovecot
@@ -250,16 +275,16 @@ else
chown 401 /mail_crypt/ecprivkey.pem /mail_crypt/ecpubkey.pem
fi
# Fix OpenSSL 3.X TLS1.0, 1.1 support (https://community.mailcow.email/d/4062-hi-all/20)
if grep -qE 'ssl_min_protocol\s*=\s*(TLSv1|TLSv1\.1)\s*$' /etc/dovecot/dovecot.conf /etc/dovecot/extra.conf; then
sed -i '/\[openssl_init\]/a ssl_conf = ssl_configuration' /etc/ssl/openssl.cnf
# # Fix OpenSSL 3.X TLS1.0, 1.1 support (https://community.mailcow.email/d/4062-hi-all/20)
# if grep -qE 'ssl_min_protocol\s*=\s*(TLSv1|TLSv1\.1)\s*$' /etc/dovecot/dovecot.conf /etc/dovecot/extra.conf; then
# sed -i '/\[openssl_init\]/a ssl_conf = ssl_configuration' /etc/ssl/openssl.cnf
echo "[ssl_configuration]" >> /etc/ssl/openssl.cnf
echo "system_default = tls_system_default" >> /etc/ssl/openssl.cnf
echo "[tls_system_default]" >> /etc/ssl/openssl.cnf
echo "MinProtocol = TLSv1" >> /etc/ssl/openssl.cnf
echo "CipherString = DEFAULT@SECLEVEL=0" >> /etc/ssl/openssl.cnf
fi
# echo "[ssl_configuration]" >> /etc/ssl/openssl.cnf
# echo "system_default = tls_system_default" >> /etc/ssl/openssl.cnf
# echo "[tls_system_default]" >> /etc/ssl/openssl.cnf
# echo "MinProtocol = TLSv1" >> /etc/ssl/openssl.cnf
# echo "CipherString = DEFAULT@SECLEVEL=0" >> /etc/ssl/openssl.cnf
# fi
# Compile sieve scripts
sievec /var/vmail/sieve/global_sieve_before.sieve

View File

@@ -2,7 +2,7 @@ FROM debian:trixie-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive
ARG RSPAMD_VER=rspamd_3.14.3-1~236eb65
ARG RSPAMD_VER=rspamd_3.14.2-82~90302bc
ARG CODENAME=trixie
ENV LC_ALL=C

View File

@@ -3,7 +3,7 @@
# Version: SOGo-5.12.4
#
# Applied security patches:
# -
# - 16ab99e7cf8db2c30b211f0d5e338d7f9e3a9efb: XSS vulnerability in theme parameter
#
# To add new patches, modify SOGO_SECURITY_PATCHES ARG below with space-separated commit hashes
@@ -12,10 +12,10 @@ FROM debian:bookworm
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive
ARG SOGO_VERSION=SOGo-5.12.5
ARG SOPE_VERSION=SOPE-5.12.5
ARG SOGO_VERSION=SOGo-5.12.4
ARG SOPE_VERSION=SOPE-5.12.4
# Security patches to apply (space-separated commit hashes)
ARG SOGO_SECURITY_PATCHES=""
ARG SOGO_SECURITY_PATCHES="16ab99e7cf8db2c30b211f0d5e338d7f9e3a9efb"
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
ARG GOSU_VERSION=1.19
ENV LC_ALL=C

View File

@@ -1,5 +1,5 @@
--- /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:57.987504204 +0200
+++ /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:35.918291298 +0200
--- /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:57.987504204 +0200
+++ /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox 2018-08-17 18:29:35.918291298 +0200
@@ -46,7 +46,7 @@
</md-item-template>
</md-autocomplete>

View File

@@ -130,22 +130,18 @@ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist
# Patch ACLs
#if [[ ${ACL_ANYONE} == 'allow' ]]; then
# #enable any or authenticated targets for ACL
# if patch -R -sfN --dry-run /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then
# patch -R /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff;
# if patch -R -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then
# patch -R /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff;
# fi
#else
# #disable any or authenticated targets for ACL
# if patch -sfN --dry-run /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then
# patch /usr/local/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff;
# if patch -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff > /dev/null; then
# patch /usr/lib/GNUstep/SOGo/Templates/UIxAclEditor.wox < /acl.diff;
# fi
#fi
# Apply custom UI patch (reverse patch to ADD buttons)
if patch -R -sfN --dry-run /usr/local/lib/GNUstep/SOGo/Templates/UIxTopnavToolbar.wox < /navMailcowBtns.diff > /dev/null; then
echo "Applying navMailcowBtns patch (reverse to add buttons)..."
patch -R /usr/local/lib/GNUstep/SOGo/Templates/UIxTopnavToolbar.wox < /navMailcowBtns.diff;
else
echo "navMailcowBtns patch already applied or cannot be applied"
if patch -R -sfN --dry-run /usr/lib/GNUstep/SOGo/Templates/UIxTopnavToolbar.wox < /navMailcowBtns.diff > /dev/null; then
patch -R /usr/lib/GNUstep/SOGo/Templates/UIxTopnavToolbar.wox < /navMailcowBtns.diff;
fi
# Rename custom logo, if any
@@ -153,7 +149,7 @@ fi
# Rsync web content
echo "Syncing web content with named volume"
rsync -a /usr/local/lib/GNUstep/SOGo/. /sogo_web/
rsync -a /usr/lib/GNUstep/SOGo/. /sogo_web/
# Chown backup path
chown -R sogo:sogo /sogo_backup

View File

@@ -1,4 +1,5 @@
function auth_password_verify(request, password)
request.domain = request.auth_user:match("@(.+)") or nil
if request.domain == nil then
return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "No such user"
end
@@ -9,10 +10,10 @@ function auth_password_verify(request, password)
https.TIMEOUT = 30
local req = {
username = request.user,
username = request.auth_user,
password = password,
real_rip = request.real_rip,
service = request.service
real_rip = request.remote_ip,
service = request.protocol
}
local req_json = json.encode(req)
local res = {}
@@ -33,7 +34,6 @@ function auth_password_verify(request, password)
-- Returning PASSDB_RESULT_INTERNAL_FAILURE keeps the existing cache entry,
-- even if the TTL has expired. Useful to avoid cache eviction during backend issues.
if c ~= 200 and c ~= 401 then
dovecot.i_info("HTTP request failed with " .. c .. " for user " .. request.user)
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Upstream error"
end
@@ -46,7 +46,7 @@ function auth_password_verify(request, password)
end
if response_json.success == true then
return dovecot.auth.PASSDB_RESULT_OK, ""
return dovecot.auth.PASSDB_RESULT_OK, { msg = "" }
end
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate"
@@ -55,3 +55,7 @@ end
function auth_passdb_lookup(req)
return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, ""
end
function auth_passdb_get_cache_key()
return "%{protocol}:%{user | username}\t:%{password}"
end

View File

@@ -0,0 +1,3 @@
# /etc/dovecot/conf.d/05-core.conf
# Core, single-line settings that don't fit elsewhere.
recipient_delimiter = +

View File

@@ -0,0 +1,13 @@
# /etc/dovecot/conf.d/10-logging.conf
# Logging and debug.
#mail_debug = yes
#auth_debug = yes
#log_debug = category=fts-flatcurve
log_path = syslog
log_timestamp = "%Y-%m-%d %H:%M:%S "
login_log_format_elements = "user=<%{user}> method=%{mechanism} rip=%{remote_ip} lip=%{local_ip} mpid=%{mail_pid} %{secured} session=<%{session}>"
# Mail event logging.
mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
mail_log_fields = uid box msgid size
mail_log_cached_only = yes

View File

@@ -0,0 +1,10 @@
# /etc/dovecot/conf.d/10-mail.conf
# Mail storage paths and core mail settings.
mail_home = /var/vmail/%{user | domain }/%{user | username }
mail_driver = maildir
mail_path = ~/Maildir
mail_index_path = /var/vmail_index/%{user}
mail_plugins = </etc/dovecot/mail_plugins
mail_shared_explicit_inbox = yes
mailbox_list_storage_escape_char = "\\"
mail_prefetch_count = 30

View File

@@ -0,0 +1,13 @@
# /etc/dovecot/conf.d/10-ssl.conf
# TLS/SSL settings.
ssl_min_protocol = TLSv1.2
ssl_cipher_list = ALL:!ADH:!LOW:!SSLv2:!SSLv3:!EXP:!aNULL:!eNULL:!3DES:!MD5:!PSK:!DSS:!RC4:!SEED:!IDEA:+HIGH:+MEDIUM
ssl_options = no_ticket
#ssl_dh_parameters_length = 2048
ssl_server {
prefer_ciphers = server
dh_file = /etc/ssl/mail/dhparams.pem
cert_file = /etc/ssl/mail/cert.pem
key_file = /etc/ssl/mail/key.pem
}

View File

@@ -0,0 +1,3 @@
# /etc/dovecot/conf.d/11-sql.conf
# Default SQL driver used by SQL-based dicts/userdb.
sql_driver = mysql

View File

@@ -0,0 +1,8 @@
# Autogenerated by mailcow - DO NOT TOUCH!
mysql /var/run/mysqld/mysqld.sock {
dbname=mailcow
user=mailcow
password=D8O9BIivJc7Pb2VCfpAeLbAzUOZ0
ssl = no
}

View File

@@ -0,0 +1,7 @@
# /etc/dovecot/conf.d/12-storage-attachments.conf
# External attachment storage.
fs mail_ext_attachment {
fs_driver = posix
mail_ext_attachment_path = /var/attachments
mail_ext_attachment_min_size = 128k
}

View File

@@ -0,0 +1,10 @@
# /etc/dovecot/conf.d/15-performance.conf
# Performance and mailbox tuning.
# Enable only when you do not manually touch cur/.
maildir_very_dirty_syncs = yes
# NFS examples | Only modify if using NFS!:
#mm ap_disable = yes
#mail_fsync = always
#mail_nfs_index = yes
#mail_nfs_storage = yes

View File

@@ -0,0 +1,40 @@
# /etc/dovecot/conf.d/20-auth.conf
# Authentication mechanisms, master/user separation, passdb chain, auth cache.
auth_mechanisms = plain login
auth_allow_cleartext = yes
auth_master_user_separator = *
auth_cache_verify_password_with_worker = yes
auth_cache_negative_ttl = 60s
auth_cache_ttl = 300s
auth_cache_size = 10M
auth_verbose_passwords = sha1:6
# 1) Lua password verification (blocking, return mapping).
passdb lua {
driver = lua
lua_file = /etc/dovecot/auth/passwd-verify.lua
lua_settings {
blocking=yes
result_success = return-ok
result_failure = continue
result_internalfail = continue
}
}
# 2) Master password for master user logins.
passdb master {
driver = passwd-file
passwd_file_path = /etc/dovecot/dovecot-master.passwd
master = yes
skip = authenticated
}
# 3) Mandatory return layer: empty Lua (e.g. for forced reset).
passdb empty-lua {
driver = lua
lua_file = /etc/dovecot/auth/passwd-verify.lua
lua_settings {
blocking = yes
}
}

View File

@@ -0,0 +1,11 @@
# /etc/dovecot/conf.d/20-userdb.conf
# User database chain.
userdb passwd {
driver = passwd-file
passwd_file_path = /etc/dovecot/dovecot-master.userdb
}
userdb sql {
!include /etc/dovecot/sql/dovecot-dict-sql-userdb.conf
skip = found
}

View File

@@ -0,0 +1,144 @@
# /etc/dovecot/conf.d/25-services.conf
# All service listeners and workers.
# doveadm remote admin
# Set doveadm_password in extra.conf.
service doveadm {
inet_listener doveadm {
port = 12345
}
vsz_limit = 2048 MB
}
# dict
service dict {
unix_listener dict {
mode = 0660
user = vmail
group = vmail
}
}
# log
service log {
user = dovenull
}
# config socket
service config {
unix_listener config {
user = root
group = vmail
mode = 0660
}
}
# anvil socket
service anvil {
unix_listener anvil {
user = vmail
group = vmail
mode = 0660
}
}
# auth sockets and inet
service auth {
inet_listener auth-inet {
port = 10001
}
unix_listener auth-master {
mode = 0600
user = vmail
}
unix_listener auth-userdb {
mode = 0600
user = vmail
}
vsz_limit = 2G
}
# managesieve login
service managesieve-login {
inet_listener sieve {
port = 4190
}
inet_listener sieve_haproxy {
port = 14190
haproxy = yes
}
service_restart_request_count = 1
process_min_avail = 2
vsz_limit = 1G
}
# imap login
service imap-login {
service_restart_request_count = 1
process_min_avail = 2
process_limit = 10000
vsz_limit = 1G
user = dovenull
inet_listener imap_haproxy {
port = 10143
haproxy = yes
}
inet_listener imaps_haproxy {
port = 10993
ssl = yes
haproxy = yes
}
}
# pop3 login
service pop3-login {
service_restart_request_count = 1
process_min_avail = 1
vsz_limit = 1G
inet_listener pop3_haproxy {
port = 10110
haproxy = yes
}
inet_listener pop3s_haproxy {
port = 10995
ssl = yes
haproxy = yes
}
}
# imap worker
service imap {
executable = imap
user = vmail
vsz_limit = 1G
}
# managesieve worker
service managesieve {
process_limit = 256
}
# lmtp
service lmtp {
inet_listener lmtp-inet {
port = 24
}
user = vmail
}
# quota warning hook
service quota-warning {
executable = script /usr/local/bin/quota_notify.py
user = vmail
unix_listener quota-warning {
user = vmail
}
}
# stats
service stats {
unix_listener stats-writer {
mode = 0660
user = vmail
}
}

View File

@@ -0,0 +1,17 @@
# /etc/dovecot/conf.d/30-protocols.conf
# IMAP protocol specifics.
protocol imap {
mail_plugins = </etc/dovecot/mail_plugins_imap
imap_metadata = yes
}
# LMTP protocol specifics.
protocol lmtp {
mail_plugins = </etc/dovecot/mail_plugins_lmtp
auth_socket_path = /var/run/dovecot/auth-master
}
# ManageSieve protocol specifics.
protocol sieve {
managesieve_logout_format = bytes=%i/%o
}

View File

@@ -0,0 +1,45 @@
# mailcow FTS Flatcurve Settings, change them as you like.
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
language_tokenizer_address_token_maxlen = 100
language_tokenizer_generic_algorithm = simple
language_tokenizer_generic_token_maxlen = 30
# These are not flatcurve settings, but required for Dovecot FTS. See
# Dovecot FTS Configuration link above for further information.
language en {
default = yes
language_filters = lowercase snowball english-possessive stopwords
}
language de {
language_filters = lowercase snowball stopwords
}
language es {
language_filters = lowercase snowball stopwords
}
language_tokenizers = generic email-address
fts_search_timeout = 300s
fts_autoindex = yes
# Tweak this setting if you only want to ensure big and frequent folders are indexed, not all.
fts_autoindex_max_recent_msgs = 20
fts flatcurve {
substring_search = no
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###
service indexer-worker {
# Max amount of simultaniously running indexer jobs.
process_limit=1
# Max amount of RAM used by EACH indexer process.
vsz_limit=128 MB
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###

View File

@@ -0,0 +1,12 @@
# /etc/dovecot/conf.d/40-acl.conf
# ACL and shared mailboxes.
imap_acl_allow_anyone = </etc/dovecot/acl_anyone
acl_sharing_map {
dict file {
path = /var/vmail/shared-mailboxes.db
}
}
acl_driver = vfile
acl_user = %{user}

View File

@@ -0,0 +1,7 @@
# /etc/dovecot/conf.d/40-attributes.conf
# User/mail attributes.
mail_attribute {
dict file {
path = /etc/dovecot/dovecot-attributes
}
}

View File

@@ -0,0 +1,25 @@
# /etc/dovecot/conf.d/50-quota.conf
# Quota configuration and notifications.
quota "User quota" {
driver = count
warning warn-95 {
quota_storage_percentage = 95
execute quota-warning {
args = 95 %{user}
}
}
warning warn-80 {
quota_storage_percentage = 80
execute quota-warning {
args = 80 %{user}
}
}
}
quota_clone {
dict proxy {
name = mysql_quota
}
}

View File

@@ -0,0 +1,97 @@
# /etc/dovecot/conf.d/60-sieve-pipeline.conf
# Complete Sieve pipeline: personal/global scripts, plugins, limits, training.
# Global before/after (file and dict)
sieve_script before {
type = before
driver = file
path = /var/vmail/sieve/global_sieve_before.sieve
}
sieve_script before2 {
type = before
driver = dict
name = active
dict proxy {
name = sieve_before
}
bin_path = /var/vmail/sieve_before_bindir/%{user}
}
sieve_script after {
type = after
driver = file
path = /var/vmail/sieve/global_sieve_after.sieve
}
sieve_script after2 {
type = after
driver = dict
name = active
dict proxy {
name = sieve_after
}
bin_path = /var/vmail/sieve_after_bindir/%{user}
}
# Personal scripts
sieve_script personal {
type = personal
driver = file
path = ~/sieve
active_path = ~/.dovecot.sieve
}
# Plugins and behavior
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_vacation_send_from_recipient = yes
sieve_redirect_envelope_from = recipient
# IMAPSieve training
imapsieve_from Junk {
sieve_script ham {
type = before
cause = copy
path = /usr/lib/dovecot/sieve/report-ham.sieve
}
}
mailbox Junk {
sieve_script spam {
type = before
cause = copy
path = /usr/lib/dovecot/sieve/report-spam.sieve
}
}
# Extprograms and extensions
sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
sieve_plugins {
sieve_extprograms = yes
}
sieve_global_extensions {
vnd.dovecot.pipe = yes
vnd.dovecot.execute = yes
}
# Limits and duplicate handling
sieve_max_script_size = 1M
sieve_max_redirects = 100
sieve_max_actions = 101
sieve_quota_script_count = 0
sieve_quota_storage_size = 0
sieve_vacation_min_period = 5s
sieve_vacation_max_period = 365d
sieve_vacation_default_period = 60s
sieve_duplicate_default_period = 1m
sieve_duplicate_max_period = 7d
sieve_extensions {
vacation-seconds = yes
editheader = yes
}
# pipe sockets in /var/run/dovecot/sieve-pipe
sieve_pipe_socket_dir = sieve-pipe
# execute sockets in /var/run/dovecot/sieve-execute
sieve_execute_socket_dir = sieve-execute

View File

@@ -0,0 +1,6 @@
# /etc/dovecot/conf.d/70-crypto.conf
# Global mail-crypt keys.
crypt_global_private_key global {
crypt_private_key_file = /mail_crypt/ecprivkey.pem
}
crypt_global_public_key_file = /mail_crypt/ecpubkey.pem

View File

@@ -0,0 +1,3 @@
# /etc/dovecot/conf.d/80-compress.conf
# Compression settings.
mail_compress_write_method = lz4

View File

@@ -0,0 +1,18 @@
# /etc/dovecot/conf.d/90-dict.conf
# Dict declarations and SQL bindings.
dict_server {
dict sieve_after {
driver = sql
!include /etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf
}
dict sieve_before {
driver = sql
!include /etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf
}
dict mysql_quota {
driver = sql
!include /etc/dovecot/sql/dovecot-dict-sql-quota.conf
}
}

View File

@@ -0,0 +1,7 @@
# /etc/dovecot/conf.d/90-limits.conf
# Connection and memory limits; doveadm port.
mail_max_userip_connections = 500
imap_max_line_length = 2 M
default_client_limit = 10400
default_vsz_limit = 1024 M
doveadm_port = 12345

View File

@@ -0,0 +1,22 @@
# /etc/dovecot/conf.d/99-includes.conf
# Late includes and site-specific bits.
# Mailbox layout includes (if used)
!include /etc/dovecot/dovecot.folders.conf
# Optional replication
!include_try /etc/dovecot/mail_replica.conf
# Existing includes you already had
!include_try /etc/dovecot/sni.conf
!include_try /etc/dovecot/sogo_trusted_ip.conf
!include_try /etc/dovecot/shared_namespace.conf
!include_try /etc/dovecot/conf.d/fts.conf
# Remote auth override
remote 127.0.0.1 {
auth_allow_cleartext = yes
}
# Outbound submission target
submission_host = postfix:588

View File

@@ -1,37 +0,0 @@
# mailcow FTS Flatcurve Settings, change them as you like.
plugin {
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
# Tweak this setting if you only want to ensure big and frequent folders are indexed, not all.
fts_autoindex_max_recent_msgs = 20
fts = flatcurve
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
fts_tokenizer_email_address = maxlen=100
fts_tokenizer_generic = algorithm=simple maxlen=30
# These are not flatcurve settings, but required for Dovecot FTS. See
# Dovecot FTS Configuration link above for further information.
fts_languages = en es de
fts_tokenizers = generic email-address
# OPTIONAL: Recommended default FTS core configuration
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
fts_index_timeout = 300s
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###
service indexer-worker {
# Max amount of simultaniously running indexer jobs.
process_limit=1
# Max amount of RAM used by EACH indexer process.
vsz_limit=128 MB
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###

View File

@@ -1,311 +1,34 @@
# --------------------------------------------------------------------------
# Please create a file "extra.conf" for persistent overrides to dovecot.conf
# --------------------------------------------------------------------------
# LDAP example:
#passdb {
# args = /etc/dovecot/ldap/passdb.conf
# driver = ldap
#}
# /etc/dovecot/dovecot.conf
# Base file kept minimal. All real config lives under conf.d/.
dovecot_config_version = 2.4.0
dovecot_storage_version = 2.4.0
auth_mechanisms = plain login
#mail_debug = yes
#auth_debug = yes
#log_debug = category=fts-flatcurve # Activate Logging for Flatcurve FTS Searchings
log_path = syslog
disable_plaintext_auth = yes
# Uncomment on NFS share
#mmap_disable = yes
#mail_fsync = always
#mail_nfs_index = yes
#mail_nfs_storage = yes
login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k"
mail_home = /var/vmail/%d/%n
mail_location = maildir:~/
mail_plugins = </etc/dovecot/mail_plugins
mail_attachment_fs = crypt:set_prefix=mail_crypt_global:posix:
mail_attachment_dir = /var/attachments
mail_attachment_min_size = 128k
# Significantly speeds up very large mailboxes, but is only safe to enable if
# you do not manually modify the files in the `cur` directories in
# mailcowdockerized_vmail-vol-1.
# https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-performance/
maildir_very_dirty_syncs = yes
# Dovecot 2.2
#ssl_protocols = !SSLv3
# Dovecot 2.3
ssl_min_protocol = TLSv1.2
ssl_prefer_server_ciphers = yes
ssl_cipher_list = ALL:!ADH:!LOW:!SSLv2:!SSLv3:!EXP:!aNULL:!eNULL:!3DES:!MD5:!PSK:!DSS:!RC4:!SEED:!IDEA:+HIGH:+MEDIUM
# Default in Dovecot 2.3
ssl_options = no_compression no_ticket
# New in Dovecot 2.3
ssl_dh = </etc/ssl/mail/dhparams.pem
# Dovecot 2.2
#ssl_dh_parameters_length = 2048
log_timestamp = "%Y-%m-%d %H:%M:%S "
recipient_delimiter = +
auth_master_user_separator = *
mail_shared_explicit_inbox = yes
mail_prefetch_count = 30
passdb {
driver = lua
args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes cache_key=%s:%u:%w
result_success = return-ok
result_failure = continue
result_internalfail = continue
}
# try a master passwd
passdb {
driver = passwd-file
args = /etc/dovecot/dovecot-master.passwd
master = yes
skip = authenticated
}
# check for regular password - if empty (e.g. force-passwd-reset), previous pass=yes passdbs also fail
# a return of the following passdb is mandatory
passdb {
driver = lua
args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes
}
# Set doveadm_password=your-secret-password in data/conf/dovecot/extra.conf (create if missing)
service doveadm {
inet_listener {
port = 12345
}
vsz_limit=2048 MB
}
!include /etc/dovecot/dovecot.folders.conf
protocols = imap sieve lmtp pop3
service dict {
unix_listener dict {
mode = 0660
user = vmail
group = vmail
}
}
service log {
user = dovenull
}
service config {
unix_listener config {
user = root
group = vmail
mode = 0660
}
}
service auth {
inet_listener auth-inet {
port = 10001
}
unix_listener auth-master {
mode = 0600
user = vmail
}
unix_listener auth-userdb {
mode = 0600
user = vmail
}
vsz_limit = 2G
}
service managesieve-login {
inet_listener sieve {
port = 4190
}
inet_listener sieve_haproxy {
port = 14190
haproxy = yes
}
service_count = 1
process_min_avail = 2
vsz_limit = 1G
}
service imap-login {
service_count = 1
process_min_avail = 2
process_limit = 10000
vsz_limit = 1G
user = dovenull
inet_listener imap_haproxy {
port = 10143
haproxy = yes
}
inet_listener imaps_haproxy {
port = 10993
ssl = yes
haproxy = yes
}
}
service pop3-login {
service_count = 1
process_min_avail = 1
vsz_limit = 1G
inet_listener pop3_haproxy {
port = 10110
haproxy = yes
}
inet_listener pop3s_haproxy {
port = 10995
ssl = yes
haproxy = yes
}
}
service imap {
executable = imap
user = vmail
vsz_limit = 1G
}
service managesieve {
process_limit = 256
}
service lmtp {
inet_listener lmtp-inet {
port = 24
}
user = vmail
}
listen = *,[::]
ssl_cert = </etc/ssl/mail/cert.pem
ssl_key = </etc/ssl/mail/key.pem
userdb {
driver = passwd-file
args = /etc/dovecot/dovecot-master.userdb
}
userdb {
args = /etc/dovecot/sql/dovecot-dict-sql-userdb.conf
driver = sql
skip = found
}
protocol imap {
mail_plugins = </etc/dovecot/mail_plugins_imap
imap_metadata = yes
}
mail_attribute_dict = file:%h/dovecot-attributes
protocol lmtp {
mail_plugins = </etc/dovecot/mail_plugins_lmtp
auth_socket_path = /var/run/dovecot/auth-master
}
protocol sieve {
managesieve_logout_format = bytes=%i/%o
}
plugin {
# Allow "any" or "authenticated" to be used in ACLs
acl_anyone = </etc/dovecot/acl_anyone
acl_shared_dict = file:/var/vmail/shared-mailboxes.db
acl = vfile
acl_user = %u
quota = dict:Userquota::proxy::sqlquota
quota_rule2 = Trash:storage=+100%%
sieve = /var/vmail/sieve/%u.sieve
sieve_plugins = sieve_imapsieve sieve_extprograms
sieve_vacation_send_from_recipient = yes
sieve_redirect_envelope_from = recipient
# From elsewhere to Spam folder
imapsieve_mailbox1_name = Junk
imapsieve_mailbox1_causes = COPY
imapsieve_mailbox1_before = file:/usr/lib/dovecot/sieve/report-spam.sieve
# END
# From Spam folder to elsewhere
imapsieve_mailbox2_name = *
imapsieve_mailbox2_from = Junk
imapsieve_mailbox2_causes = COPY
imapsieve_mailbox2_before = file:/usr/lib/dovecot/sieve/report-ham.sieve
# END
master_user = %u
quota_warning = storage=95%% quota-warning 95 %u
quota_warning2 = storage=80%% quota-warning 80 %u
sieve_pipe_bin_dir = /usr/lib/dovecot/sieve
sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
sieve_extensions = +notify +imapflags +vacation-seconds +editheader
sieve_max_script_size = 1M
sieve_max_redirects = 100
sieve_max_actions = 101
sieve_quota_max_scripts = 0
sieve_quota_max_storage = 0
listescape_char = "\\"
sieve_vacation_min_period = 5s
sieve_vacation_max_period = 0
sieve_vacation_default_period = 60s
sieve_before = /var/vmail/sieve/global_sieve_before.sieve
sieve_before2 = dict:proxy::sieve_before;name=active;bindir=/var/vmail/sieve_before_bindir
sieve_after = dict:proxy::sieve_after;name=active;bindir=/var/vmail/sieve_after_bindir
sieve_after2 = /var/vmail/sieve/global_sieve_after.sieve
sieve_duplicate_default_period = 1m
sieve_duplicate_max_period = 7d
protocols = imap sieve lmtp pop3
# -- Global keys
mail_crypt_global_private_key = </mail_crypt/ecprivkey.pem
mail_crypt_global_public_key = </mail_crypt/ecpubkey.pem
mail_crypt_save_version = 2
!include_try /etc/dovecot/conf.d/05-core.conf
!include_try /etc/dovecot/conf.d/10-logging.conf
!include_try /etc/dovecot/conf.d/10-mail.conf
!include_try /etc/dovecot/conf.d/10-ssl.conf
!include_try /etc/dovecot/conf.d/11-sql.conf
!include_try /etc/dovecot/conf.d/12-mysql.conf
!include_try /etc/dovecot/conf.d/12-storage-attachments.conf
!include_try /etc/dovecot/conf.d/15-performance.conf
!include_try /etc/dovecot/conf.d/20-auth.conf
!include_try /etc/dovecot/conf.d/20-userdb.conf
!include_try /etc/dovecot/conf.d/25-services.conf
!include_try /etc/dovecot/conf.d/30-protocols.conf
!include_try /etc/dovecot/conf.d/35-fts.conf
!include_try /etc/dovecot/conf.d/40-acl.conf
!include_try /etc/dovecot/conf.d/40-attributes.conf
!include_try /etc/dovecot/conf.d/50-quota.conf
!include_try /etc/dovecot/conf.d/60-sieve-pipeline.conf
!include_try /etc/dovecot/conf.d/70-crypto.conf
!include_try /etc/dovecot/conf.d/80-compress.conf
!include_try /etc/dovecot/conf.d/80-mail-logging.conf
!include_try /etc/dovecot/conf.d/90-limits.conf
!include_try /etc/dovecot/conf.d/90-dict.conf
!include_try /etc/dovecot/conf.d/99-includes.conf
# Enable compression while saving, lz4 Dovecot v2.3.17+
zlib_save = lz4
mail_log_events = delete undelete expunge copy mailbox_delete mailbox_rename
mail_log_fields = uid box msgid size
mail_log_cached_only = yes
# Try set mail_replica
!include_try /etc/dovecot/mail_replica.conf
}
service quota-warning {
executable = script /usr/local/bin/quota_notify.py
# use some unprivileged user for executing the quota warnings
user = vmail
unix_listener quota-warning {
user = vmail
}
}
dict {
sqlquota = mysql:/etc/dovecot/sql/dovecot-dict-sql-quota.conf
sieve_after = mysql:/etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf
sieve_before = mysql:/etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf
}
remote 127.0.0.1 {
disable_plaintext_auth = no
}
submission_host = postfix:588
mail_max_userip_connections = 500
service stats {
unix_listener stats-writer {
mode = 0660
user = vmail
}
}
imap_max_line_length = 2 M
auth_cache_verify_password_with_worker = yes
auth_cache_negative_ttl = 60s
auth_cache_ttl = 300s
auth_cache_size = 10M
auth_verbose_passwords = sha1:6
service replicator {
process_min_avail = 1
}
service aggregator {
fifo_listener replication-notify-fifo {
user = vmail
}
unix_listener replication-notify {
user = vmail
}
}
service replicator {
unix_listener replicator-doveadm {
mode = 0666
}
}
replication_max_conns = 10
doveadm_port = 12345
replication_dsync_parameters = -d -l 30 -U -n INBOX
# <Includes>
!include_try /etc/dovecot/sni.conf
!include_try /etc/dovecot/sogo_trusted_ip.conf
!include_try /etc/dovecot/extra.conf
!include_try /etc/dovecot/shared_namespace.conf
!include_try /etc/dovecot/conf.d/fts.conf
# </Includes>
default_client_limit = 10400
default_vsz_limit = 1024 M
# Last: local overrides
!include_try /etc/dovecot/extra.conf

View File

@@ -1,10 +1,14 @@
namespace inbox {
inbox = yes
location =
separator = /
mailbox storage/* {
quota_storage_extra = 100M
}
mailbox "Trash" {
auto = subscribe
special_use = \Trash
quota_storage_percentage = 100
fts_autoindex = no
}
mailbox "Deleted Messages" {
special_use = \Trash
@@ -195,6 +199,7 @@ namespace inbox {
mailbox "Junk" {
auto = subscribe
special_use = \Junk
fts_autoindex = no
}
mailbox "Junk-E-Mail" {
special_use = \Junk

View File

@@ -261,19 +261,19 @@ location ~* /sogo$ {
}
location /SOGo.woa/WebServerResources/ {
alias /usr/local/lib/GNUstep/SOGo/WebServerResources/;
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /.woa/WebServerResources/ {
alias /usr/local/lib/GNUstep/SOGo/WebServerResources/;
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /SOGo/WebServerResources/ {
alias /usr/local/lib/GNUstep/SOGo/WebServerResources/;
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
alias /usr/local/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
}
{% endif %}

View File

@@ -9,10 +9,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$_data_log = $_data;
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
// Track mailboxes affected by alias operations for incremental SOGo updates
$update_sogo_mailboxes = array();
switch ($_action) {
case 'add':
switch ($_type) {
@@ -890,17 +886,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('alias_added', $address, $id)
);
// Track affected mailboxes for SOGo update
if (!empty($goto)) {
$gotos = array_map('trim', explode(',', $goto));
foreach ($gotos as $g) {
if (filter_var($g, FILTER_VALIDATE_EMAIL) &&
!in_array($g, array('null@localhost', 'spam@localhost', 'ham@localhost'))) {
$update_sogo_mailboxes[] = $g;
}
}
}
}
break;
case 'alias_domain':
@@ -1383,8 +1368,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
), $_extra);
}
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $username;
try {
update_sogo_static_view($username);
} catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => $e->getMessage()
);
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
@@ -1615,9 +1607,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('resource_added', htmlspecialchars($name))
);
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $name;
break;
case 'domain_templates':
if ($_SESSION['mailcow_cc_role'] != "admin") {
@@ -2736,28 +2725,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('alias_modified', htmlspecialchars($address))
);
// Track affected mailboxes for SOGo update (both old and new goto addresses)
// Old goto: to remove alias from their view
if (!empty($is_now['goto'])) {
$old_gotos = array_map('trim', explode(',', $is_now['goto']));
foreach ($old_gotos as $g) {
if (filter_var($g, FILTER_VALIDATE_EMAIL) &&
!in_array($g, array('null@localhost', 'spam@localhost', 'ham@localhost'))) {
$update_sogo_mailboxes[] = $g;
}
}
}
// New goto: to add alias to their view
if (!empty($goto)) {
$new_gotos = array_map('trim', explode(',', $goto));
foreach ($new_gotos as $g) {
if (filter_var($g, FILTER_VALIDATE_EMAIL) &&
!in_array($g, array('null@localhost', 'spam@localhost', 'ham@localhost'))) {
$update_sogo_mailboxes[] = $g;
}
}
}
}
break;
case 'domain':
@@ -3472,8 +3439,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'msg' => array('mailbox_modified', $username)
);
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $username;
try {
update_sogo_static_view($username);
} catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => $e->getMessage()
);
}
}
return true;
break;
@@ -4102,9 +4076,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('resource_modified', htmlspecialchars($name))
);
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $name;
}
break;
case 'domain_wide_footer':
@@ -5809,18 +5780,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
continue;
}
// Track affected mailboxes for SOGo update (capture before deletion)
if (!empty($alias_data['goto'])) {
$gotos = array_map('trim', explode(',', $alias_data['goto']));
foreach ($gotos as $g) {
if (filter_var($g, FILTER_VALIDATE_EMAIL) &&
!in_array($g, array('null@localhost', 'spam@localhost', 'ham@localhost'))) {
$update_sogo_mailboxes[] = $g;
}
}
}
$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `id` = :id");
$stmt->execute(array(
':id' => $alias_data['id']
@@ -6079,14 +6038,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
continue;
}
try {
update_sogo_static_view($username);
}catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => $e->getMessage()
);
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('mailbox_removed', htmlspecialchars($username))
);
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $username;
}
return true;
break;
@@ -6188,9 +6153,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('resource_removed', htmlspecialchars($name))
);
// Track affected mailboxes for SOGo update
$update_sogo_mailboxes[] = $name;
}
break;
case 'tags_domain':
@@ -6297,21 +6259,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
}
break;
}
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource', 'mailbox')) && getenv('SKIP_SOGO') != "y") {
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") {
try {
if (($_type == 'alias' || $_type == 'resource' || $_type == 'mailbox') && !empty($update_sogo_mailboxes)) {
// INCREMENTAL UPDATE: Update only affected mailboxes/resources
$update_sogo_mailboxes = array_unique($update_sogo_mailboxes);
foreach ($update_sogo_mailboxes as $mailbox) {
update_sogo_static_view($mailbox);
}
}
else {
// FULL REBUILD: For domain and alias_domain operations or if no tracked mailboxes
// Domain operations affect all mailboxes
// Alias_domain operations affect entire target domain
update_sogo_static_view();
}
update_sogo_static_view();
}catch (PDOException $e) {
$_SESSION['return'][] = array(
'type' => 'success',

View File

@@ -26,8 +26,7 @@
"syncjobs": "Sync jobs",
"tls_policy": "Versleutelingsbeleid",
"unlimited_quota": "Onbeperkte quota voor mailboxen",
"domain_desc": "Wijzig domeinbeschrijving",
"pw_reset": "Toegang om mailcow gebruikers wachtwoord te resetten"
"domain_desc": "Wijzig domeinbeschrijving"
},
"add": {
"activate_filter_warn": "Alle andere filters worden gedeactiveerd zolang deze geactiveerd is.",
@@ -105,11 +104,7 @@
"validate": "Verifieer",
"validation_success": "Succesvol geverifieerd",
"tags": "Tags",
"bcc_dest_format": "BCC-bestemming moet één geldig e-mailadres zijn.<br>Als u een kopie naar meerdere adressen wilt sturen, maak dan een alias aan en gebruik die hier.",
"dry": "Synchronisatie simuleren",
"internal": "Intern",
"internal_info": "Interne aliassen zijn alleen toegankelijk vanuit het eigen (alias)domein.",
"sender_allowed": "Toestaan om te verzenden als deze alias"
"bcc_dest_format": "BCC-bestemming moet één geldig e-mailadres zijn.<br>Als u een kopie naar meerdere adressen wilt sturen, maak dan een alias aan en gebruik die hier."
},
"admin": {
"access": "Toegang",
@@ -143,7 +138,7 @@
"arrival_time": "Aankomsttijd",
"authed_user": "Geauthenticeerde gebruiker",
"ays": "Weet je zeker dat je deze actie wilt uitvoeren?",
"ban_list_info": "Bekijk de lijst met verbannen IP-adressen hieronder: <b>netwerk (resterende tijd) - [acties]</b>.<br />IP-adressen die in de wachtrij staan om te worden gedeblokkeerd, worden binnen enkele seconden uit de actieve banlijst verwijderd.<br />\n<br />Rode labels geven actieve permanente blokkades door denylisting aan.",
"ban_list_info": "Bekijk de lijst met verbannen IP-adressen hieronder: <b>netwerk (resterende tijd) - [acties]</b>.<br />Rode labels geven een permanente verbanning aan.<br />Het kan enkele seconden duren voordat wijzigingen hieronder zichtbaar zijn.",
"change_logo": "Logo",
"configuration": "Instellingen",
"convert_html_to_text": "Converteer HTML naar plaintext",
@@ -176,7 +171,7 @@
"excludes": "Exclusief",
"f2b_ban_time": "Verbanningstijd (s)",
"f2b_ban_time_increment": "Verbanningstijd wordt verhoogd met elk verbanning",
"f2b_blacklist": "Netwerken/hosts op de denylist",
"f2b_blacklist": "Netwerken/hosts op de blacklist",
"f2b_filter": "Regex-filters",
"f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. <b>Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.</b>",
"f2b_max_attempts": "Maximaal aantal pogingen",
@@ -211,7 +206,7 @@
"link": "Link",
"loading": "Even geduld aub...",
"logo_info": "De afbeelding zal worden geschaald naar een hoogte van 40px voor de navigatiebar, en naar een breedte van 250px voor de startpagina.",
"lookup_mx": "Bestemming is een reguliere expressie die wordt gematcht met de MX-naam (<code>.*\\.google\\.com</code> om alle e-mail die gericht is aan een MX die eindigt op google.com via deze hop te routeren)",
"lookup_mx": "Match bestemming aan MX (gebruik .outlook.com om alle mail gericht aan MX *.outlook.com over deze hop te laten gaan)",
"main_name": "\"Mailcow\"",
"merged_vars_hint": "Grijze rijen zijn samengevoegd van <code>vars.(local.)inc.php</code> en kunnen niet worden gewijzigd.",
"message": "Bericht",
@@ -280,7 +275,7 @@
"rspamd_com_settings": "Een beschrijving voor deze instelling zal automatisch worden gegenereerd, gebruik de onderstaande presets als voorbeeld. Raadpleeg de <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Rspamd-documentatie</a> voor meer informatie.",
"rspamd_global_filters": "Globale filters",
"rspamd_global_filters_agree": "Ik ben me ervan bewust dat aanpassingen desastreuze gevolgen kunnen hebben",
"rspamd_global_filters_info": "Globale filtermaps bevatten verschillende soorten globale deny- en allowlists.",
"rspamd_global_filters_info": "Ieder globaal filter heeft zijn eigen functie, zie de namen.",
"rspamd_global_filters_regex": "De velden kunnen uitsluitend regular expressions bevatten met het formaat \"/pattern/options\", bijvoorbeeld <code>/.+@domain\\.tld/i</code>.<br>Ondanks dat alle invoer wordt gecontroleerd op fouten, is het toch mogelijk dat Rspamd onbruikbaar wordt als deze de invoer niet kan lezen.<br>Als je problemen ervaart, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">herstart Rspamd</a> dan om de filters opnieuw te laten lezen.<br>Elementen op de blacklist zijn uitgesloten van de quarantaine.",
"rspamd_settings_map": "Rspamd",
"sal_level": "Moo-level",
@@ -342,71 +337,7 @@
"admins_ldap": "LDAP administrators",
"api_read_only": "Alleen-lezen toegang",
"api_read_write": "Lees en schrijf toegang",
"login_time": "Login tijd",
"admin_quicklink": "Snelle link naar de admin-loginpagina verbergen",
"allowed_methods": "Toegestane toegangsmethoden",
"app_hide": "Verberg voor login",
"copy_to_clipboard": "Tekst gekopieerd naar het klembord!",
"login_page": "Loginpagina",
"domainadmin_quicklink": "Snelle link naar de domeinbeheerder-loginpagina verbergen",
"f2b_manage_external": "Fail2Ban extern beheren",
"f2b_manage_external_info": "Fail2Ban zal nog steeds de banlijst bijhouden, maar zal niet actief regels instellen om verkeer te blokkeren. Gebruik de onderstaande gegenereerde banlijst om het verkeer extern te blokkeren.",
"filter": "Filter",
"force_sso_text": "Als een externe OIDC-provider is geconfigureerd, verbergt deze optie de standaard Mailcow-loginformulieren en wordt alleen de Single SignOn-knop weergegeven.",
"force_sso": "Mailcow-login uitschakelen en alleen Single SignOn tonen",
"iam": "Identiteitsprovider",
"iam_attribute_field": "Attribuutveld",
"iam_authorize_url": "Autorisatie endpoint",
"iam_auth_flow": "Autorisatie flow",
"iam_auth_flow_info": "Naast de Authorization Code Flow (Standard Flow in Keycloak), die wordt gebruikt voor Single SignOn-login, ondersteunt Mailcow ook een authenticatiestroom met directe inloggegevens. De Mailpassword Flow probeert de gebruikersgegevens te valideren door gebruik te maken van de Keycloak Admin REST API. Mailcow haalt het gehashte wachtwoord op uit het attribuut <code>mailcow_password</code>, dat in Keycloak is gekoppeld.",
"iam_client_id": "Client ID",
"iam_client_secret": "Client Secret",
"iam_client_scopes": "Clientscopes",
"iam_default_template": "Standaardsjabloon",
"iam_default_template_description": "Als er geen sjabloon aan een gebruiker is toegewezen, wordt het standaardsjabloon gebruikt voor het aanmaken van de mailbox, maar niet voor het bijwerken van de mailbox.",
"iam_description": "Configureer een externe provider voor authenticatie. De mailboxen van gebruikers worden automatisch aangemaakt bij hun eerste login, mits er een attribuutkoppeling is ingesteld.",
"iam_extra_permission": "Om de volgende instellingen te laten werken, heeft de mailcow-client in Keycloak een <code>service account</code> nodig en de toestemming <code>view-users</code>.",
"iam_host": "Hostname",
"iam_host_info": "Voer één of meerdere LDAP-hosts in, gescheiden door kommas.",
"iam_import_users": "Importeer gebruikers",
"iam_login_provisioning": "Gebruikers automatisch aanmaken bij het inloggen",
"iam_mapping": "Attribuutkoppeling",
"iam_bindpass": "Bind-wachtwoord",
"iam_periodic_full_sync": "Periodieke volledige synchronisatie",
"iam_port": "Poort",
"iam_realm": "Realm",
"iam_redirect_url": "Redirect-URL",
"iam_rest_flow": "Mailwachtwoord-flow",
"iam_server_url": "Server Url",
"iam_sso": "Single SignOn",
"iam_sync_interval": "Synchronisatie-/importinterval (min)",
"iam_test_connection": "Verbinding testen",
"iam_token_url": "Token endpoint",
"iam_userinfo_url": "Gebruikersinfo endpoint",
"iam_username_field": "Gebruikersnaam veld",
"iam_use_ssl": "Gebruik SSL",
"iam_use_ssl_info": "Als SSL wordt ingeschakeld en de poort is ingesteld op 389, wordt deze automatisch aangepast naar 636.",
"iam_use_tls": "Gebruik StartTLS",
"iam_use_tls_info": "Als TLS wordt ingeschakeld, moet je de standaardpoort voor je LDAP-server (389) gebruiken. SSL-poorten kunnen niet worden gebruikt.",
"iam_version": "Versie",
"ignore_ssl_error": "Negeer SSL foutmeldingen",
"ip_check_opt_in": "Kies ervoor om de externe diensten <strong>ipv4.mailcow.email</strong> en <strong>ipv6.mailcow.email</strong> te gebruiken om externe IP-adressen te bepalen.",
"needs_restart": "vereist een herstart",
"no": "&#10005;",
"password_reset_info": "Als er geen herstel-e-mailadres is opgegeven, kan deze functie niet worden gebruikt.",
"password_reset_settings": "Instellingen voor wachtwoordherstel",
"password_reset_tmpl_html": "HTML sjabloon",
"password_reset_tmpl_text": "Tekst sjabloon",
"password_settings": "Wachtwoordinstellingen",
"quicklink_text": "Toon of verberg snelle links naar andere inlogpaginas onder het inlogformulier",
"queue_unban": "deblokkeren",
"reset_password_vars": "<code>{{link}}</code> De gegenereerde link om het wachtwoord te resetten<br><code>{{username}}</code> De mailboxnaam van de gebruiker die het wachtwoordherstel heeft aangevraagd<br><code>{{username2}}</code> De naam van de herstelmailbox<br><code>{{date}}</code> De datum waarop het verzoek tot wachtwoordherstel is gedaan<br><code>{{token_lifetime}}</code> De geldigheidsduur van de token in minuten<br><code>{{hostname}}</code> De mailcow-hostnaam",
"restore_template": "Leeg laten om het standaardsjabloon te herstellen.",
"task": "Taak",
"transport_test_rcpt_info": "&#8226; Gebruik null@hosted.mailcow.de om relaying naar een externe bestemming te testen.",
"user_link": "Gebruikerslink",
"user_quicklink": "Snelle link naar de gebruikers-loginpagina verbergen",
"yes": "&#10003;"
"login_time": "Login tijd"
},
"danger": {
"access_denied": "Toegang geweigerd of ongeldige gegevens",
@@ -532,27 +463,7 @@
"demo_mode_enabled": "Demo modus is ingeschakeld",
"template_exists": "Sjabloon %s bestaat al",
"template_id_invalid": "Sjabloon ID %s ongeldig",
"template_name_invalid": "Sjabloon naam ongeldig",
"tfa_removal_blocked": "Twee-factor-authenticatie kan niet worden verwijderd omdat dit vereist is voor uw account.",
"authsource_in_use": "De identiteitsprovider kan niet worden gewijzigd of verwijderd omdat deze momenteel door één of meerdere gebruikers wordt gebruikt.",
"cors_invalid_origin": "Ongeldige Allow-Origin opgegeven",
"extended_sender_acl_denied": "Ontbrekende ACL om externe afzenderadressen in te stellen",
"generic_server_error": "Er is een onverwachte serverfout opgetreden. Neem contact op met uw beheerder.",
"iam_test_connection": "Verbinding mislukt",
"img_dimensions_exceeded": "De afbeelding overschrijdt de maximale afbeeldingsgrootte",
"img_size_exceeded": "De afbeelding overschrijdt de maximale afbeeldingsgrootte",
"invalid_reset_token": "Ongeldige reset-token",
"max_age_invalid": "Maximale leeftijd %s is ongeldig",
"mode_invalid": "Mode %s is ongeldig",
"mx_invalid": "MX-record %s is ongeldig",
"password_reset_invalid_user": "Mailbox niet gevonden of er is geen herstel-e-mailadres ingesteld",
"password_reset_na": "Wachtwoordherstel is momenteel niet beschikbaar. Neem contact op met uw beheerder.",
"recovery_email_failed": "Kon geen herstel-e-mail verzenden. Neem contact op met uw beheerder.",
"required_data_missing": "Vereiste gegevens %s ontbreken",
"reset_token_limit_exceeded": "De limiet voor reset-tokens is overschreden. Probeer het later opnieuw.",
"to_invalid": "Ontvanger mag niet leeg zijn",
"webauthn_username_failed": "De geselecteerde authenticator behoort tot een ander account",
"version_invalid": "Versie %s is ongeldig"
"template_name_invalid": "Sjabloon naam ongeldig"
},
"debug": {
"chart_this_server": "Grafiek (deze server)",
@@ -609,7 +520,7 @@
"alias": "Wijzig alias",
"allow_from_smtp": "Sta enkel de volgende IP-adressen toe voor <b>SMTP</b>",
"allow_from_smtp_info": "Laat leeg om alle afzenders toe te staan.<br>IPv4/IPv6-adressen en netwerken.",
"allowed_protocols": "Toegestane protocollen voor directe gebruikerstoegang (heeft geen invloed op protocollen voor app-wachtwoorden).",
"allowed_protocols": "Toegestane protocollen",
"app_name": "Naam van app",
"app_passwd": "Appwachtwoord",
"automap": "Probeer mappen automatisch te koppelen (\"Verzonden items\", \"Verzonden\" => \"Verzonden\" etc.)",
@@ -694,7 +605,7 @@
"sogo_visible_info": "Wanneer verborgen zal een alias niet worden weergegeven als een selecteerbaar verzendadres. Deze optie beïnvloedt uitsluitend objecten die kunnen worden weergegeven in SOGo (gedeelde of niet-gedeelde aliasadressen die naar minstens één mailbox verwijzen).",
"spam_alias": "Maak een nieuw tijdelijk alias aan, of pas deze aan",
"spam_filter": "Spamfilter",
"spam_policy": "Voeg items toe of verwijder items van de deny- en allowlists",
"spam_policy": "Voeg items toe of verwijder items van de white- of blacklist",
"spam_score": "Stel een aangepaste spamscore in",
"subfolder2": "Synchroniseer in submap op bestemming<br><small>(leeg = gebruik geen submappen)</small>",
"syncjob": "Wijzig sync job",
@@ -713,47 +624,7 @@
"acl": "ACL (Toestemming)",
"domain_footer": "Domeinbreede footer",
"domain_footer_html": "HTML footer",
"mailbox_relayhost_info": "Wordt alleen toegepast op de mailbox en directe aliassen, maar heft een domein relayhost op.",
"custom_attributes": "Aangepaste attributen",
"domain_footer_info_vars": {
"auth_user": "{= auth_user =} - Geauthenticeerde gebruikersnaam opgegeven door een MTA",
"from_user": "{= from_user =} - Afzendergedeelte van het e-mailadres, bijvoorbeeld bij \"moo@mailcow.tld\" wordt \"moo\" teruggegeven",
"from_name": "{= from_name =} - Naam van de afzender, bijvoorbeeld bij \"Mailcow <moo@mailcow.tld>\" wordt \"Mailcow\" teruggegeven",
"from_addr": "{= from_addr =} - Adres van de afzender",
"from_domain": "{= from_domain =} - Domein van de afzender",
"custom": "{= foo =} - Als de mailbox het aangepaste attribuut \"foo\" met de waarde \"bar\" heeft, wordt \"bar\" teruggegeven."
},
"domain_footer_plain": "PLAIN-voettekst",
"domain_footer_skip_replies": "Voettekst negeren bij antwoord-e-mails",
"footer_exclude": "Uitsluiten van voettekst",
"internal": "Intern",
"internal_info": "Interne aliassen zijn alleen toegankelijk vanuit het eigen (alias)domein.",
"sender_allowed": "Toestaan om als deze alias te verzenden",
"sender_allowed_info": "Als dit is uitgeschakeld, kan deze alias alleen e-mail ontvangen. Gebruik de afzender-ACL om dit te overschrijven en specifieke mailboxen toestemming te geven om te verzenden.",
"lookup_mx": "Bestemming is een reguliere expressie die wordt gematcht met de MX-naam (<code>.*.google.com</code> om alle e-mail die gericht is aan een MX die eindigt op google.com via deze hop te routeren)",
"mailbox_rename": "Hernoem mailbox",
"mailbox_rename_agree": "Ik heb een backup gemaakt.",
"mailbox_rename_warning": "BELANGRIJK! Maak een back-up voordat u de mailbox hernoemt.",
"mailbox_rename_alias": "Alias automatisch aanmaken.",
"mailbox_rename_title": "Nieuwe naam van de lokale mailbox",
"mta_sts": "MTA-STS",
"mta_sts_info": "<a href='https://en.wikipedia.org/wiki/Simple_Mail_Transfer_Protocol#SMTP_MTA_Strict_Transport_Security' target='_blank'>MTA-STS</a> is een standaard die afdwingt dat e-mailbezorging tussen mailservers TLS met geldige certificaten gebruikt. <br>\nDeze wordt gebruikt wanneer <a target='_blank' href='https://en.wikipedia.org/wiki/DNS-based_Authentication_of_Named_Entities'>DANE</a> niet mogelijk is vanwege ontbrekende of niet-ondersteunde DNSSEC.<br>\n<b>Opmerking</b>: Als het ontvangende domein DANE met DNSSEC ondersteunt, heeft DANE <b>altijd</b> de voorkeur MTA-STS fungeert alleen als een fallback.",
"mta_sts_version": "Versie",
"mta_sts_version_info": "Definieert de versie van de MTA-STS-standaard momenteel is alleen <code>STSv1</code> geldig.",
"mta_sts_mode": "Modus",
"mta_sts_mode_info": "Er zijn drie modus om uit te kiezen:<ul><li><em>testing</em> het beleid wordt alleen gemonitord, overtredingen hebben geen impact.</li><li><em>enforce</em> het beleid wordt strikt afgedwongen, verbindingen zonder geldige TLS worden geweigerd.</li><li><em>none</em> het beleid wordt gepubliceerd maar niet toegepast.</li></ul>",
"mta_sts_max_age": "Maximale leeftijd",
"mta_sts_max_age_info": "Tijd in seconden dat ontvangende mailservers dit beleid mogen cachen voordat het opnieuw wordt opgehaald.",
"mta_sts_mx": "MX server",
"mta_sts_mx_info": "Staat verzending alleen toe naar expliciet vermelde mailserver-hostnamen; de verzendende MTA controleert of de DNS MX-hostnaam overeenkomt met de beleidslijst en staat levering alleen toe met een geldig TLS-certificaat (beschermt tegen MITM).",
"mta_sts_mx_notice": "Meerdere MX-servers kunnen worden opgegeven (gescheiden door kommas).",
"none_inherit": "Geen / Erven",
"password_recovery_email": "E-mail voor wachtwoordherstel",
"pushover": "Pushover",
"quota_warning_bcc": "Quotum waarschuwing BCC",
"quota_warning_bcc_info": "Waarschuwingen zullen in afzonderlijke exemplaren naar de volgende ontvangers worden gestuurd. Het onderwerp zal worden gevolgd door de bijbehorende gebruikersnaam tussen haakjes, bijvoorbeeld: <code>Contingentwaarschuwing (user@example.com)</code>.",
"sogo_access": "Verleen directe logintoegang tot SOGo",
"sogo_access_info": "Na het inloggen wordt de gebruiker automatisch doorgestuurd naar SOGo"
"mailbox_relayhost_info": "Wordt alleen toegepast op de mailbox en directe aliassen, maar heft een domein relayhost op."
},
"footer": {
"cancel": "Annuleren",
@@ -766,21 +637,18 @@
"restart_container": "Herstart container",
"restart_container_info": "<b>Belangrijk:</b> Een herstart kan enige tijd in beslag nemen, wacht aub totdat dit proces voltooid is.<br>Deze pagina zal zichzelf verversen zodra het proces voltooid is.",
"restart_now": "Nu herstarten",
"restarting_container": "Container wordt herstart, even geduld aub...",
"hibp_check": "Controleer tegen haveibeenpwned.com",
"nothing_selected": "Niets geselecteerd"
"restarting_container": "Container wordt herstart, even geduld aub..."
},
"header": {
"administration": "Configuratie & details",
"apps": "Apps",
"debug": "Informatie",
"debug": "Systeeminformatie",
"email": "E-Mail",
"mailcow_config": "Beheer",
"quarantine": "Quarantaine",
"restart_netfilter": "Herstart netfilter",
"restart_sogo": "Herstart SOGo",
"user_settings": "Gebruikersinstellingen",
"mailcow_system": "Systeem"
"user_settings": "Gebruikersinstellingen"
},
"info": {
"awaiting_tfa_confirmation": "In afwachting van tweefactorauthenticatie...",
@@ -794,22 +662,7 @@
"mobileconfig_info": "Log in als mailboxgebruiker om het Apple-verbindingsprofiel te downloaden.",
"other_logins": "of aanmelden met",
"password": "Wachtwoord",
"username": "Gebruikersnaam",
"back_to_mailcow": "Terug naar mailcow",
"forgot_password": "> Wachtwoord vergeten?",
"invalid_pass_reset_token": "De reset-wachtwoordtoken is ongeldig of verlopen.<br>Vraag een nieuwe link voor het resetten van het wachtwoord aan.",
"login_linkstext": "Niet de juiste login?",
"login_usertext": "Log in als gebruiker",
"login_domainadmintext": "Login in als domeinbeheerder",
"login_admintext": "Log in als administrator",
"login_user": "Gebruikerslogin",
"login_dadmin": "Domeinbeheerder login",
"login_admin": "Administrator login",
"new_password": "Nieuw wachtwoord",
"new_password_confirm": "Bevestig nieuw wachtwoord",
"reset_password": "Herstel wachtwoord",
"request_reset_password": "Verzoek wachtwoord wijziging",
"email": "E-mailadres"
"username": "Gebruikersnaam"
},
"mailbox": {
"action": "Handeling",
@@ -929,7 +782,7 @@
"sieve_preset_5": "Autoreply (vakantie)",
"sieve_preset_6": "Weiger mail met antwoord",
"sieve_preset_7": "Forward en behoud/verwijder",
"sieve_preset_8": "E-mail van een specifieke afzender doorsturen, als gelezen markeren en in een submap plaatsen",
"sieve_preset_8": "Verwijder mail verstuurd naar een aliasadres van de afzender",
"sieve_preset_header": "Zie de onderstaande voorbeelden. Raadpleeg <a href=\"https://en.wikipedia.org/wiki/Sieve_(mail_filtering_language)\" target=\"_blank\">Wikipedia</a> voor meer informatie.",
"sogo_visible": "Alias tonen in SOGo",
"sogo_visible_n": "Verberg alias in SOGo",
@@ -956,37 +809,7 @@
"toggle_all": "Selecteer alles",
"username": "Gebruikersnaam",
"waiting": "Wachten",
"weekly": "Wekelijks",
"add_alias_expand": "Alias uitbreiden over alias-domeinen",
"add_template": "Sjabloon toevoegen",
"all_domains": "Alle domeinen",
"catch_all": "Catch-All",
"created_on": "Aangemaakt op",
"domain_templates": "Domein sjablonen",
"domain_quota_total": "Totale domein-opslagruimte",
"goto_ham": "Leren als <b>Ham</b>",
"goto_spam": "Leren als <b>spam</b>",
"iam": "Identiteitsprovider",
"internal": "Intern",
"last_pw_change": "Laatste wachtwoordwijziging",
"mailbox_templates": "Mailbox sjablonen",
"no": "&#10005;",
"open_logs": "Open logs",
"recipient": "Ontvanger",
"relay_unknown": "Onbekende mailboxen relayen",
"sender": "Afzender",
"syncjob_check_log": "Controleer log",
"syncjob_last_run_result": "Laatste uitvoeringsresultaat",
"syncjob_EX_OK": "Succes",
"syncjob_EXIT_CONNECTION_FAILURE": "Verbindingsprobleem",
"syncjob_EXIT_TLS_FAILURE": "Probleem met versleutelde verbinding",
"syncjob_EXIT_AUTHENTICATION_FAILURE": "Authenticatieprobleem",
"syncjob_EXIT_OVERQUOTA": "Doel mailbox is over quota",
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Kan geen verbinding maken met de externe server",
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Verkeerde gebruikersnaam of wachtwoord",
"templates": "Sjablonen",
"template": "Sjabloon",
"yes": "&#10003;"
"weekly": "Wekelijks"
},
"oauth2": {
"access_denied": "Log in als een mailboxgebruiker om toegang via OAuth te verlenen",
@@ -1019,7 +842,7 @@
"notified": "Verwittigd",
"qhandler_success": "Aanvraag succesvol verzonden naar het systeem. Je kunt nu het venster sluiten.",
"qid": "Rspamd QID",
"qinfo": "Het quarantainesysteem slaat een kopie van zowel geweigerde mail (voor de afzender zal het lijken alsof de mail <em>niet</em> afgeleverd is), als mail die afgeleverd is de spamfolder, op in de database.\n <br>\"Markeer als spam en verwijder\" traint het systeem om soortgelijke mails in de toekomst opnieuw als spam te markeren.\n <br>Wanneer er meerdere berichten tegelijkertijd worden behandeld kan het mogelijk enige tijd duren.<br>Elementen op de denylist zijn uitgesloten van de quarantaine.",
"qinfo": "Het quarantainesysteem slaat een kopie van zowel geweigerde mail (voor de afzender zal het lijken alsof de mail <em>niet</em> afgeleverd is), als mail die afgeleverd is de spamfolder, op in de database.\r\n <br>\"Markeer als spam en verwijder\" traint het systeem om soortgelijke mails in de toekomst opnieuw als spam te markeren.\r\n <br>Wanneer er meerdere berichten tegelijkertijd worden behandeld kan het mogelijk enige tijd duren.<br>Elementen op de blacklist zijn uitgesloten van de quarantaine.",
"qitem": "Quarantaine-item",
"quarantine": "Quarantaine",
"quick_actions": "Handelingen",
@@ -1051,19 +874,7 @@
"toggle_all": "Selecteer alles"
},
"queue": {
"queue_manager": "Queue manager",
"delete": "Verwijder alles",
"flush": "Wachtrij leegmaken",
"info": "De mailwachtrij bevat alle e-mails die wachten op aflevering. Als een e-mail lange tijd in de mailwachtrij blijft staan, wordt deze automatisch door het systeem verwijderd.<br>De foutmelding van de betreffende e-mail geeft informatie over waarom de e-mail niet kon worden afgeleverd.",
"legend": "Functies voor acties in de mailwachtrij:",
"ays": "Bevestig dat u alle items uit de huidige wachtrij wilt verwijderen.",
"deliver_mail": "Afleveren",
"deliver_mail_legend": "Probeert de geselecteerde e-mails opnieuw te bezorgen.",
"hold_mail": "Vasthouden",
"hold_mail_legend": "Houdt de geselecteerde e-mails vast. (Voorkomt verdere afleverpogingen)",
"show_message": "Bericht weergeven",
"unban": "Wachtrij deblokkeren",
"unhold_mail": "Vrijgeven"
"queue_manager": "Queue manager"
},
"start": {
"help": "Toon/verberg hulppaneel",
@@ -1183,8 +994,7 @@
"start_fido2_validation": "Start FIDO2-validatie",
"fido2_auth": "Aanmelden met FIDO2",
"fido2_success": "Apparaat succesvol geregistreerd",
"fido2_validation_failed": "Validatie mislukt",
"set_fido2_touchid": "Registreer Touch ID op Apple M1"
"fido2_validation_failed": "Validatie mislukt"
},
"user": {
"action": "Handeling",
@@ -1351,7 +1161,6 @@
"loadingRecords": "Laden...",
"processing": "Wachten alstublieft..",
"search": "Zoeken:",
"zeroRecords": "Geen overeenkomsten gevonden",
"infoFiltered": "(gefilterd uit _MAX_ totale vermeldingen)"
"zeroRecords": "Geen overeenkomsten gevonden"
}
}

View File

@@ -84,7 +84,7 @@ services:
- clamd
rspamd-mailcow:
image: ghcr.io/mailcow/rspamd:3.14.3-1
image: ghcr.io/mailcow/rspamd:3.14.2
stop_grace_period: 30s
depends_on:
- dovecot-mailcow
@@ -200,7 +200,7 @@ services:
- phpfpm
sogo-mailcow:
image: ghcr.io/mailcow/sogo:5.12.5-1
image: ghcr.io/mailcow/sogo:5.12.4-2
environment:
- DBNAME=${DBNAME}
- DBUSER=${DBUSER}
@@ -225,12 +225,12 @@ services:
- ./data/hooks/sogo:/hooks:Z
- ./data/conf/sogo/:/etc/sogo/:z
- ./data/web/inc/init_db.inc.php:/init_db.inc.php:z
- ./data/conf/sogo/custom-favicon.ico:/usr/local/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
- ./data/conf/sogo/custom-shortlogo.svg:/usr/local/lib/GNUstep/SOGo/WebServerResources/img/sogo-compact.svg:z
- ./data/conf/sogo/custom-fulllogo.svg:/usr/local/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg:z
- ./data/conf/sogo/custom-fulllogo.png:/usr/local/lib/GNUstep/SOGo/WebServerResources/img/sogo-logo.png:z
- ./data/conf/sogo/custom-theme.js:/usr/local/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
- ./data/conf/sogo/custom-sogo.js:/usr/local/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
- ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
- ./data/conf/sogo/custom-shortlogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-compact.svg:z
- ./data/conf/sogo/custom-fulllogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg:z
- ./data/conf/sogo/custom-fulllogo.png:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-logo.png:z
- ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
- ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
- mysql-socket-vol-1:/var/run/mysqld/:z
- sogo-web-vol-1:/sogo_web
- sogo-userdata-backup-vol-1:/sogo_backup
@@ -449,7 +449,7 @@ services:
- ./data/web/inc/functions.inc.php:/mailcowauth/functions.inc.php:z
- ./data/web/inc/functions.auth.inc.php:/mailcowauth/functions.auth.inc.php:z
- ./data/web/inc/sessions.inc.php:/mailcowauth/sessions.inc.php:z
- sogo-web-vol-1:/usr/local/lib/GNUstep/SOGo/
- sogo-web-vol-1:/usr/lib/GNUstep/SOGo/
ports:
- "${HTTPS_BIND:-}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}"
- "${HTTP_BIND:-}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"

View File

@@ -299,7 +299,7 @@ ACME_DNS_CHALLENGE=n
ACME_DNS_PROVIDER=dns_xxx
ACME_ACCOUNT_EMAIL=me@example.com
# You will need to pass provider-specific environment variables to the acme-mailcow container.
# See the dns-01 provider documentation for more information.
# See the dns-101 provider documentation for more information.
# for example for Azure DNS:
#AZUREDNS_SUBSCRIPTIONID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx
#AZUREDNS_TENANTID=xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx

View File

@@ -19,48 +19,30 @@ if [ ! -f "${PWD}/mailcow.conf" ]; then
fi
BRANCH="$(cd "${SCRIPT_DIR}" && git rev-parse --abbrev-ref HEAD)"
# Check for --dev flag early to skip _modules update
for arg in "$@"; do
if [[ "$arg" == "--dev" || "$arg" == "-d" ]]; then
echo -e "\e[32mRunning in Developer mode...\e[0m"
DEV=y
break
fi
done
MODULE_DIR="${SCRIPT_DIR}/_modules"
if [ ! "$DEV" ]; then
# 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[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
# 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
echo -e "\e[33mDeveloper mode: Skipping _modules update from git\e[0m"
if [[ ! -d "${MODULE_DIR}" || -z "$(ls -A "${MODULE_DIR}")" ]]; then
echo -e "\e[31mError: _modules directory is missing or empty!\e[0m"
exit 2
fi
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[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
source _modules/scripts/core.sh
@@ -169,7 +151,8 @@ while (($#)); do
FORCE=y
;;
-d|--dev)
# Already handled at the top of the script before _modules update
echo -e "\e[32mRunning in Developer mode...\e[0m"
DEV=y
;;
--legacy)
CURRENT_BRANCH="$(cd "${SCRIPT_DIR}"; git rev-parse --abbrev-ref HEAD)"