2
0
Эх сурвалжийг харах

Merge branch 'master' into admin-login

André Peters 6 жил өмнө
parent
commit
216451ed43

+ 2 - 2
data/Dockerfiles/postfix/postfix.sh

@@ -104,8 +104,8 @@ query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM relayhosts
   WHERE id IN (
   WHERE id IN (
     SELECT relayhost FROM domain
     SELECT relayhost FROM domain
       WHERE CONCAT('@', domain) = '%s'
       WHERE CONCAT('@', domain) = '%s'
-      OR '%s' IN (
-        SELECT CONCAT('@', alias_domain) FROM alias_domain
+      OR domain IN (
+        SELECT target_domain FROM alias_domain WHERE CONCAT('@', alias_domain) =  '%s'
       )
       )
   )
   )
   AND active = '1'
   AND active = '1'

+ 1 - 3
data/Dockerfiles/rspamd/Dockerfile

@@ -10,10 +10,9 @@ RUN apt-get update && apt-get install -y \
 	gnupg2 \
 	gnupg2 \
 	apt-transport-https \
 	apt-transport-https \
 	&& apt-key adv --fetch-keys https://rspamd.com/apt/gpg.key \
 	&& apt-key adv --fetch-keys https://rspamd.com/apt/gpg.key \
-	&& echo "deb https://rspamd.com/apt-stable/ bionic main" > /etc/apt/sources.list.d/rspamd.list \
+	&& echo "deb https://rspamd.com/apt/ bionic main" > /etc/apt/sources.list.d/rspamd.list \
 	&& apt-get update && apt-get install -y rspamd \
 	&& apt-get update && apt-get install -y rspamd \
 	&& rm -rf /var/lib/apt/lists/* \
 	&& rm -rf /var/lib/apt/lists/* \
-	&& echo '.include $LOCAL_CONFDIR/local.d/rspamd.conf.local' > /etc/rspamd/rspamd.conf.local \
 	&& apt-get autoremove --purge \
 	&& apt-get autoremove --purge \
 	&& apt-get clean \
 	&& apt-get clean \
 	&& mkdir -p /run/rspamd \
 	&& mkdir -p /run/rspamd \
@@ -21,7 +20,6 @@ RUN apt-get update && apt-get install -y \
 
 
 COPY settings.conf /etc/rspamd/settings.conf
 COPY settings.conf /etc/rspamd/settings.conf
 COPY docker-entrypoint.sh /docker-entrypoint.sh
 COPY docker-entrypoint.sh /docker-entrypoint.sh
-COPY metadata_exporter.lua /usr/share/rspamd/lua/metadata_exporter.lua
 
 
 ENTRYPOINT ["/docker-entrypoint.sh"]
 ENTRYPOINT ["/docker-entrypoint.sh"]
 
 

+ 21 - 17
data/Dockerfiles/watchdog/watchdog.sh

@@ -37,7 +37,7 @@ progress() {
 log_msg() {
 log_msg() {
   if [[ ${2} != "no_redis" ]]; then
   if [[ ${2} != "no_redis" ]]; then
     redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}" | \
     redis-cli -h redis LPUSH WATCHDOG_LOG "{\"time\":\"$(date +%s)\",\"message\":\"$(printf '%s' "${1}" | \
-      tr '%&;$"_[]{}-\r\n' ' ')\"}" > /dev/null
+      tr '\r\n%&;$"_[]{}-' ' ')\"}" > /dev/null
   fi
   fi
   echo $(date) $(printf '%s\n' "${1}")
   echo $(date) $(printf '%s\n' "${1}")
 }
 }
@@ -115,7 +115,7 @@ nginx_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/nginx-mailcow
+    touch /tmp/nginx-mailcow; echo "$(tail -50 /tmp/nginx-mailcow)" > /tmp/nginx-mailcow
     host_ip=$(get_container_ip nginx-mailcow)
     host_ip=$(get_container_ip nginx-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u / -p 8081 2>> /tmp/nginx-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u / -p 8081 2>> /tmp/nginx-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -140,7 +140,7 @@ unbound_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/unbound-mailcow
+    touch /tmp/unbound-mailcow; echo "$(tail -50 /tmp/unbound-mailcow)" > /tmp/unbound-mailcow
     host_ip=$(get_container_ip unbound-mailcow)
     host_ip=$(get_container_ip unbound-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_dns -s ${host_ip} -H stackoverflow.com 2>> /tmp/unbound-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_dns -s ${host_ip} -H stackoverflow.com 2>> /tmp/unbound-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -172,7 +172,7 @@ mysql_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/mysql-mailcow
+    touch /tmp/mysql-mailcow; echo "$(tail -50 /tmp/mysql-mailcow)" > /tmp/mysql-mailcow
     host_ip=$(get_container_ip mysql-mailcow)
     host_ip=$(get_container_ip mysql-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_mysql -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 2>> /tmp/mysql-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_mysql -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 2>> /tmp/mysql-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -198,7 +198,7 @@ sogo_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/sogo-mailcow
+    touch /tmp/sogo-mailcow; echo "$(tail -50 /tmp/sogo-mailcow)" > /tmp/sogo-mailcow
     host_ip=$(get_container_ip sogo-mailcow)
     host_ip=$(get_container_ip sogo-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 2>> /tmp/sogo-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 2>> /tmp/sogo-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -223,7 +223,7 @@ postfix_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/postfix-mailcow
+    touch /tmp/postfix-mailcow; echo "$(tail -50 /tmp/postfix-mailcow)" > /tmp/postfix-mailcow
     host_ip=$(get_container_ip postfix-mailcow)
     host_ip=$(get_container_ip postfix-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -f "watchdog@invalid" -C "RCPT TO:null@localhost" -C DATA -C . -R 250 2>> /tmp/postfix-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 589 -f "watchdog@invalid" -C "RCPT TO:null@localhost" -C DATA -C . -R 250 2>> /tmp/postfix-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -249,7 +249,7 @@ clamd_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/clamd-mailcow
+    touch /tmp/clamd-mailcow; echo "$(tail -50 /tmp/clamd-mailcow)" > /tmp/clamd-mailcow
     host_ip=$(get_container_ip clamd-mailcow)
     host_ip=$(get_container_ip clamd-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_clamd -4 -H ${host_ip} 2>> /tmp/clamd-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_clamd -4 -H ${host_ip} 2>> /tmp/clamd-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -274,7 +274,7 @@ dovecot_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/dovecot-mailcow
+    touch /tmp/dovecot-mailcow; echo "$(tail -50 /tmp/dovecot-mailcow)" > /tmp/dovecot-mailcow
     host_ip=$(get_container_ip dovecot-mailcow)
     host_ip=$(get_container_ip dovecot-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 24 -f "watchdog@invalid" -C "RCPT TO:<watchdog@invalid>" -L -R "User doesn't exist" 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_smtp -4 -H ${host_ip} -p 24 -f "watchdog@invalid" -C "RCPT TO:<watchdog@invalid>" -L -R "User doesn't exist" 2>> /tmp/dovecot-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -303,7 +303,7 @@ phpfpm_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/php-fpm-mailcow
+    touch /tmp/php-fpm-mailcow; echo "$(tail -50 /tmp/php-fpm-mailcow)" > /tmp/php-fpm-mailcow
     host_ip=$(get_container_ip php-fpm-mailcow)
     host_ip=$(get_container_ip php-fpm-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
     /usr/lib/nagios/plugins/check_tcp -H ${host_ip} -p 9001 2>> /tmp/php-fpm-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
     /usr/lib/nagios/plugins/check_tcp -H ${host_ip} -p 9001 2>> /tmp/php-fpm-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
@@ -358,10 +358,11 @@ ipv6nat_checks() {
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
     err_c_cur=${err_count}
     err_c_cur=${err_count}
-    IPV6NAT_CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\")) | .id")
+    CONTAINERS=$(curl --silent --insecure https://dockerapi/containers/json)
+    IPV6NAT_CONTAINER_ID=$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\")) | .id")
     if [[ ! -z ${IPV6NAT_CONTAINER_ID} ]]; then
     if [[ ! -z ${IPV6NAT_CONTAINER_ID} ]]; then
-      LATEST_STARTED="$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\") | not)" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)"
-      LATEST_IPV6NAT="$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\"))" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)"
+      LATEST_STARTED="$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\") | not)" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)"
+      LATEST_IPV6NAT="$(echo ${CONTAINERS} | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], StartedAt: .State.StartedAt}" | jq -rc "select( .name | tostring | contains(\"ipv6nat-mailcow\"))" | jq -rc .StartedAt | xargs -n1 date +%s -d | sort | tail -n1)"
       DIFFERENCE_START_TIME=$(expr ${LATEST_IPV6NAT} - ${LATEST_STARTED} 2>/dev/null)
       DIFFERENCE_START_TIME=$(expr ${LATEST_IPV6NAT} - ${LATEST_STARTED} 2>/dev/null)
       if [[ "${DIFFERENCE_START_TIME}" -lt 30 ]]; then
       if [[ "${DIFFERENCE_START_TIME}" -lt 30 ]]; then
         err_count=$(( ${err_count} + 1 ))
         err_count=$(( ${err_count} + 1 ))
@@ -375,12 +376,13 @@ ipv6nat_checks() {
       sleep 1
       sleep 1
     else
     else
       diff_c=0
       diff_c=0
-      sleep 3600
+      sleep 300
     fi
     fi
   done
   done
   return 1
   return 1
 }
 }
 
 
+
 rspamd_checks() {
 rspamd_checks() {
   err_count=0
   err_count=0
   diff_c=0
   diff_c=0
@@ -388,15 +390,14 @@ rspamd_checks() {
   # Reduce error count by 2 after restarting an unhealthy container
   # Reduce error count by 2 after restarting an unhealthy container
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
   while [ ${err_count} -lt ${THRESHOLD} ]; do
   while [ ${err_count} -lt ${THRESHOLD} ]; do
-    cat /dev/null > /tmp/rspamd-mailcow
+    touch /tmp/rspamd-mailcow; echo "$(tail -50 /tmp/rspamd-mailcow)" > /tmp/rspamd-mailcow
     host_ip=$(get_container_ip rspamd-mailcow)
     host_ip=$(get_container_ip rspamd-mailcow)
     err_c_cur=${err_count}
     err_c_cur=${err_count}
-    SCORE=$(/usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan -d '
-To: null@localhost
+    SCORE=$(echo 'To: null@localhost
 From: watchdog@localhost
 From: watchdog@localhost
 
 
 Empty
 Empty
-' | jq -rc .required_score)
+' | usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan | jq -rc .required_score)
     if [[ ${SCORE} != "9999" ]]; then
     if [[ ${SCORE} != "9999" ]]; then
       echo "Rspamd settings check failed" 2>> /tmp/rspamd-mailcow 1>&2
       echo "Rspamd settings check failed" 2>> /tmp/rspamd-mailcow 1>&2
       err_count=$(( ${err_count} + 1))
       err_count=$(( ${err_count} + 1))
@@ -561,6 +562,9 @@ while true; do
   CONTAINER_ID=
   CONTAINER_ID=
   HAS_INITDB=
   HAS_INITDB=
   read com_pipe_answer </tmp/com_pipe
   read com_pipe_answer </tmp/com_pipe
+  if [ -s "/tmp/${com_pipe_answer}" ]; then
+    cat "/tmp/${com_pipe_answer}"
+  fi
   if [[ ${com_pipe_answer} == "ratelimit" ]]; then
   if [[ ${com_pipe_answer} == "ratelimit" ]]; then
     log_msg "At least one ratelimit was applied"
     log_msg "At least one ratelimit was applied"
     [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${com_pipe_answer}" "No further information available."
     [[ ! -z ${WATCHDOG_NOTIFY_EMAIL} ]] && mail_error "${com_pipe_answer}" "No further information available."

+ 1 - 1
data/conf/dovecot/dovecot.conf

@@ -328,7 +328,7 @@ plugin {
   quota_warning = storage=95%% quota-warning 95 %u
   quota_warning = storage=95%% quota-warning 95 %u
   quota_warning2 = storage=80%% quota-warning 80 %u
   quota_warning2 = storage=80%% quota-warning 80 %u
   sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
   sieve_pipe_bin_dir = /usr/local/lib/dovecot/sieve
-  sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute +vacation-seconds
+  sieve_global_extensions = +vnd.dovecot.pipe +vnd.dovecot.execute
   sieve_extensions = +notify +imapflags +vacation-seconds
   sieve_extensions = +notify +imapflags +vacation-seconds
   sieve_max_script_size = 1M
   sieve_max_script_size = 1M
   sieve_max_redirects = 30
   sieve_max_redirects = 30

+ 1 - 0
data/conf/postfix/local_transport

@@ -0,0 +1 @@
+/localhost$/  local:

+ 9 - 5
data/conf/postfix/main.cf

@@ -94,12 +94,16 @@ smtpd_tls_dh1024_param_file = /etc/ssl/mail/dhparams.pem
 smtpd_tls_eecdh_grade = auto
 smtpd_tls_eecdh_grade = auto
 smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL, DES-CBC3-SHA, ECDHE-RSA-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA
 smtpd_tls_exclude_ciphers = ECDHE-RSA-RC4-SHA, RC4, aNULL, DES-CBC3-SHA, ECDHE-RSA-DES-CBC3-SHA, EDH-RSA-DES-CBC3-SHA
 smtpd_tls_loglevel = 1
 smtpd_tls_loglevel = 1
-smtp_tls_mandatory_protocols = !SSLv2, !SSLv3
+
+smtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
 smtp_tls_protocols = !SSLv2, !SSLv3
 smtp_tls_protocols = !SSLv2, !SSLv3
-lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3
-lmtp_tls_protocols = !SSLv2, !SSLv2, !SSLv3
-smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3
+
+lmtp_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+lmtp_tls_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
+
+smtpd_tls_mandatory_protocols = !SSLv2, !SSLv3, !TLSv1, !TLSv1.1
 smtpd_tls_protocols = !SSLv2, !SSLv3
 smtpd_tls_protocols = !SSLv2, !SSLv3
+
 smtpd_tls_security_level = may
 smtpd_tls_security_level = may
 tls_preempt_cipherlist = yes
 tls_preempt_cipherlist = yes
 tls_ssl_options = NO_COMPRESSION
 tls_ssl_options = NO_COMPRESSION
@@ -134,5 +138,5 @@ smtp_sasl_mechanism_filter = plain, login
 smtp_tls_policy_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf
 smtp_tls_policy_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf
 smtp_header_checks = pcre:/opt/postfix/conf/anonymize_headers.pcre
 smtp_header_checks = pcre:/opt/postfix/conf/anonymize_headers.pcre
 mail_name = Postcow
 mail_name = Postcow
-transport_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf
+transport_maps = pcre:/opt/postfix/conf/local_transport, proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf
 smtp_sasl_auth_soft_bounce = no
 smtp_sasl_auth_soft_bounce = no

+ 3 - 0
data/conf/postfix/master.cf

@@ -2,14 +2,17 @@ smtp       inet  n       -       n       -       1       postscreen
 smtpd      pass  -       -       n       -       -       smtpd
 smtpd      pass  -       -       n       -       -       smtpd
   -o smtpd_helo_restrictions=permit_mynetworks,reject_non_fqdn_helo_hostname
   -o smtpd_helo_restrictions=permit_mynetworks,reject_non_fqdn_helo_hostname
   -o smtpd_sasl_auth_enable=no
   -o smtpd_sasl_auth_enable=no
+  -o smtpd_sender_restrictions=permit_mynetworks,reject_unlisted_sender,reject_unknown_sender_domain
 smtps    inet  n       -       n       -       -       smtpd
 smtps    inet  n       -       n       -       -       smtpd
   -o smtpd_tls_wrappermode=yes
   -o smtpd_tls_wrappermode=yes
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
+  -o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
   -o tls_preempt_cipherlist=yes
   -o tls_preempt_cipherlist=yes
 submission inet n       -       n       -       -       smtpd
 submission inet n       -       n       -       -       smtpd
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
   -o smtpd_enforce_tls=yes
   -o smtpd_enforce_tls=yes
   -o smtpd_tls_security_level=encrypt
   -o smtpd_tls_security_level=encrypt
+  -o smtpd_tls_mandatory_protocols=!SSLv2,!SSLv3
   -o tls_preempt_cipherlist=yes
   -o tls_preempt_cipherlist=yes
 588 inet n      -       n       -       -       smtpd
 588 inet n      -       n       -       -       smtpd
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject
   -o smtpd_client_restrictions=permit_mynetworks,permit_sasl_authenticated,reject

+ 30 - 32
data/conf/rspamd/dynmaps/settings.php

@@ -6,6 +6,8 @@ then any of these will trigger the rule. If a rule is triggered then no more rul
 */
 */
 header('Content-Type: text/plain');
 header('Content-Type: text/plain');
 require_once "vars.inc.php";
 require_once "vars.inc.php";
+// Getting headers sent by the client.
+$headers = apache_request_headers();
 
 
 ini_set('error_reporting', 0);
 ini_set('error_reporting', 0);
 
 
@@ -25,6 +27,23 @@ catch (PDOException $e) {
   exit;
   exit;
 }
 }
 
 
+// Check if db changed and return header
+/*$stmt = $pdo->prepare("SELECT UNIX_TIMESTAMP(UPDATE_TIME) AS `db_update_time` FROM information_schema.tables
+  WHERE `TABLE_NAME` = 'filterconf'
+    AND TABLE_SCHEMA = :dbname;");
+$stmt->execute(array(
+  ':dbname' => $database_name
+));
+$db_update_time = $stmt->fetch(PDO::FETCH_ASSOC)['db_update_time'];
+
+if (isset($headers['If-Modified-Since']) && (strtotime($headers['If-Modified-Since']) == $db_update_time)) {
+  header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 304);
+  exit;
+} else {
+  header('Last-Modified: '.gmdate('D, d M Y H:i:s', $db_update_time).' GMT', true, 200);
+}
+*/
+
 function parse_email($email) {
 function parse_email($email) {
   if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
   if (!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
   $a = strrpos($email, '@');
   $a = strrpos($email, '@');
@@ -107,8 +126,8 @@ function ucl_rcpts($object, $type) {
 settings {
 settings {
   watchdog {
   watchdog {
     priority = 10;
     priority = 10;
-    rcpt = "/null@localhost/i";
-    from = "/watchdog@localhost/i";
+    rcpt_mime = "/null@localhost/i";
+    from_mime = "/watchdog@localhost/i";
     apply "default" {
     apply "default" {
       actions {
       actions {
         reject = 9999.0;
         reject = 9999.0;
@@ -199,12 +218,13 @@ while ($row = array_shift($rows)) {
 ?>
 ?>
   whitelist_<?=$username_sane;?> {
   whitelist_<?=$username_sane;?> {
 <?php
 <?php
+  $list_items = array();
   $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
   $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
     WHERE `object`= :object
     WHERE `object`= :object
       AND `option` = 'whitelist_from'");
       AND `option` = 'whitelist_from'");
   $stmt->execute(array(':object' => $row['object']));
   $stmt->execute(array(':object' => $row['object']));
   $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
   $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
-  while ($item = array_shift($list_items)) {
+  foreach ($list_items as $item) {
 ?>
 ?>
     from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
     from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
 <?php
 <?php
@@ -237,24 +257,13 @@ while ($row = array_shift($rows)) {
       "MAILCOW_WHITE"
       "MAILCOW_WHITE"
     ]
     ]
   }
   }
-  whitelist_header_<?=$username_sane;?> {
+  whitelist_mime_<?=$username_sane;?> {
 <?php
 <?php
-  $header_from = array();
-  $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
-    WHERE `object`= :object
-      AND `option` = 'whitelist_from'");
-  $stmt->execute(array(':object' => $row['object']));
-  $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($list_items as $item) {
 ?>
 ?>
-    header = {
+    from_mime = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
 <?php
 <?php
-  while ($item = array_shift($list_items)) {
-    $header_from[] = str_replace('\*', '.*', preg_quote($item['value'], '/'));
   }
   }
-?>
-      "From" = "/(<?=implode('|', $header_from);?>)/i";
-    }
-<?php
   if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
   if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
 ?>
 ?>
     priority = 5;
     priority = 5;
@@ -297,13 +306,13 @@ while ($row = array_shift($rows)) {
 ?>
 ?>
   blacklist_<?=$username_sane;?> {
   blacklist_<?=$username_sane;?> {
 <?php
 <?php
-  $items[] = array();
+  $list_items = array();
   $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
   $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
     WHERE `object`= :object
     WHERE `object`= :object
       AND `option` = 'blacklist_from'");
       AND `option` = 'blacklist_from'");
   $stmt->execute(array(':object' => $row['object']));
   $stmt->execute(array(':object' => $row['object']));
   $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
   $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
-  while ($item = array_shift($list_items)) {
+  foreach ($list_items as $item) {
 ?>
 ?>
     from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
     from = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
 <?php
 <?php
@@ -338,22 +347,11 @@ while ($row = array_shift($rows)) {
   }
   }
   blacklist_header_<?=$username_sane;?> {
   blacklist_header_<?=$username_sane;?> {
 <?php
 <?php
-  $header_from = array();
-  $stmt = $pdo->prepare("SELECT `value` FROM `filterconf`
-    WHERE `object`= :object
-      AND `option` = 'blacklist_from'");
-  $stmt->execute(array(':object' => $row['object']));
-  $list_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
+  foreach ($list_items as $item) {
 ?>
 ?>
-    header = {
+    from_mime = "/<?='^' . str_replace('\*', '.*', preg_quote($item['value'], '/')) . '$' ;?>/i";
 <?php
 <?php
-  while ($item = array_shift($list_items)) {
-    $header_from[] = str_replace('\*', '.*', preg_quote($item['value'], '/'));
   }
   }
-?>
-      "From" = "/(<?=implode('|', $header_from);?>)/i";
-    }
-<?php
   if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
   if (!filter_var(trim($row['object']), FILTER_VALIDATE_EMAIL)) {
 ?>
 ?>
     priority = 5;
     priority = 5;

+ 0 - 16
data/conf/rspamd/local.d/rspamd.conf.local

@@ -1,16 +0,0 @@
-# rspamd.conf.local
-
-worker "fuzzy" {
-  # Socket to listen on (UDP and TCP from rspamd 1.3)
-  bind_socket = "*:11445";
-  allow_update = ["127.0.0.1", "::1"];
-  # Number of processes to serve this storage (useful for read scaling)
-  count = 2;
-  # Backend ("sqlite" or "redis" - default "sqlite")
-  backend = "redis";
-  # Hashes storage time (3 months)
-  expire = 90d;
-  # Synchronize updates to the storage each minute
-  sync = 1min;
-}
-

+ 12 - 0
data/conf/rspamd/override.d/worker-fuzzy.inc

@@ -0,0 +1,12 @@
+# Socket to listen on (UDP and TCP from rspamd 1.3)
+bind_socket = "*:11445";
+allow_update = ["127.0.0.1", "::1"];
+# Number of processes to serve this storage (useful for read scaling)
+count = 2;
+# Backend ("sqlite" or "redis" - default "sqlite")
+backend = "redis";
+# Hashes storage time (3 months)
+expire = 90d;
+# Synchronize updates to the storage each minute
+sync = 1min;
+

+ 1 - 1
data/conf/rspamd/override.d/worker-proxy.inc

@@ -1,6 +1,6 @@
 bind_socket = "rspamd:9900";
 bind_socket = "rspamd:9900";
 milter = true;
 milter = true;
-upstream {
+upstream "local" {
   name = "localhost";
   name = "localhost";
   default = true;
   default = true;
   hosts = "rspamd:11333"
   hosts = "rspamd:11333"

+ 1 - 0
data/web/admin.php

@@ -746,6 +746,7 @@ $tfa_data = get_tfa();
       <div id="active_settings_map" class="collapse" >
       <div id="active_settings_map" class="collapse" >
         <textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly><?=file_get_contents('http://nginx:8081/settings.php');?></textarea>
         <textarea autocorrect="off" spellcheck="false" autocapitalize="none" class="form-control textarea-code" rows="20" name="settings_map" readonly><?=file_get_contents('http://nginx:8081/settings.php');?></textarea>
       </div>
       </div>
+      <br>
       <?php $rsettings = rsettings('get'); ?>
       <?php $rsettings = rsettings('get'); ?>
         <form class="form" data-id="rsettings" role="form" method="post">
         <form class="form" data-id="rsettings" role="form" method="post">
           <div class="row">
           <div class="row">

Файлын зөрүү хэтэрхий том тул дарагдсан байна
+ 5 - 4
data/web/css/build/001-bootstrap.min.css


+ 3 - 0
data/web/inc/ajax/transport_check.php

@@ -58,6 +58,9 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admi
       )
       )
     );
     );
     $mail->SMTPDebug = 3;
     $mail->SMTPDebug = 3;
+    if ($port == 465) {
+      $mail->SMTPSecure = "ssl";
+    }
     $mail->Debugoutput = function($str, $level) {
     $mail->Debugoutput = function($str, $level) {
       foreach(preg_split("/((\r?\n)|(\r\n?)|\n)/", $str) as $line){
       foreach(preg_split("/((\r?\n)|(\r\n?)|\n)/", $str) as $line){
         if (empty($line)) { continue; }
         if (empty($line)) { continue; }

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

@@ -755,7 +755,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
           }
           }
           $password     = $_data['password'];
           $password     = $_data['password'];
           $password2    = $_data['password2'];
           $password2    = $_data['password2'];
-          $name         = $_data['name'];
+          $name         = ltrim(rtrim($_data['name'], '>'), '<');
           $quota_m			= filter_var($_data['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
           $quota_m			= filter_var($_data['quota'], FILTER_SANITIZE_NUMBER_FLOAT);
           if (empty($name)) {
           if (empty($name)) {
             $name = $local_part;
             $name = $local_part;
@@ -1993,7 +1993,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
               $active     = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
               $active     = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
               (int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
               (int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
               (int)$sogo_access = (isset($_data['sogo_access'])) ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
               (int)$sogo_access = (isset($_data['sogo_access'])) ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
-              $name       = (!empty($_data['name'])) ? $_data['name'] : $is_now['name'];
+              $name       = (!empty($_data['name'])) ? ltrim(rtrim($_data['name'], '>'), '<') : $is_now['name'];
               $domain     = $is_now['domain'];
               $domain     = $is_now['domain'];
               $quota_m    = (!empty($_data['quota'])) ? $_data['quota'] : ($is_now['quota'] / 1048576);
               $quota_m    = (!empty($_data['quota'])) ? $_data['quota'] : ($is_now['quota'] / 1048576);
               $quota_b    = $quota_m * 1048576;
               $quota_b    = $quota_m * 1048576;

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

@@ -141,7 +141,7 @@ $MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out'] = false;
 // Force password change on next login (only allows login to mailcow UI)
 // Force password change on next login (only allows login to mailcow UI)
 $MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false;
 $MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false;
 
 
-// Force password change on next login (only allows login to mailcow UI)
+// Enable SOGo access (set to false to disable access by default)
 $MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true;
 $MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true;
 
 
 // Send notification when quarantine is not empty (never, hourly, daily, weekly)
 // Send notification when quarantine is not empty (never, hourly, daily, weekly)

+ 5 - 5
data/web/lang/lang.de.php

@@ -607,11 +607,11 @@ $lang['admin']['forwarding_hosts_hint'] = 'Eingehende Nachrichten werden von den
 $lang['admin']['forwarding_hosts_add_hint'] = 'Sie können entweder IPv4/IPv6-Adressen, Netzwerke in CIDR-Notation, Hostnamen (die zu IP-Adressen aufgelöst werden), oder Domainnamen (die zu IP-Adressen aufgelöst werden, indem ihr SPF-Record abgefragt wird oder, in dessen Abwesenheit, ihre MX-Records) angeben.';
 $lang['admin']['forwarding_hosts_add_hint'] = 'Sie können entweder IPv4/IPv6-Adressen, Netzwerke in CIDR-Notation, Hostnamen (die zu IP-Adressen aufgelöst werden), oder Domainnamen (die zu IP-Adressen aufgelöst werden, indem ihr SPF-Record abgefragt wird oder, in dessen Abwesenheit, ihre MX-Records) angeben.';
 $lang['admin']['relayhosts_hint'] = 'Erstellen Sie senderabhängige Transporte, um diese im Einstellungsdialog einer Domain auszuwählen.<br>
 $lang['admin']['relayhosts_hint'] = 'Erstellen Sie senderabhängige Transporte, um diese im Einstellungsdialog einer Domain auszuwählen.<br>
   Der Transporttyp lautet immer "smtp:". Benutzereinstellungen bezüglich Verschlüsselungsrichtlinie werden beim Transport berücksichtigt.';
   Der Transporttyp lautet immer "smtp:". Benutzereinstellungen bezüglich Verschlüsselungsrichtlinie werden beim Transport berücksichtigt.';
-$lang['admin']['transports_hint'] = 'Transport Maps <b>überwiegen</b> senderabhängige Transport Maps und ignorieren die individuellen Einstellungen eines Benutzers bezüglich Verschlüsselungsrichtlinie, da der Absender bei Ermittlung der Transportregel nicht berücksichtigt wird.<br>
-  Der Transport erfolgt immer via "smtp:".<br>
-  Ein Eintrag in der TLS Policy Map kann eine Verschlüsselung erzwingen.<br>
-  Die Authentifizierung wird anhand des Host Parameters ermittelt, hierbei würde bei einem beispielhaften Next Hop "[host]:25" immer zuerst "host" abfragt und <b>erst im Anschluss</b> "[host]:25".<br>
-  Dieses Verhalten schließt die <b>gleichzeitige Verwendung</b> von Einträgen der Art "host" sowie "[host]:25" aus.';
+$lang['admin']['transports_hint'] = 'Transport Maps <b>überwiegen</b> senderabhängige Transport Maps.
+→ Transport Maps ignorieren Mailbox-Einstellungen für ausgehende Verschlüsselung. Eine serverweite TLS-Richtlinie wird jedoch angewendet.<br>
+→ Der Transport erfolgt immer via "smtp:".<br>
+→ Adressen, die mit "/localhost$/" übereinstimmen, werden immer via "local:" transportiert, daher sind sie von einer Zieldefinition "*" ausgeschlossen.<br>
+ Die Authentifizierung wird anhand des "Next hop" Parameters ermittelt. Hierbei würde bei einem beispielhaften Wert "[host]:25" immer zuerst "host" abfragt und <b>erst im Anschluss</b> "[host]:25". Dieses Verhalten schließt die <b>gleichzeitige Verwendung</b> von Einträgen der Art "host" sowie "[host]:25" aus.';
 $lang['admin']['add_relayhost_hint'] = 'Bitte beachten Sie, dass Anmeldedaten unverschlüsselt gespeichert werden.<br>
 $lang['admin']['add_relayhost_hint'] = 'Bitte beachten Sie, dass Anmeldedaten unverschlüsselt gespeichert werden.<br>
   Angelegte Transporte dieser Art sind <b>senderabhängig</b> und müssen erst einer Domain zugewiesen werden, bevor sie als Transport verwendet werden.<br>
   Angelegte Transporte dieser Art sind <b>senderabhängig</b> und müssen erst einer Domain zugewiesen werden, bevor sie als Transport verwendet werden.<br>
   Diese Einstellungen entsprechen demach <i>nicht</i> dem "relayhost" Parameter in Postfix.';
   Diese Einstellungen entsprechen demach <i>nicht</i> dem "relayhost" Parameter in Postfix.';

+ 5 - 3
data/web/lang/lang.en.php

@@ -631,9 +631,11 @@ $lang['admin']['forwarding_hosts_hint'] = 'Incoming messages are unconditionally
 $lang['admin']['forwarding_hosts_add_hint'] = 'You can either specify IPv4/IPv6 addresses, networks in CIDR notation, host names (which will be resolved to IP addresses), or domain names (which will be resolved to IP addresses by querying SPF records or, in their absence, MX records).';
 $lang['admin']['forwarding_hosts_add_hint'] = 'You can either specify IPv4/IPv6 addresses, networks in CIDR notation, host names (which will be resolved to IP addresses), or domain names (which will be resolved to IP addresses by querying SPF records or, in their absence, MX records).';
 $lang['admin']['relayhosts_hint'] = 'Define sender-dependent transports to be able to select them in a domains configuration dialog.<br>
 $lang['admin']['relayhosts_hint'] = 'Define sender-dependent transports to be able to select them in a domains configuration dialog.<br>
   The transport service is always "smtp:". A users individual outbound TLS policy setting is taken into account.';
   The transport service is always "smtp:". A users individual outbound TLS policy setting is taken into account.';
-$lang['admin']['transports_hint'] = 'A transport map entry <b>overrules</b> a sender-dependent transport map</b>.<br>
-Outbound TLS policy settings per-user are ignored and can only be enfored by TLS policy map entries. The transport service is always "smtp:".<br>
-To determine credentials for an exemplary next hop "[host]:25", Postfix <b>always</b> queries for "nexthop" before searching for "[nexthop]:25". This behavior makes it impossible to use "nexthop" and "[nexthop]:25" at the same time.';
+$lang['admin']['transports_hint'] = '→ A transport map entry <b>overrules</b> a sender-dependent transport map</b>.<br>
+→ Outbound TLS policy settings per-user are ignored and can only be enfored by TLS policy map entries.<br>
+→ The transport service for defined transports is always "smtp:".<br>
+→ Adresses matching "/localhost$/" will always be transported via "local:", therefore a "*" destination will not apply to those addresses.<br>
+→ To determine credentials for an exemplary next hop "[host]:25", Postfix <b>always</b> queries for "host" before searching for "[host]:25". This behavior makes it impossible to use "host" and "[host]:25" at the same time.';
 $lang['admin']['add_relayhost_hint'] = 'Please be aware that authentication data, if any, will be stored as plain text.';
 $lang['admin']['add_relayhost_hint'] = 'Please be aware that authentication data, if any, will be stored as plain text.';
 $lang['admin']['add_transports_hint'] = 'Please be aware that authentication data, if any, will be stored as plain text.';
 $lang['admin']['add_transports_hint'] = 'Please be aware that authentication data, if any, will be stored as plain text.';
 $lang['admin']['host'] = 'Host';
 $lang['admin']['host'] = 'Host';

+ 3 - 4
docker-compose.yml

@@ -71,7 +71,7 @@ services:
             - clamd
             - clamd
 
 
     rspamd-mailcow:
     rspamd-mailcow:
-      image: mailcow/rspamd:1.34
+      image: mailcow/rspamd:1.36
       build: ./data/Dockerfiles/rspamd
       build: ./data/Dockerfiles/rspamd
       stop_grace_period: 30s
       stop_grace_period: 30s
       depends_on:
       depends_on:
@@ -219,7 +219,7 @@ services:
             - dovecot
             - dovecot
 
 
     postfix-mailcow:
     postfix-mailcow:
-      image: mailcow/postfix:1.29
+      image: mailcow/postfix:1.31
       build: ./data/Dockerfiles/postfix
       build: ./data/Dockerfiles/postfix
       volumes:
       volumes:
         - ./data/conf/postfix:/opt/postfix/conf
         - ./data/conf/postfix:/opt/postfix/conf
@@ -239,7 +239,6 @@ services:
       ports:
       ports:
         - "${SMTP_PORT:-25}:25"
         - "${SMTP_PORT:-25}:25"
         - "${SMTPS_PORT:-465}:465"
         - "${SMTPS_PORT:-465}:465"
-        - "${SUBMISSION_PORT:-587}:587"
       restart: always
       restart: always
       dns:
       dns:
         - ${IPV4_NETWORK:-172.22.1}.254
         - ${IPV4_NETWORK:-172.22.1}.254
@@ -357,7 +356,7 @@ services:
         - /lib/modules:/lib/modules:ro
         - /lib/modules:/lib/modules:ro
 
 
     watchdog-mailcow:
     watchdog-mailcow:
-      image: mailcow/watchdog:1.35
+      image: mailcow/watchdog:1.37
       # Debug
       # Debug
       #command: /watchdog.sh
       #command: /watchdog.sh
       build: ./data/Dockerfiles/watchdog
       build: ./data/Dockerfiles/watchdog

+ 4 - 1
update.sh

@@ -6,9 +6,12 @@ if [ "$(id -u)" -ne "0" ]; then
   exit 1
   exit 1
 fi
 fi
 
 
-#exit on error and pipefail
+# Exit on error and pipefail
 set -o pipefail
 set -o pipefail
 
 
+# Add /opt/bin to PATH
+PATH=$PATH:/opt/bin
+
 umask 0022
 umask 0022
 
 
 for bin in curl docker-compose docker git awk sha1sum; do
 for bin in curl docker-compose docker git awk sha1sum; do

Энэ ялгаанд хэт олон файл өөрчлөгдсөн тул зарим файлыг харуулаагүй болно