mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-09-13 17:27:58 +00:00
Compare commits
21
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
489db90512 | ||
|
|
641ed63782 | ||
|
|
96a70652c3 | ||
|
|
2ac4b1deae | ||
|
|
1eb6d2e26c | ||
|
|
384e2f6ac1 | ||
|
|
32156a337a | ||
|
|
281cf93db3 | ||
|
|
f399c07c85 | ||
|
|
a693325fe6 | ||
|
|
9ad84eee92 | ||
|
|
b59869b720 | ||
|
|
7515bef66c | ||
|
|
b84ba8ded1 | ||
|
|
4845928e7a | ||
|
|
4ccfedd6b3 | ||
|
|
e8d9315d4a | ||
|
|
d977ddb501 | ||
|
|
e76f5237ed | ||
|
|
c11ed5dd1e | ||
|
|
4ef65fc382 |
@@ -30,8 +30,6 @@ A big thank you to everyone supporting us on GitHub Sponsors—your contribution
|
|||||||
### 50$/Month Sponsors
|
### 50$/Month Sponsors
|
||||||
<a href="https://github.com/vnukhr" target=_blank><img
|
<a href="https://github.com/vnukhr" target=_blank><img
|
||||||
src="https://avatars.githubusercontent.com/u/7805987?s=52&v=4" height="58"
|
src="https://avatars.githubusercontent.com/u/7805987?s=52&v=4" height="58"
|
||||||
/></a><a href="https://github.com/humiico" target=_blank><img
|
|
||||||
src="https://avatars.githubusercontent.com/u/110134705?s=52&v=4" height="58"
|
|
||||||
/></a>
|
/></a>
|
||||||
|
|
||||||
## Info, documentation and support
|
## Info, documentation and support
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
FROM alpine:3.24 AS builder
|
FROM alpine:3.21 AS builder
|
||||||
|
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
ENV CLAMD_VERSION=1.4.6
|
ENV CLAMD_VERSION=1.4.2
|
||||||
|
|
||||||
RUN apk upgrade --no-cache \
|
RUN apk upgrade --no-cache \
|
||||||
&& apk add --update --no-cache \
|
&& apk add --update --no-cache \
|
||||||
@@ -68,7 +68,7 @@ RUN wget -P /src https://www.clamav.net/downloads/production/clamav-${CLAMD_VERS
|
|||||||
"/clamav/etc/clamav/clamav-milter.conf.sample" > "/clamav/etc/clamav/clamav-milter.conf" || exit 1
|
"/clamav/etc/clamav/clamav-milter.conf.sample" > "/clamav/etc/clamav/clamav-milter.conf" || exit 1
|
||||||
|
|
||||||
|
|
||||||
FROM alpine:3.24
|
FROM alpine:3.21
|
||||||
|
|
||||||
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
|
|||||||
@@ -1,17 +1,17 @@
|
|||||||
FROM golang:1.26-trixie AS builder
|
FROM golang:1.25-bookworm AS builder
|
||||||
WORKDIR /src
|
WORKDIR /src
|
||||||
|
|
||||||
ENV CGO_ENABLED=0 \
|
ENV CGO_ENABLED=0 \
|
||||||
GO111MODULE=on \
|
GO111MODULE=on \
|
||||||
NOOPT=1 \
|
NOOPT=1 \
|
||||||
VERSION=1.11.0
|
VERSION=1.8.22
|
||||||
|
|
||||||
RUN git clone --branch v${VERSION} https://github.com/Zuplu/postfix-tlspol && \
|
RUN git clone --branch v${VERSION} https://github.com/Zuplu/postfix-tlspol && \
|
||||||
cd /src/postfix-tlspol && \
|
cd /src/postfix-tlspol && \
|
||||||
scripts/build.sh build-only
|
scripts/build.sh build-only
|
||||||
|
|
||||||
|
|
||||||
FROM debian:trixie-slim
|
FROM debian:bookworm-slim
|
||||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@version: 4.8
|
@version: 3.38
|
||||||
@include "scl.conf"
|
@include "scl.conf"
|
||||||
options {
|
options {
|
||||||
chain_hostnames(off);
|
chain_hostnames(off);
|
||||||
@@ -7,7 +7,7 @@ options {
|
|||||||
dns_cache(no);
|
dns_cache(no);
|
||||||
use_fqdn(no);
|
use_fqdn(no);
|
||||||
owner("root"); group("adm"); perm(0640);
|
owner("root"); group("adm"); perm(0640);
|
||||||
stats(freq(0));
|
stats_freq(0);
|
||||||
bad_hostname("^gconfd$");
|
bad_hostname("^gconfd$");
|
||||||
};
|
};
|
||||||
source s_src {
|
source s_src {
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
@version: 4.8
|
@version: 3.38
|
||||||
@include "scl.conf"
|
@include "scl.conf"
|
||||||
options {
|
options {
|
||||||
chain_hostnames(off);
|
chain_hostnames(off);
|
||||||
@@ -7,7 +7,7 @@ options {
|
|||||||
dns_cache(no);
|
dns_cache(no);
|
||||||
use_fqdn(no);
|
use_fqdn(no);
|
||||||
owner("root"); group("adm"); perm(0640);
|
owner("root"); group("adm"); perm(0640);
|
||||||
stats(freq(0));
|
stats_freq(0);
|
||||||
bad_hostname("^gconfd$");
|
bad_hostname("^gconfd$");
|
||||||
};
|
};
|
||||||
source s_src {
|
source s_src {
|
||||||
|
|||||||
@@ -12,8 +12,8 @@ FROM debian:bookworm
|
|||||||
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
|
||||||
|
|
||||||
ARG DEBIAN_FRONTEND=noninteractive
|
ARG DEBIAN_FRONTEND=noninteractive
|
||||||
ARG SOGO_VERSION=SOGo-5.12.10
|
ARG SOGO_VERSION=SOGo-5.12.9
|
||||||
ARG SOPE_VERSION=SOPE-5.12.10
|
ARG SOPE_VERSION=SOPE-5.12.9
|
||||||
# Security patches to apply (space-separated commit hashes)
|
# Security patches to apply (space-separated commit hashes)
|
||||||
ARG SOGO_SECURITY_PATCHES=""
|
ARG SOGO_SECURITY_PATCHES=""
|
||||||
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
|
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
|
||||||
|
|||||||
@@ -32,17 +32,8 @@ function auth_password_verify(request, password)
|
|||||||
-- Returning PASSDB_RESULT_PASSWORD_MISMATCH will reset the user's auth cache entry.
|
-- Returning PASSDB_RESULT_PASSWORD_MISMATCH will reset the user's auth cache entry.
|
||||||
-- Returning PASSDB_RESULT_INTERNAL_FAILURE keeps the existing cache entry,
|
-- Returning PASSDB_RESULT_INTERNAL_FAILURE keeps the existing cache entry,
|
||||||
-- even if the TTL has expired. Useful to avoid cache eviction during backend issues.
|
-- even if the TTL has expired. Useful to avoid cache eviction during backend issues.
|
||||||
|
|
||||||
-- On a network-level failure (nginx unreachable, DNS failure, timeout) https.request
|
|
||||||
-- returns nil plus an error string, so c is not a numeric HTTP status code. Treat this
|
|
||||||
-- as a backend outage and keep the cache entry, rather than wiping it as a mismatch.
|
|
||||||
if type(c) ~= "number" then
|
|
||||||
dovecot.i_info("HTTP request to auth backend failed with " .. tostring(c) .. " for user " .. request.user)
|
|
||||||
return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "Upstream unreachable"
|
|
||||||
end
|
|
||||||
|
|
||||||
if c ~= 200 and c ~= 401 then
|
if c ~= 200 and c ~= 401 then
|
||||||
dovecot.i_info("HTTP request failed with " .. tostring(c) .. " for user " .. request.user)
|
dovecot.i_info("HTTP request failed with " .. c .. " for user " .. request.user)
|
||||||
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Upstream error"
|
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Upstream error"
|
||||||
end
|
end
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,13 @@
|
|||||||
# global_sieve_before script
|
# global_sieve_before script
|
||||||
# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
|
# global_sieve_before -> user sieve_before (mailcow UI) -> user sieve_after (mailcow UI) -> global_sieve_after
|
||||||
|
|
||||||
|
require ["mailbox", "fileinto"];
|
||||||
|
|
||||||
|
if header :contains ["Chat-Version"] [""] {
|
||||||
|
if mailboxexists "DeltaChat" {
|
||||||
|
fileinto "DeltaChat";
|
||||||
|
} else {
|
||||||
|
fileinto :create "DeltaChat";
|
||||||
|
}
|
||||||
|
stop;
|
||||||
|
}
|
||||||
|
|||||||
@@ -116,7 +116,6 @@ location ~ \.php$ {
|
|||||||
include /etc/nginx/fastcgi_params;
|
include /etc/nginx/fastcgi_params;
|
||||||
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
|
||||||
fastcgi_param PATH_INFO $fastcgi_path_info;
|
fastcgi_param PATH_INFO $fastcgi_path_info;
|
||||||
fastcgi_param HTTP_X_REAL_IP $remote_addr;
|
|
||||||
# trusted internal-auth marker; empty for external clients (see nginx.conf map)
|
# trusted internal-auth marker; empty for external clients (see nginx.conf map)
|
||||||
fastcgi_param SOGO_AUTH_INTERNAL $sogo_auth_internal;
|
fastcgi_param SOGO_AUTH_INTERNAL $sogo_auth_internal;
|
||||||
fastcgi_read_timeout 3600;
|
fastcgi_read_timeout 3600;
|
||||||
|
|||||||
@@ -150,7 +150,7 @@ smtp_sasl_auth_enable = yes
|
|||||||
smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf
|
smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps_sender_dependent.cf
|
||||||
smtp_sasl_security_options =
|
smtp_sasl_security_options =
|
||||||
smtp_sasl_mechanism_filter = plain, login
|
smtp_sasl_mechanism_filter = plain, login
|
||||||
smtp_tls_policy_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf socketmap:inet:postfix-tlspol:8642:QUERYwithTLSRPT
|
smtp_tls_policy_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf socketmap:inet:postfix-tlspol:8642:QUERY
|
||||||
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
|
||||||
# local_transport map catches local destinations and prevents routing local dests when the next map would route "*"
|
# local_transport map catches local destinations and prevents routing local dests when the next map would route "*"
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Whitelist generated by Postwhite v3.4 on Tue Sep 1 00:34:07 UTC 2026
|
# Whitelist generated by Postwhite v3.4 on Wed Jul 1 00:51:20 UTC 2026
|
||||||
# https://github.com/stevejenkins/postwhite/
|
# https://github.com/stevejenkins/postwhite/
|
||||||
# 2243 total rules
|
# 2251 total rules
|
||||||
2a00:1450:4000::/36 permit
|
2a00:1450:4000::/36 permit
|
||||||
2a00:1450:4864::/56 permit
|
2a00:1450:4864::/56 permit
|
||||||
2a01:111:f400::/48 permit
|
2a01:111:f400::/48 permit
|
||||||
@@ -29,7 +29,6 @@
|
|||||||
2a01:b747:3004:200::/56 permit
|
2a01:b747:3004:200::/56 permit
|
||||||
2a01:b747:3005:200::/56 permit
|
2a01:b747:3005:200::/56 permit
|
||||||
2a01:b747:3006:200::/56 permit
|
2a01:b747:3006:200::/56 permit
|
||||||
2a01:b747:3007::/56 permit
|
|
||||||
2a02:a60:0:5::/64 permit
|
2a02:a60:0:5::/64 permit
|
||||||
2a0f:f640::/56 permit
|
2a0f:f640::/56 permit
|
||||||
2c0f:fb50:4000::/36 permit
|
2c0f:fb50:4000::/36 permit
|
||||||
@@ -57,14 +56,7 @@
|
|||||||
8.25.194.0/23 permit
|
8.25.194.0/23 permit
|
||||||
8.25.196.0/23 permit
|
8.25.196.0/23 permit
|
||||||
8.36.116.0/24 permit
|
8.36.116.0/24 permit
|
||||||
8.39.54.0/23 permit
|
|
||||||
8.39.54.240/29 permit
|
|
||||||
8.39.54.250/31 permit
|
|
||||||
8.39.144.0/24 permit
|
8.39.144.0/24 permit
|
||||||
8.40.222.0/23 permit
|
|
||||||
8.40.222.240/29 permit
|
|
||||||
8.40.222.250/31 permit
|
|
||||||
8.47.10.9 permit
|
|
||||||
12.130.86.238 permit
|
12.130.86.238 permit
|
||||||
13.108.16.0/20 permit
|
13.108.16.0/20 permit
|
||||||
13.110.208.0/21 permit
|
13.110.208.0/21 permit
|
||||||
@@ -75,7 +67,6 @@
|
|||||||
13.111.191.0/24 permit
|
13.111.191.0/24 permit
|
||||||
13.216.7.111 permit
|
13.216.7.111 permit
|
||||||
13.216.54.180 permit
|
13.216.54.180 permit
|
||||||
13.247.164.219 permit
|
|
||||||
15.200.21.50 permit
|
15.200.21.50 permit
|
||||||
15.200.44.248 permit
|
15.200.44.248 permit
|
||||||
15.200.201.185 permit
|
15.200.201.185 permit
|
||||||
@@ -125,6 +116,7 @@
|
|||||||
23.249.208.0/20 permit
|
23.249.208.0/20 permit
|
||||||
23.251.224.0/19 permit
|
23.251.224.0/19 permit
|
||||||
23.253.141.0/24 permit
|
23.253.141.0/24 permit
|
||||||
|
23.253.182.0/23 permit
|
||||||
23.253.182.103 permit
|
23.253.182.103 permit
|
||||||
23.253.183.145 permit
|
23.253.183.145 permit
|
||||||
23.253.183.146 permit
|
23.253.183.146 permit
|
||||||
@@ -146,7 +138,24 @@
|
|||||||
27.123.206.80/28 permit
|
27.123.206.80/28 permit
|
||||||
31.47.251.17 permit
|
31.47.251.17 permit
|
||||||
31.186.239.0/24 permit
|
31.186.239.0/24 permit
|
||||||
34.2.64.0/19 permit
|
34.2.64.0/22 permit
|
||||||
|
34.2.68.0/23 permit
|
||||||
|
34.2.70.0/23 permit
|
||||||
|
34.2.71.64/26 permit
|
||||||
|
34.2.72.0/22 permit
|
||||||
|
34.2.75.0/26 permit
|
||||||
|
34.2.78.0/23 permit
|
||||||
|
34.2.80.0/23 permit
|
||||||
|
34.2.82.0/23 permit
|
||||||
|
34.2.84.0/24 permit
|
||||||
|
34.2.84.64/26 permit
|
||||||
|
34.2.85.0/24 permit
|
||||||
|
34.2.85.64/26 permit
|
||||||
|
34.2.86.0/23 permit
|
||||||
|
34.2.88.0/23 permit
|
||||||
|
34.2.90.0/23 permit
|
||||||
|
34.2.92.0/23 permit
|
||||||
|
34.2.94.0/23 permit
|
||||||
34.70.158.162 permit
|
34.70.158.162 permit
|
||||||
34.74.74.140 permit
|
34.74.74.140 permit
|
||||||
34.83.159.189 permit
|
34.83.159.189 permit
|
||||||
@@ -161,7 +170,6 @@
|
|||||||
34.215.104.144 permit
|
34.215.104.144 permit
|
||||||
34.218.115.239 permit
|
34.218.115.239 permit
|
||||||
34.225.212.172 permit
|
34.225.212.172 permit
|
||||||
34.241.242.183 permit
|
|
||||||
35.83.148.184 permit
|
35.83.148.184 permit
|
||||||
35.155.198.111 permit
|
35.155.198.111 permit
|
||||||
35.158.23.94 permit
|
35.158.23.94 permit
|
||||||
@@ -173,7 +181,6 @@
|
|||||||
35.205.92.9 permit
|
35.205.92.9 permit
|
||||||
35.228.216.85 permit
|
35.228.216.85 permit
|
||||||
35.242.169.159 permit
|
35.242.169.159 permit
|
||||||
37.187.220.204 permit
|
|
||||||
37.188.97.188 permit
|
37.188.97.188 permit
|
||||||
37.218.248.47 permit
|
37.218.248.47 permit
|
||||||
37.218.249.47 permit
|
37.218.249.47 permit
|
||||||
@@ -186,7 +193,6 @@
|
|||||||
40.233.64.216 permit
|
40.233.64.216 permit
|
||||||
40.233.83.78 permit
|
40.233.83.78 permit
|
||||||
40.233.88.28 permit
|
40.233.88.28 permit
|
||||||
43.239.212.33 permit
|
|
||||||
44.206.138.57 permit
|
44.206.138.57 permit
|
||||||
44.210.169.44 permit
|
44.210.169.44 permit
|
||||||
44.217.45.156 permit
|
44.217.45.156 permit
|
||||||
@@ -247,8 +253,8 @@
|
|||||||
46.228.39.112/31 permit
|
46.228.39.112/31 permit
|
||||||
46.243.88.174 permit
|
46.243.88.174 permit
|
||||||
46.243.88.175 permit
|
46.243.88.175 permit
|
||||||
46.243.88.176/30 permit
|
46.243.88.176 permit
|
||||||
46.243.95.96/27 permit
|
46.243.88.177 permit
|
||||||
46.243.95.179 permit
|
46.243.95.179 permit
|
||||||
46.243.95.180 permit
|
46.243.95.180 permit
|
||||||
50.16.246.183 permit
|
50.16.246.183 permit
|
||||||
@@ -266,11 +272,9 @@
|
|||||||
50.56.130.221 permit
|
50.56.130.221 permit
|
||||||
50.56.130.222 permit
|
50.56.130.222 permit
|
||||||
50.112.246.219 permit
|
50.112.246.219 permit
|
||||||
50.152.146.25 permit
|
|
||||||
51.83.17.38 permit
|
51.83.17.38 permit
|
||||||
52.1.14.157 permit
|
52.1.14.157 permit
|
||||||
52.5.230.59 permit
|
52.5.230.59 permit
|
||||||
52.6.74.205 permit
|
|
||||||
52.12.53.23 permit
|
52.12.53.23 permit
|
||||||
52.13.214.179 permit
|
52.13.214.179 permit
|
||||||
52.26.1.71 permit
|
52.26.1.71 permit
|
||||||
@@ -327,7 +331,6 @@
|
|||||||
54.244.54.130 permit
|
54.244.54.130 permit
|
||||||
54.244.242.0/24 permit
|
54.244.242.0/24 permit
|
||||||
54.255.61.23 permit
|
54.255.61.23 permit
|
||||||
56.124.6.228 permit
|
|
||||||
57.103.64.0/18 permit
|
57.103.64.0/18 permit
|
||||||
57.129.93.249 permit
|
57.129.93.249 permit
|
||||||
62.13.128.0/24 permit
|
62.13.128.0/24 permit
|
||||||
@@ -394,7 +397,6 @@
|
|||||||
65.110.161.77 permit
|
65.110.161.77 permit
|
||||||
65.123.29.213 permit
|
65.123.29.213 permit
|
||||||
65.123.29.220 permit
|
65.123.29.220 permit
|
||||||
65.154.166.0/24 permit
|
|
||||||
65.212.180.36 permit
|
65.212.180.36 permit
|
||||||
66.102.0.0/20 permit
|
66.102.0.0/20 permit
|
||||||
66.119.150.192/26 permit
|
66.119.150.192/26 permit
|
||||||
@@ -638,7 +640,6 @@
|
|||||||
79.135.106.0/24 permit
|
79.135.106.0/24 permit
|
||||||
79.135.107.0/24 permit
|
79.135.107.0/24 permit
|
||||||
80.225.160.128/25 permit
|
80.225.160.128/25 permit
|
||||||
81.88.38.0/23 permit
|
|
||||||
81.169.146.243 permit
|
81.169.146.243 permit
|
||||||
81.169.146.245 permit
|
81.169.146.245 permit
|
||||||
81.169.146.246 permit
|
81.169.146.246 permit
|
||||||
@@ -723,7 +724,6 @@
|
|||||||
96.43.148.64/28 permit
|
96.43.148.64/28 permit
|
||||||
96.43.148.64/31 permit
|
96.43.148.64/31 permit
|
||||||
96.43.151.64/28 permit
|
96.43.151.64/28 permit
|
||||||
98.77.0.0/16 permit
|
|
||||||
98.97.248.0/21 permit
|
98.97.248.0/21 permit
|
||||||
98.136.44.181 permit
|
98.136.44.181 permit
|
||||||
98.136.44.182/31 permit
|
98.136.44.182/31 permit
|
||||||
@@ -1210,15 +1210,14 @@
|
|||||||
99.78.197.208/28 permit
|
99.78.197.208/28 permit
|
||||||
103.9.96.0/22 permit
|
103.9.96.0/22 permit
|
||||||
103.28.42.0/24 permit
|
103.28.42.0/24 permit
|
||||||
103.84.217.15 permit
|
|
||||||
103.84.217.238 permit
|
|
||||||
103.89.75.238 permit
|
|
||||||
103.151.192.0/23 permit
|
103.151.192.0/23 permit
|
||||||
103.168.172.128/27 permit
|
103.168.172.128/27 permit
|
||||||
103.237.104.0/22 permit
|
103.237.104.0/22 permit
|
||||||
104.43.243.237 permit
|
104.43.243.237 permit
|
||||||
104.44.112.128/25 permit
|
104.44.112.128/25 permit
|
||||||
104.47.0.0/17 permit
|
104.47.0.0/17 permit
|
||||||
|
104.130.96.0/28 permit
|
||||||
|
104.130.122.0/23 permit
|
||||||
106.10.144.64/27 permit
|
106.10.144.64/27 permit
|
||||||
106.10.144.100/31 permit
|
106.10.144.100/31 permit
|
||||||
106.10.144.103 permit
|
106.10.144.103 permit
|
||||||
@@ -1371,10 +1370,6 @@
|
|||||||
117.120.16.0/21 permit
|
117.120.16.0/21 permit
|
||||||
119.42.242.52/31 permit
|
119.42.242.52/31 permit
|
||||||
119.42.242.156 permit
|
119.42.242.156 permit
|
||||||
121.244.91.31 permit
|
|
||||||
121.244.91.48 permit
|
|
||||||
121.244.91.52 permit
|
|
||||||
122.15.156.182 permit
|
|
||||||
123.126.78.64/29 permit
|
123.126.78.64/29 permit
|
||||||
124.108.96.24/31 permit
|
124.108.96.24/31 permit
|
||||||
124.108.96.28/31 permit
|
124.108.96.28/31 permit
|
||||||
@@ -1440,7 +1435,6 @@
|
|||||||
130.35.116.0/25 permit
|
130.35.116.0/25 permit
|
||||||
130.61.9.72 permit
|
130.61.9.72 permit
|
||||||
130.162.39.83 permit
|
130.162.39.83 permit
|
||||||
130.162.194.23 permit
|
|
||||||
130.248.172.0/24 permit
|
130.248.172.0/24 permit
|
||||||
130.248.173.0/24 permit
|
130.248.173.0/24 permit
|
||||||
131.186.12.0/25 permit
|
131.186.12.0/25 permit
|
||||||
@@ -1458,21 +1452,7 @@
|
|||||||
134.170.141.64/26 permit
|
134.170.141.64/26 permit
|
||||||
134.170.143.0/24 permit
|
134.170.143.0/24 permit
|
||||||
134.170.174.0/24 permit
|
134.170.174.0/24 permit
|
||||||
135.84.80.0/24 permit
|
|
||||||
135.84.81.0/24 permit
|
|
||||||
135.84.82.0/24 permit
|
|
||||||
135.84.83.0/24 permit
|
|
||||||
135.84.216.0/22 permit
|
135.84.216.0/22 permit
|
||||||
136.143.160.0/24 permit
|
|
||||||
136.143.161.0/24 permit
|
|
||||||
136.143.162.0/24 permit
|
|
||||||
136.143.176.0/24 permit
|
|
||||||
136.143.177.0/24 permit
|
|
||||||
136.143.178.49 permit
|
|
||||||
136.143.182.0/23 permit
|
|
||||||
136.143.184.0/24 permit
|
|
||||||
136.143.188.0/24 permit
|
|
||||||
136.143.190.0/23 permit
|
|
||||||
136.146.128.0/20 permit
|
136.146.128.0/20 permit
|
||||||
136.147.128.0/20 permit
|
136.147.128.0/20 permit
|
||||||
136.147.135.0/24 permit
|
136.147.135.0/24 permit
|
||||||
@@ -1492,7 +1472,6 @@
|
|||||||
139.138.46.219 permit
|
139.138.46.219 permit
|
||||||
139.138.57.55 permit
|
139.138.57.55 permit
|
||||||
139.138.58.119 permit
|
139.138.58.119 permit
|
||||||
139.167.79.86 permit
|
|
||||||
139.177.108.0/25 permit
|
139.177.108.0/25 permit
|
||||||
139.180.17.0/24 permit
|
139.180.17.0/24 permit
|
||||||
140.238.148.191 permit
|
140.238.148.191 permit
|
||||||
@@ -1524,6 +1503,9 @@
|
|||||||
146.20.14.105 permit
|
146.20.14.105 permit
|
||||||
146.20.14.106 permit
|
146.20.14.106 permit
|
||||||
146.20.14.107 permit
|
146.20.14.107 permit
|
||||||
|
146.20.112.0/26 permit
|
||||||
|
146.20.113.0/24 permit
|
||||||
|
146.20.191.0/24 permit
|
||||||
146.20.215.0/24 permit
|
146.20.215.0/24 permit
|
||||||
146.20.215.182 permit
|
146.20.215.182 permit
|
||||||
146.88.28.0/24 permit
|
146.88.28.0/24 permit
|
||||||
@@ -1550,7 +1532,6 @@
|
|||||||
150.230.98.160 permit
|
150.230.98.160 permit
|
||||||
151.145.38.14 permit
|
151.145.38.14 permit
|
||||||
152.67.105.195 permit
|
152.67.105.195 permit
|
||||||
152.69.165.251 permit
|
|
||||||
152.69.200.236 permit
|
152.69.200.236 permit
|
||||||
152.70.155.126 permit
|
152.70.155.126 permit
|
||||||
155.248.135.128/25 permit
|
155.248.135.128/25 permit
|
||||||
@@ -1572,7 +1553,6 @@
|
|||||||
158.247.16.0/20 permit
|
158.247.16.0/20 permit
|
||||||
158.247.100.0/25 permit
|
158.247.100.0/25 permit
|
||||||
159.13.4.0/25 permit
|
159.13.4.0/25 permit
|
||||||
159.13.33.181 permit
|
|
||||||
159.92.154.0/24 permit
|
159.92.154.0/24 permit
|
||||||
159.92.155.0/24 permit
|
159.92.155.0/24 permit
|
||||||
159.92.157.0/24 permit
|
159.92.157.0/24 permit
|
||||||
@@ -1600,8 +1580,6 @@
|
|||||||
159.183.121.182 permit
|
159.183.121.182 permit
|
||||||
159.183.129.172 permit
|
159.183.129.172 permit
|
||||||
160.1.62.192 permit
|
160.1.62.192 permit
|
||||||
161.33.94.110 permit
|
|
||||||
161.33.228.244 permit
|
|
||||||
161.38.192.0/20 permit
|
161.38.192.0/20 permit
|
||||||
161.38.204.0/22 permit
|
161.38.204.0/22 permit
|
||||||
161.71.32.0/19 permit
|
161.71.32.0/19 permit
|
||||||
@@ -1633,6 +1611,7 @@
|
|||||||
165.173.182.0/24 permit
|
165.173.182.0/24 permit
|
||||||
165.173.182.250/31 permit
|
165.173.182.250/31 permit
|
||||||
165.173.189.205 permit
|
165.173.189.205 permit
|
||||||
|
166.78.68.0/22 permit
|
||||||
166.78.68.221 permit
|
166.78.68.221 permit
|
||||||
166.78.69.169 permit
|
166.78.69.169 permit
|
||||||
166.78.69.170 permit
|
166.78.69.170 permit
|
||||||
@@ -1664,19 +1643,6 @@
|
|||||||
168.245.12.252 permit
|
168.245.12.252 permit
|
||||||
168.245.46.9 permit
|
168.245.46.9 permit
|
||||||
168.245.127.231 permit
|
168.245.127.231 permit
|
||||||
169.148.129.0/24 permit
|
|
||||||
169.148.131.0/24 permit
|
|
||||||
169.148.138.0/24 permit
|
|
||||||
169.148.142.10 permit
|
|
||||||
169.148.142.33 permit
|
|
||||||
169.148.144.0/25 permit
|
|
||||||
169.148.144.10 permit
|
|
||||||
169.148.146.0/23 permit
|
|
||||||
169.148.174.10 permit
|
|
||||||
169.148.175.3 permit
|
|
||||||
169.148.179.3 permit
|
|
||||||
169.148.188.0/24 permit
|
|
||||||
169.148.188.182 permit
|
|
||||||
170.9.232.254 permit
|
170.9.232.254 permit
|
||||||
170.10.128.0/24 permit
|
170.10.128.0/24 permit
|
||||||
170.10.129.0/24 permit
|
170.10.129.0/24 permit
|
||||||
@@ -1787,9 +1753,9 @@
|
|||||||
188.125.85.234/31 permit
|
188.125.85.234/31 permit
|
||||||
188.125.85.236/31 permit
|
188.125.85.236/31 permit
|
||||||
188.125.85.238 permit
|
188.125.85.238 permit
|
||||||
|
188.165.51.139 permit
|
||||||
188.172.128.0/20 permit
|
188.172.128.0/20 permit
|
||||||
192.0.64.0/18 permit
|
192.0.64.0/18 permit
|
||||||
192.9.166.184 permit
|
|
||||||
192.18.139.154 permit
|
192.18.139.154 permit
|
||||||
192.18.145.36 permit
|
192.18.145.36 permit
|
||||||
192.18.152.58 permit
|
192.18.152.58 permit
|
||||||
@@ -1814,6 +1780,7 @@
|
|||||||
192.30.252.0/22 permit
|
192.30.252.0/22 permit
|
||||||
192.161.144.0/20 permit
|
192.161.144.0/20 permit
|
||||||
192.162.87.0/24 permit
|
192.162.87.0/24 permit
|
||||||
|
192.237.158.0/23 permit
|
||||||
192.237.159.42 permit
|
192.237.159.42 permit
|
||||||
192.237.159.43 permit
|
192.237.159.43 permit
|
||||||
192.254.112.0/20 permit
|
192.254.112.0/20 permit
|
||||||
@@ -1856,6 +1823,7 @@
|
|||||||
198.21.0.0/21 permit
|
198.21.0.0/21 permit
|
||||||
198.37.144.0/20 permit
|
198.37.144.0/20 permit
|
||||||
198.37.152.186 permit
|
198.37.152.186 permit
|
||||||
|
198.61.254.0/23 permit
|
||||||
198.61.254.21 permit
|
198.61.254.21 permit
|
||||||
198.61.254.231 permit
|
198.61.254.231 permit
|
||||||
198.178.234.57 permit
|
198.178.234.57 permit
|
||||||
@@ -1881,16 +1849,7 @@
|
|||||||
199.16.156.0/22 permit
|
199.16.156.0/22 permit
|
||||||
199.33.145.1 permit
|
199.33.145.1 permit
|
||||||
199.33.145.32 permit
|
199.33.145.32 permit
|
||||||
199.34.22.36 permit
|
|
||||||
199.59.148.0/22 permit
|
199.59.148.0/22 permit
|
||||||
199.67.80.2 permit
|
|
||||||
199.67.80.20 permit
|
|
||||||
199.67.82.2 permit
|
|
||||||
199.67.82.20 permit
|
|
||||||
199.67.84.0/24 permit
|
|
||||||
199.67.86.0/24 permit
|
|
||||||
199.67.88.0/24 permit
|
|
||||||
199.67.90.0/24 permit
|
|
||||||
199.101.161.130 permit
|
199.101.161.130 permit
|
||||||
199.101.162.0/25 permit
|
199.101.162.0/25 permit
|
||||||
199.122.120.0/21 permit
|
199.122.120.0/21 permit
|
||||||
@@ -1942,17 +1901,12 @@
|
|||||||
204.14.232.0/21 permit
|
204.14.232.0/21 permit
|
||||||
204.14.232.64/28 permit
|
204.14.232.64/28 permit
|
||||||
204.14.234.64/28 permit
|
204.14.234.64/28 permit
|
||||||
204.75.18.128/27 permit
|
|
||||||
204.75.142.0/24 permit
|
204.75.142.0/24 permit
|
||||||
204.92.114.187 permit
|
204.92.114.187 permit
|
||||||
204.92.114.203 permit
|
204.92.114.203 permit
|
||||||
204.92.114.204/31 permit
|
204.92.114.204/31 permit
|
||||||
204.141.32.0/23 permit
|
|
||||||
204.141.42.0/23 permit
|
|
||||||
204.216.164.202 permit
|
204.216.164.202 permit
|
||||||
204.220.90.0/23 permit
|
204.220.160.0/21 permit
|
||||||
204.220.92.0/22 permit
|
|
||||||
204.220.160.0/20 permit
|
|
||||||
204.220.168.0/21 permit
|
204.220.168.0/21 permit
|
||||||
204.220.176.0/20 permit
|
204.220.176.0/20 permit
|
||||||
204.220.181.105 permit
|
204.220.181.105 permit
|
||||||
@@ -1988,8 +1942,6 @@
|
|||||||
207.211.31.0/25 permit
|
207.211.31.0/25 permit
|
||||||
207.211.41.113 permit
|
207.211.41.113 permit
|
||||||
207.211.132.0/25 permit
|
207.211.132.0/25 permit
|
||||||
207.211.147.87 permit
|
|
||||||
207.211.159.110 permit
|
|
||||||
207.218.90.0/24 permit
|
207.218.90.0/24 permit
|
||||||
207.218.90.122 permit
|
207.218.90.122 permit
|
||||||
207.250.68.0/24 permit
|
207.250.68.0/24 permit
|
||||||
@@ -2039,6 +1991,7 @@
|
|||||||
209.43.22.0/28 permit
|
209.43.22.0/28 permit
|
||||||
209.46.117.168 permit
|
209.46.117.168 permit
|
||||||
209.46.117.179 permit
|
209.46.117.179 permit
|
||||||
|
209.61.151.0/24 permit
|
||||||
209.61.151.236 permit
|
209.61.151.236 permit
|
||||||
209.61.151.249 permit
|
209.61.151.249 permit
|
||||||
209.61.151.251 permit
|
209.61.151.251 permit
|
||||||
@@ -2225,7 +2178,7 @@
|
|||||||
2001:748:400:3301::4 permit
|
2001:748:400:3301::4 permit
|
||||||
2404:6800:4000::/36 permit
|
2404:6800:4000::/36 permit
|
||||||
2404:6800:4864::/56 permit
|
2404:6800:4864::/56 permit
|
||||||
2603:1061:14:102::1 permit
|
2603:1061:14:1c2::1 permit
|
||||||
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
|
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
|
||||||
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
|
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
|
||||||
2607:13c0:0004:0000:0000:0000:0000:0000/116 permit
|
2607:13c0:0004:0000:0000:0000:0000:0000/116 permit
|
||||||
|
|||||||
@@ -380,13 +380,13 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
else {
|
else {
|
||||||
$state = state_nomatch;
|
$state = state_nomatch;
|
||||||
}
|
}
|
||||||
$state .= '<br />' . htmlspecialchars($current[$data_field[$current['type']]]);
|
$state .= '<br />' . $current[$data_field[$current['type']]];
|
||||||
}
|
}
|
||||||
if ($current['type'] == 'TXT' &&
|
if ($current['type'] == 'TXT' &&
|
||||||
stripos($current['txt'], 'v=dmarc') === 0 &&
|
stripos($current['txt'], 'v=dmarc') === 0 &&
|
||||||
$record[2] == $dmarc_link) {
|
$record[2] == $dmarc_link) {
|
||||||
$current['txt'] = str_replace(' ', '', $current['txt']);
|
$current['txt'] = str_replace(' ', '', $current['txt']);
|
||||||
$state = htmlspecialchars($current[$data_field[$current['type']]]) . state_optional;
|
$state = $current[$data_field[$current['type']]] . state_optional;
|
||||||
}
|
}
|
||||||
elseif ($current['type'] == 'TXT' &&
|
elseif ($current['type'] == 'TXT' &&
|
||||||
stripos($current['txt'], 'v=spf') === 0 &&
|
stripos($current['txt'], 'v=spf') === 0 &&
|
||||||
@@ -396,7 +396,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
if (in_array($ip, $rslt) && in_array(expand_ipv6($ip6), $rslt)) {
|
if (in_array($ip, $rslt) && in_array(expand_ipv6($ip6), $rslt)) {
|
||||||
$state = state_good;
|
$state = state_good;
|
||||||
}
|
}
|
||||||
$state .= '<br />' . htmlspecialchars($current[$data_field[$current['type']]]) . state_optional;
|
$state .= '<br />' . $current[$data_field[$current['type']]] . state_optional;
|
||||||
}
|
}
|
||||||
elseif ($current['type'] == 'TXT' &&
|
elseif ($current['type'] == 'TXT' &&
|
||||||
stripos($current['txt'], 'v=dkim') === 0 &&
|
stripos($current['txt'], 'v=dkim') === 0 &&
|
||||||
@@ -426,7 +426,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
if ($state == state_nomatch) {
|
if ($state == state_nomatch) {
|
||||||
$state = array();
|
$state = array();
|
||||||
foreach ($currents as $current) {
|
foreach ($currents as $current) {
|
||||||
$state[] = htmlspecialchars($current[$data_field[$current['type']]]);
|
$state[] = $current[$data_field[$current['type']]];
|
||||||
}
|
}
|
||||||
$state = implode('<br />', $state);
|
$state = implode('<br />', $state);
|
||||||
}
|
}
|
||||||
@@ -436,22 +436,12 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
<td>%s</td>
|
<td>%s</td>
|
||||||
<td class="dns-found">%s</td>
|
<td class="dns-found">%s</td>
|
||||||
<td class="dns-recommended">%s</td>
|
<td class="dns-recommended">%s</td>
|
||||||
</tr>', htmlspecialchars($record[0]), htmlspecialchars($record[1]), $record[2], $state);
|
</tr>', $record[0], $record[1], $record[2], $state);
|
||||||
$record[3] = explode('<br />', $state);
|
$record[3] = explode('<br />', $state);
|
||||||
}
|
}
|
||||||
|
|
||||||
unset($record);
|
unset($record);
|
||||||
|
|
||||||
// Make a hostname RHS absolute so it is not read relative to $ORIGIN.
|
|
||||||
// Already-absolute names, the SRV root target "." and IP addresses are left alone.
|
|
||||||
$absolutize = function($host) {
|
|
||||||
$host = trim($host);
|
|
||||||
if ($host === '' || $host === '.' || substr($host, -1) === '.' || filter_var($host, FILTER_VALIDATE_IP)) {
|
|
||||||
return $host;
|
|
||||||
}
|
|
||||||
return $host . '.';
|
|
||||||
};
|
|
||||||
|
|
||||||
$dns_data = sprintf("\$ORIGIN %s.\n", $domain);
|
$dns_data = sprintf("\$ORIGIN %s.\n", $domain);
|
||||||
foreach ($records as $record) {
|
foreach ($records as $record) {
|
||||||
if ($domain == substr($record[0], -strlen($domain))) {
|
if ($domain == substr($record[0], -strlen($domain))) {
|
||||||
@@ -472,32 +462,22 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||||||
$val = str_replace(state_optional, '', $val);
|
$val = str_replace(state_optional, '', $val);
|
||||||
$val = str_replace(state_good, '', $val);
|
$val = str_replace(state_good, '', $val);
|
||||||
if (strlen($val) > 0) {
|
if (strlen($val) > 0) {
|
||||||
// these are all TXT values, their RHS is a character string, not a name
|
|
||||||
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
if ($record[1] == 'MX' || $record[1] == 'CNAME') {
|
|
||||||
$val = $absolutize($val);
|
|
||||||
}
|
|
||||||
elseif ($record[1] == 'SRV') {
|
|
||||||
// format here is "target port"; only the target is a name
|
|
||||||
$parts = explode(' ', $val, 2);
|
|
||||||
$parts[0] = $absolutize($parts[0]);
|
|
||||||
$val = implode(' ', $parts);
|
|
||||||
}
|
|
||||||
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
$vals[] = sprintf("%s\tIN\t%s\t%s\n", $label, $record[1], $val);
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach ($vals as $val) {
|
foreach ($vals as $val) {
|
||||||
$dns_data .= $val;
|
$dns_data .= str_replace($domain, $domain . '.', $val);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
?>
|
?>
|
||||||
</table>
|
</table>
|
||||||
<a id='download-zonefile' class="btn btn-sm btn-secondary visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline mb-4" style="margin-top:10px" data-zonefile="<?=base64_encode($dns_data);?>" download='<?=htmlspecialchars($_GET['domain']);?>.txt' type='text/csv'>Download</a>
|
<a id='download-zonefile' class="btn btn-sm btn-secondary visible-xs-block visible-sm-inline visible-md-inline visible-lg-inline mb-4" style="margin-top:10px" data-zonefile="<?=base64_encode($dns_data);?>" download='<?=$_GET['domain'];?>.txt' type='text/csv'>Download</a>
|
||||||
<script>
|
<script>
|
||||||
var zonefile_dl_link = document.getElementById('download-zonefile');
|
var zonefile_dl_link = document.getElementById('download-zonefile');
|
||||||
var zonefile = atob(zonefile_dl_link.getAttribute('data-zonefile'));
|
var zonefile = atob(zonefile_dl_link.getAttribute('data-zonefile'));
|
||||||
|
|||||||
@@ -591,7 +591,7 @@ function logger($_data = false) {
|
|||||||
$type = $return['type'];
|
$type = $return['type'];
|
||||||
$msg = null;
|
$msg = null;
|
||||||
if (isset($return['msg'])) {
|
if (isset($return['msg'])) {
|
||||||
$msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE | JSON_HEX_TAG | JSON_HEX_AMP | JSON_HEX_APOS | JSON_HEX_QUOT);
|
$msg = json_encode($return['msg'], JSON_UNESCAPED_UNICODE);
|
||||||
}
|
}
|
||||||
$call = null;
|
$call = null;
|
||||||
if (isset($return['log'])) {
|
if (isset($return['log'])) {
|
||||||
@@ -633,18 +633,6 @@ function logger($_data = false) {
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function is_local_mailcow_domain($domain) {
|
|
||||||
// True if domain is a locally managed, active primary or alias domain
|
|
||||||
global $pdo;
|
|
||||||
$domain = idn_to_ascii($domain, 0, INTL_IDNA_VARIANT_UTS46);
|
|
||||||
if (empty($domain)) {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$stmt = $pdo->prepare("SELECT 1 FROM `domain` WHERE `domain` = :d AND `active` = 1
|
|
||||||
UNION SELECT 1 FROM `alias_domain` WHERE `alias_domain` = :d2 AND `active` = 1 LIMIT 1");
|
|
||||||
$stmt->execute(array(':d' => $domain, ':d2' => $domain));
|
|
||||||
return (bool)$stmt->fetchColumn();
|
|
||||||
}
|
|
||||||
function hasDomainAccess($username, $role, $domain) {
|
function hasDomainAccess($username, $role, $domain) {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
if (empty($domain) || !is_valid_domain_name($domain)) {
|
if (empty($domain) || !is_valid_domain_name($domain)) {
|
||||||
@@ -3563,16 +3551,7 @@ function protect_route($allowed_roles = ['admin', 'domainadmin', 'user'], $redir
|
|||||||
if (isset($redirects['unauthenticated'])) {
|
if (isset($redirects['unauthenticated'])) {
|
||||||
header('Location: ' . $redirects['unauthenticated']);
|
header('Location: ' . $redirects['unauthenticated']);
|
||||||
} else {
|
} else {
|
||||||
// Send a deep link to the login page for its area instead of the user login at /,
|
header('Location: /');
|
||||||
// e.g. /admin/dashboard -> /admin rather than /
|
|
||||||
$request_uri = isset($_SERVER['REQUEST_URI']) ? $_SERVER['REQUEST_URI'] : '/';
|
|
||||||
if (strpos($request_uri, '/admin/') === 0) {
|
|
||||||
header('Location: /admin');
|
|
||||||
} elseif (strpos($request_uri, '/domainadmin/') === 0) {
|
|
||||||
header('Location: /domainadmin');
|
|
||||||
} else {
|
|
||||||
header('Location: /');
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
exit();
|
exit();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -750,18 +750,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
|
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
|
||||||
$goto_local_part = strstr($goto, '@', true);
|
$goto_local_part = strstr($goto, '@', true);
|
||||||
$goto = $goto_local_part.'@'.$goto_domain;
|
$goto = $goto_local_part.'@'.$goto_domain;
|
||||||
// Deny external goto domains: global switch (all roles) overrides the per-DA ACL
|
|
||||||
if (($GLOBALS['ALIAS_DISABLE_EXTERNAL_DOMAINS'] === true ||
|
|
||||||
(isset($_SESSION['acl']['alias_external_goto']) && $_SESSION['acl']['alias_external_goto'] != "1")) &&
|
|
||||||
!is_local_mailcow_domain($goto_domain)) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
|
||||||
'msg' => array('external_goto_denied', htmlspecialchars($goto))
|
|
||||||
);
|
|
||||||
unset($gotos[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
|
$stmt = $pdo->prepare("SELECT `username` FROM `mailbox`
|
||||||
WHERE `kind` REGEXP 'location|thing|group'
|
WHERE `kind` REGEXP 'location|thing|group'
|
||||||
AND `username`= :goto");
|
AND `username`= :goto");
|
||||||
@@ -2727,19 +2715,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
unset($gotos[$i]);
|
unset($gotos[$i]);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
// Deny external goto domains: global switch (all roles) overrides the per-DA ACL
|
|
||||||
$goto_domain = idn_to_ascii(substr(strstr($goto, '@'), 1), 0, INTL_IDNA_VARIANT_UTS46);
|
|
||||||
if (($GLOBALS['ALIAS_DISABLE_EXTERNAL_DOMAINS'] === true ||
|
|
||||||
(isset($_SESSION['acl']['alias_external_goto']) && $_SESSION['acl']['alias_external_goto'] != "1")) &&
|
|
||||||
!is_local_mailcow_domain($goto_domain)) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
|
||||||
'msg' => array('external_goto_denied', htmlspecialchars($goto))
|
|
||||||
);
|
|
||||||
unset($gotos[$i]);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
if ($goto == $address) {
|
if ($goto == $address) {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'danger',
|
'type' => 'danger',
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ function init_db_schema()
|
|||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "18082026_1200";
|
$db_version = "19022026_1220";
|
||||||
|
|
||||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||||
@@ -719,8 +719,7 @@ function init_db_schema()
|
|||||||
"alias_domains" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"alias_domains" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
"mailbox_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"mailbox_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"domain_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"domain_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"domain_desc" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"domain_desc" => "TINYINT(1) NOT NULL DEFAULT '0'"
|
||||||
"alias_external_goto" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
|
||||||
),
|
),
|
||||||
"keys" => array(
|
"keys" => array(
|
||||||
"primary" => array(
|
"primary" => array(
|
||||||
|
|||||||
@@ -246,10 +246,6 @@ $PW_RESET_TOKEN_LIMIT = 3;
|
|||||||
// Maximum time in minutes a password reset token is valid
|
// Maximum time in minutes a password reset token is valid
|
||||||
$PW_RESET_TOKEN_LIFETIME = 15;
|
$PW_RESET_TOKEN_LIFETIME = 15;
|
||||||
|
|
||||||
// Globally forbid aliases with external (non-local) goto domains for ALL roles (incl. admins),
|
|
||||||
// overriding the per-domain-admin da_acl. false = defer to da_acl.
|
|
||||||
$ALIAS_DISABLE_EXTERNAL_DOMAINS = false;
|
|
||||||
|
|
||||||
// UV flag handling in FIDO2/WebAuthn - defaults to false to allow iOS logins
|
// UV flag handling in FIDO2/WebAuthn - defaults to false to allow iOS logins
|
||||||
// true = required
|
// true = required
|
||||||
// false = preferred
|
// false = preferred
|
||||||
|
|||||||
@@ -1169,7 +1169,6 @@ jQuery(function($){
|
|||||||
if (item === null) { return true; }
|
if (item === null) { return true; }
|
||||||
item.user = escapeHtml(item.user);
|
item.user = escapeHtml(item.user);
|
||||||
item.call = escapeHtml(item.call);
|
item.call = escapeHtml(item.call);
|
||||||
if (item.msg) item.msg = escapeHtml(item.msg);
|
|
||||||
item.task = '<code>' + item.task + '</code>';
|
item.task = '<code>' + item.task + '</code>';
|
||||||
item.type = '<span class="badge fs-6 bg-' + item.type + '">' + item.type + '</span>';
|
item.type = '<span class="badge fs-6 bg-' + item.type + '">' + item.type + '</span>';
|
||||||
});
|
});
|
||||||
@@ -1177,7 +1176,6 @@ jQuery(function($){
|
|||||||
$.each(data, function (i, item) {
|
$.each(data, function (i, item) {
|
||||||
if (item === null) { return true; }
|
if (item === null) { return true; }
|
||||||
item.username = escapeHtml(item.username);
|
item.username = escapeHtml(item.username);
|
||||||
item.real_rip = escapeHtml(item.real_rip);
|
|
||||||
item.service = '<div class="badge fs-6 bg-secondary">' + item.service.toUpperCase() + '</div>';
|
item.service = '<div class="badge fs-6 bg-secondary">' + item.service.toUpperCase() + '</div>';
|
||||||
});
|
});
|
||||||
} else if (table == 'general_syslog') {
|
} else if (table == 'general_syslog') {
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"acl": {
|
"acl": {
|
||||||
"alias_domains": "Alias-Domains hinzufügen",
|
"alias_domains": "Alias-Domains hinzufügen",
|
||||||
"alias_external_goto": "Aliase mit externen Ziel-Domains erlauben",
|
|
||||||
"app_passwds": "App-Passwörter verwalten",
|
"app_passwds": "App-Passwörter verwalten",
|
||||||
"bcc_maps": "BCC-Maps",
|
"bcc_maps": "BCC-Maps",
|
||||||
"delimiter_action": "Delimiter-Aktionen (tags)",
|
"delimiter_action": "Delimiter-Aktionen (tags)",
|
||||||
@@ -444,7 +443,6 @@
|
|||||||
"domain_not_found": "Domain %s nicht gefunden",
|
"domain_not_found": "Domain %s nicht gefunden",
|
||||||
"domain_quota_m_in_use": "Domain-Speicherplatzlimit muss größer oder gleich %d MiB sein",
|
"domain_quota_m_in_use": "Domain-Speicherplatzlimit muss größer oder gleich %d MiB sein",
|
||||||
"extended_sender_acl_denied": "Keine Rechte zum Setzen von externen Absenderadressen",
|
"extended_sender_acl_denied": "Keine Rechte zum Setzen von externen Absenderadressen",
|
||||||
"external_goto_denied": "Externe Ziel-Adresse %s ist nicht erlaubt",
|
|
||||||
"extra_acl_invalid": "Externe Absenderadresse \"%s\" ist ungültig",
|
"extra_acl_invalid": "Externe Absenderadresse \"%s\" ist ungültig",
|
||||||
"extra_acl_invalid_domain": "Externe Absenderadresse \"%s\" verwendet eine ungültige Domain",
|
"extra_acl_invalid_domain": "Externe Absenderadresse \"%s\" verwendet eine ungültige Domain",
|
||||||
"fido2_verification_failed": "FIDO2-Verifizierung fehlgeschlagen: %s",
|
"fido2_verification_failed": "FIDO2-Verifizierung fehlgeschlagen: %s",
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
{
|
{
|
||||||
"acl": {
|
"acl": {
|
||||||
"alias_domains": "Add alias domains",
|
"alias_domains": "Add alias domains",
|
||||||
"alias_external_goto": "Allow aliases with external goto domains",
|
|
||||||
"app_passwds": "Manage app passwords",
|
"app_passwds": "Manage app passwords",
|
||||||
"bcc_maps": "BCC maps",
|
"bcc_maps": "BCC maps",
|
||||||
"delimiter_action": "Delimiter action",
|
"delimiter_action": "Delimiter action",
|
||||||
@@ -445,7 +444,6 @@
|
|||||||
"domain_not_found": "Domain %s not found",
|
"domain_not_found": "Domain %s not found",
|
||||||
"domain_quota_m_in_use": "Domain quota must be greater or equal to %s MiB",
|
"domain_quota_m_in_use": "Domain quota must be greater or equal to %s MiB",
|
||||||
"extended_sender_acl_denied": "missing ACL to set external sender addresses",
|
"extended_sender_acl_denied": "missing ACL to set external sender addresses",
|
||||||
"external_goto_denied": "External goto address %s is not allowed",
|
|
||||||
"extra_acl_invalid": "External sender address \"%s\" is invalid",
|
"extra_acl_invalid": "External sender address \"%s\" is invalid",
|
||||||
"extra_acl_invalid_domain": "External sender \"%s\" uses an invalid domain",
|
"extra_acl_invalid_domain": "External sender \"%s\" uses an invalid domain",
|
||||||
"fido2_verification_failed": "FIDO2 verification failed: %s",
|
"fido2_verification_failed": "FIDO2 verification failed: %s",
|
||||||
|
|||||||
@@ -109,10 +109,7 @@
|
|||||||
"bcc_dest_format": "Il destinatario in copia nascosta deve essere un singolo indirizzo email.<br>Se si vuole spedire una copia del messaggio a più destinatari, bisogna creare un alias ed utilizzarlo per questa opzione.",
|
"bcc_dest_format": "Il destinatario in copia nascosta deve essere un singolo indirizzo email.<br>Se si vuole spedire una copia del messaggio a più destinatari, bisogna creare un alias ed utilizzarlo per questa opzione.",
|
||||||
"app_passwd_protocols": "Protocolli consentiti per la password dell'app",
|
"app_passwd_protocols": "Protocolli consentiti per la password dell'app",
|
||||||
"tags": "Tag",
|
"tags": "Tag",
|
||||||
"dry": "Simula sincronizzazione",
|
"dry": "Simula sincronizzazione"
|
||||||
"internal": "Interno",
|
|
||||||
"internal_info": "Gli alias interni sono accessibili solo dal proprio dominio o dai domini alias.",
|
|
||||||
"sender_allowed": "Consenti l'invio con questo alias"
|
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "Accedi",
|
"access": "Accedi",
|
||||||
@@ -134,7 +131,7 @@
|
|||||||
"additional_rows": " righe aggiuntive inserite",
|
"additional_rows": " righe aggiuntive inserite",
|
||||||
"admin": "Amministratore",
|
"admin": "Amministratore",
|
||||||
"admin_details": "Modifica impostazioni amministratore",
|
"admin_details": "Modifica impostazioni amministratore",
|
||||||
"admin_domains": "Assegnazioni di dominio",
|
"admin_domains": "Assengazioni di dominio",
|
||||||
"admins": "Amministratori",
|
"admins": "Amministratori",
|
||||||
"admins_ldap": "Amministratori LDAP",
|
"admins_ldap": "Amministratori LDAP",
|
||||||
"advanced_settings": "Impostazioni avanzate",
|
"advanced_settings": "Impostazioni avanzate",
|
||||||
|
|||||||
@@ -786,8 +786,7 @@
|
|||||||
"mta_sts_mx_info": "Permite envio apenas para nomes de host de servidor de email explicitamente listados; o MTA de envio verifica se o nome do host DNS MX corresponde à lista de políticas e permite entrega apenas com certificado TLS válido (protege contra MITM).",
|
"mta_sts_mx_info": "Permite envio apenas para nomes de host de servidor de email explicitamente listados; o MTA de envio verifica se o nome do host DNS MX corresponde à lista de políticas e permite entrega apenas com certificado TLS válido (protege contra MITM).",
|
||||||
"mta_sts_mx_notice": "Múltiplos servidores MX podem ser especificados (separados por vírgulas).",
|
"mta_sts_mx_notice": "Múltiplos servidores MX podem ser especificados (separados por vírgulas).",
|
||||||
"sender_allowed": "Permitir enviar como este alias",
|
"sender_allowed": "Permitir enviar como este alias",
|
||||||
"sender_allowed_info": "Se desativado, este alias poderá apenas receber e-mails. Use a ACL de remetente para substituir essa configuração e conceder a caixas de correio específicas permissão para enviar.",
|
"sender_allowed_info": "Se desativado, este alias poderá apenas receber e-mails. Use a ACL de remetente para substituir essa configuração e conceder a caixas de correio específicas permissão para enviar."
|
||||||
"mta_sts_active_info": "Se esta opção estiver desmarcada, a política MTA-STS não será publicada e nenhum certificado será solicitado via ACME para o subdomínio mta-sts."
|
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"confirm": "Confirme",
|
"confirm": "Confirme",
|
||||||
@@ -1035,8 +1034,7 @@
|
|||||||
"weekly": "Semanalmente",
|
"weekly": "Semanalmente",
|
||||||
"yes": "✓",
|
"yes": "✓",
|
||||||
"iam": "Provedor de Identidade",
|
"iam": "Provedor de Identidade",
|
||||||
"internal": "Interno",
|
"internal": "Interno"
|
||||||
"force_tfa": "A2F"
|
|
||||||
},
|
},
|
||||||
"oauth2": {
|
"oauth2": {
|
||||||
"access_denied": "Faça login como proprietário da mailbox para conceder acesso via OAuth2.",
|
"access_denied": "Faça login como proprietário da mailbox para conceder acesso via OAuth2.",
|
||||||
@@ -1088,7 +1086,7 @@
|
|||||||
"rspamd_result": "Resultado do Rspamd",
|
"rspamd_result": "Resultado do Rspamd",
|
||||||
"sender": "Remetente (SMTP)",
|
"sender": "Remetente (SMTP)",
|
||||||
"sender_header": "Remetente (cabeçalho “De”)",
|
"sender_header": "Remetente (cabeçalho “De”)",
|
||||||
"settings_info": "Número máximo de elementos em quarentena (por caixa de correio): %s <br>Tamanho máximo do e-mail: %s MiB",
|
"settings_info": "Quantidade máxima de elementos a serem colocados em quarentena: %s <br>Tamanho máximo do e-mail: %s MiB",
|
||||||
"show_item": "Mostrar item",
|
"show_item": "Mostrar item",
|
||||||
"spam": "Spam",
|
"spam": "Spam",
|
||||||
"spam_score": "Ponto",
|
"spam_score": "Ponto",
|
||||||
|
|||||||
@@ -29,8 +29,7 @@
|
|||||||
"extend_sender_acl": "Dovoli razširitev pošiljateljevega ACL z zunanjimi e-poštnimi naslovi",
|
"extend_sender_acl": "Dovoli razširitev pošiljateljevega ACL z zunanjimi e-poštnimi naslovi",
|
||||||
"quarantine_category": "Spremeni kategorijo obvestil o karanteni",
|
"quarantine_category": "Spremeni kategorijo obvestil o karanteni",
|
||||||
"syncjobs": "Sinhronizacijska opravila",
|
"syncjobs": "Sinhronizacijska opravila",
|
||||||
"pw_reset": "Dovoli ponastavitev uporabniškega gesla mailcow",
|
"pw_reset": "Dovoli ponastavitev uporabniškega gesla mailcow"
|
||||||
"alias_external_goto": "Dovoli vzdevke z zunanjimi domenami goto"
|
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"active": "Aktivno",
|
"active": "Aktivno",
|
||||||
@@ -560,8 +559,7 @@
|
|||||||
"mx_invalid": "Zapis MX %s je neveljaven",
|
"mx_invalid": "Zapis MX %s je neveljaven",
|
||||||
"version_invalid": "Različica %s je neveljavna",
|
"version_invalid": "Različica %s je neveljavna",
|
||||||
"tfa_removal_blocked": "Dvofaktorske avtentikacije ni mogoče odstraniti, ker je obvezna za vaš račun.",
|
"tfa_removal_blocked": "Dvofaktorske avtentikacije ni mogoče odstraniti, ker je obvezna za vaš račun.",
|
||||||
"quarantine_category_invalid": "Kategorija karantene mora biti ena od: add_header, reject, all",
|
"quarantine_category_invalid": "Kategorija karantene mora biti ena od: add_header, reject, all"
|
||||||
"external_goto_denied": "Zunanji naslov goto %s ni dovoljen"
|
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"containers_info": "Informacije o zabojniku",
|
"containers_info": "Informacije o zabojniku",
|
||||||
@@ -787,8 +785,7 @@
|
|||||||
"internal": "Notranje",
|
"internal": "Notranje",
|
||||||
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.",
|
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.",
|
||||||
"sender_allowed": "Dovoli pošiljanje kot ta vzdevek",
|
"sender_allowed": "Dovoli pošiljanje kot ta vzdevek",
|
||||||
"sender_allowed_info": "Če je onemogočeno, lahko ta vzdevek samo prejema pošto. Za preglasitev in dodelitev dovoljenja za pošiljanje določenim poštnim predalom uporabite seznam za nadzor dostopa pošiljatelja.",
|
"sender_allowed_info": "Če je onemogočeno, lahko ta vzdevek samo prejema pošto. Za preglasitev in dodelitev dovoljenja za pošiljanje določenim poštnim predalom uporabite seznam za nadzor dostopa pošiljatelja."
|
||||||
"mta_sts_active_info": "Če ni označeno, pravilnik MTA-STS ne bo objavljen in za poddomeno mta-sts ne bo zahtevano nobeno potrdilo prek ACME."
|
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
"restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
|
"restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
|
||||||
@@ -1081,7 +1078,7 @@
|
|||||||
"rspamd_result": "Rezultat Rspamd",
|
"rspamd_result": "Rezultat Rspamd",
|
||||||
"sender": "Pošiljatelj (SMTP)",
|
"sender": "Pošiljatelj (SMTP)",
|
||||||
"sender_header": "Pošiljatelj (glava »Od«)",
|
"sender_header": "Pošiljatelj (glava »Od«)",
|
||||||
"settings_info": "Največje število elementov za karanteno (na poštni predal): %s<br>Največja velikost e-pošte: %s MiB",
|
"settings_info": "Največje število elementov za karanteno: %s<br>Največja velikost e-pošte: %s MiB",
|
||||||
"show_item": "Prikaži element",
|
"show_item": "Prikaži element",
|
||||||
"spam": "Neželena pošta",
|
"spam": "Neželena pošta",
|
||||||
"subj": "Zadeva",
|
"subj": "Zadeva",
|
||||||
|
|||||||
@@ -29,8 +29,7 @@
|
|||||||
"syncjobs": "同步任务",
|
"syncjobs": "同步任务",
|
||||||
"tls_policy": "TLS 策略",
|
"tls_policy": "TLS 策略",
|
||||||
"unlimited_quota": "无限邮箱容量配额",
|
"unlimited_quota": "无限邮箱容量配额",
|
||||||
"pw_reset": "允许重置mailcow使用者密码",
|
"pw_reset": "允许重置mailcow使用者密码"
|
||||||
"alias_external_goto": "允许带有外部目标地址的别名"
|
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"activate_filter_warn": "当“启用”选项被勾选后,其它所有的过滤器都会被禁用。",
|
"activate_filter_warn": "当“启用”选项被勾选后,其它所有的过滤器都会被禁用。",
|
||||||
@@ -112,8 +111,7 @@
|
|||||||
"validation_success": "验证成功",
|
"validation_success": "验证成功",
|
||||||
"dry": "模拟同步(Dry run)",
|
"dry": "模拟同步(Dry run)",
|
||||||
"internal_info": "内部的别名只能在域内部或者别名域内部访问。",
|
"internal_info": "内部的别名只能在域内部或者别名域内部访问。",
|
||||||
"internal": "内部的",
|
"internal": "内部的"
|
||||||
"sender_allowed": "允许以该别名发送"
|
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "权限管理",
|
"access": "权限管理",
|
||||||
@@ -557,10 +555,7 @@
|
|||||||
"max_age_invalid": "最大有效时间 %s 无效",
|
"max_age_invalid": "最大有效时间 %s 无效",
|
||||||
"mode_invalid": "模式 %s 无效",
|
"mode_invalid": "模式 %s 无效",
|
||||||
"mx_invalid": "MX 记录 %s 无效",
|
"mx_invalid": "MX 记录 %s 无效",
|
||||||
"version_invalid": "版本 %s 无效",
|
"version_invalid": "版本 %s 无效"
|
||||||
"tfa_removal_blocked": "无法移除两步验证,你的账户必须使用两步验证。",
|
|
||||||
"external_goto_denied": "不允许使用外部目标地址 %s",
|
|
||||||
"quarantine_category_invalid": "隔离分类必须是 add_header, reject, all 的其中一个"
|
|
||||||
},
|
},
|
||||||
"debug": {
|
"debug": {
|
||||||
"chart_this_server": "图表 (此服务器)",
|
"chart_this_server": "图表 (此服务器)",
|
||||||
@@ -759,10 +754,7 @@
|
|||||||
"mta_sts_max_age_info": "接收方邮件服务器可缓存该策略的时长(秒),超出后需重新获取策略。",
|
"mta_sts_max_age_info": "接收方邮件服务器可缓存该策略的时长(秒),超出后需重新获取策略。",
|
||||||
"mta_sts_mx": "MX 服务器",
|
"mta_sts_mx": "MX 服务器",
|
||||||
"mta_sts_mx_info": "仅允许向明确列出的邮件服务器发送邮件;发送方 MTA 会验证 DNS MX 记录的主机名是否与策略列表匹配,并仅允许携带有效 TLS 证书的投递(可防范中间人攻击)。",
|
"mta_sts_mx_info": "仅允许向明确列出的邮件服务器发送邮件;发送方 MTA 会验证 DNS MX 记录的主机名是否与策略列表匹配,并仅允许携带有效 TLS 证书的投递(可防范中间人攻击)。",
|
||||||
"mta_sts_mx_notice": "可配置多个 MX 服务器(以逗号分隔)。",
|
"mta_sts_mx_notice": "可配置多个 MX 服务器(以逗号分隔)。"
|
||||||
"sender_allowed": "允许以此别名发送",
|
|
||||||
"sender_allowed_info": "如果禁用了,此别名只能接收邮件。使用发件者 ACL 来覆盖此选项并赋予指定的邮箱发送权限。",
|
|
||||||
"mta_sts_active_info": "如果未选中,MTA-STS 策略不会被公布并且不会通过 ACME 为 MTA-STS 子域名请求证书。"
|
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"confirm": "确认",
|
"confirm": "确认",
|
||||||
@@ -1010,8 +1002,7 @@
|
|||||||
"templates": "模板",
|
"templates": "模板",
|
||||||
"template": "模板",
|
"template": "模板",
|
||||||
"iam": "身份提供者(IDP)",
|
"iam": "身份提供者(IDP)",
|
||||||
"internal": "内部的",
|
"internal": "内部的"
|
||||||
"force_tfa": "两步验证"
|
|
||||||
},
|
},
|
||||||
"oauth2": {
|
"oauth2": {
|
||||||
"access_denied": "请作为邮箱所有者登录以使用 OAuth2 授权。",
|
"access_denied": "请作为邮箱所有者登录以使用 OAuth2 授权。",
|
||||||
@@ -1219,12 +1210,7 @@
|
|||||||
"waiting_usb_auth": "<i>等待 USB 设备中...</i><br><br>现在请触碰你的 WebAuthn USB 设备上的按钮。",
|
"waiting_usb_auth": "<i>等待 USB 设备中...</i><br><br>现在请触碰你的 WebAuthn USB 设备上的按钮。",
|
||||||
"waiting_usb_register": "<i>等待 USB 设备中...</i><br><br>请在上方输入你的密码并请触碰你的 WebAuthn USB 设备上的按钮以确认注册该 WebAuthn 设备。",
|
"waiting_usb_register": "<i>等待 USB 设备中...</i><br><br>请在上方输入你的密码并请触碰你的 WebAuthn USB 设备上的按钮以确认注册该 WebAuthn 设备。",
|
||||||
"yubi_otp": "Yubico OTP 认证",
|
"yubi_otp": "Yubico OTP 认证",
|
||||||
"authenticators": "验证器(Authenticators)",
|
"authenticators": "验证器(Authenticators)"
|
||||||
"force_tfa": "在登录时强制启用 2FA",
|
|
||||||
"force_tfa_info": "在访问面板前用户会被要求设置两步验证。",
|
|
||||||
"setup_title": "需要设置两步验证",
|
|
||||||
"setup_required": "你的账户需要设置两步验证。请添加一个两步验证方法以继续。",
|
|
||||||
"cancel_setup": "取消并注销"
|
|
||||||
},
|
},
|
||||||
"user": {
|
"user": {
|
||||||
"action": "操作",
|
"action": "操作",
|
||||||
@@ -1398,8 +1384,7 @@
|
|||||||
"overview": "概览",
|
"overview": "概览",
|
||||||
"expire_never": "永不过期",
|
"expire_never": "永不过期",
|
||||||
"forever": "永久",
|
"forever": "永久",
|
||||||
"spam_aliases_info": "垃圾邮件别名是一种临时电子邮件地址,可用于保护真实电子邮件地址。<br>还可以选择设置过期时间,以便在设定的时间后自动停用别名,从而有效地销毁被滥用或泄露的地址。",
|
"spam_aliases_info": "垃圾邮件别名是一种临时电子邮件地址,可用于保护真实电子邮件地址。<br>还可以选择设置过期时间,以便在设定的时间后自动停用别名,从而有效地销毁被滥用或泄露的地址。"
|
||||||
"pw_update_required": "你的账户需要修改一次密码。请设置一个新密码以继续。"
|
|
||||||
},
|
},
|
||||||
"warning": {
|
"warning": {
|
||||||
"cannot_delete_self": "不能删除已登录的用户",
|
"cannot_delete_self": "不能删除已登录的用户",
|
||||||
|
|||||||
@@ -4,7 +4,6 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
|||||||
if (!isset($_SESSION['mailcow_cc_role'])) {
|
if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||||
$_SESSION['oauth2_request'] = $_SERVER['REQUEST_URI'];
|
$_SESSION['oauth2_request'] = $_SERVER['REQUEST_URI'];
|
||||||
header('Location: /?oauth');
|
header('Location: /?oauth');
|
||||||
exit;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$request = OAuth2\Request::createFromGlobals();
|
$request = OAuth2\Request::createFromGlobals();
|
||||||
@@ -25,11 +24,6 @@ if (!isset($_POST['authorized'])) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (empty($_SESSION['mailcow_cc_username'])) {
|
|
||||||
header('Location: /?oauth');
|
|
||||||
exit;
|
|
||||||
}
|
|
||||||
|
|
||||||
// print the authorization code if the user has authorized your client
|
// print the authorization code if the user has authorized your client
|
||||||
$is_authorized = ($_POST['authorized'] == '1');
|
$is_authorized = ($_POST['authorized'] == '1');
|
||||||
$oauth2_server->handleAuthorizeRequest($request, $response, $is_authorized, $_SESSION['mailcow_cc_username']);
|
$oauth2_server->handleAuthorizeRequest($request, $response, $is_authorized, $_SESSION['mailcow_cc_username']);
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
||||||
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
||||||
<button type="button" class="input-group-text" style="cursor:pointer;" onclick="var i=document.getElementById('pass_user'),ic=this.querySelector('i');if(i.type==='password'){i.type='text';ic.className='bi bi-eye-slash';}else{i.type='password';ic.className='bi bi-eye';}" tabindex="-1" aria-label="Toggle password visibility"><i class="bi bi-eye"></i></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-between mt-4" style="position: relative">
|
<div class="d-flex justify-content-between mt-4" style="position: relative">
|
||||||
|
|||||||
@@ -473,10 +473,6 @@ function recursiveBase64StrToArrayBuffer(obj) {
|
|||||||
window.location.reload();
|
window.location.reload();
|
||||||
} else {
|
} else {
|
||||||
var msg = (data && data[0] && data[0].msg) ? data[0].msg : 'Password change failed.';
|
var msg = (data && data[0] && data[0].msg) ? data[0].msg : 'Password change failed.';
|
||||||
// the API returns raw language keys, resolve them like the alert box does
|
|
||||||
if (Object.prototype.hasOwnProperty.call(lang_danger, msg)) {
|
|
||||||
msg = lang_danger[msg];
|
|
||||||
}
|
|
||||||
$('#changePWAlert').show().text(msg);
|
$('#changePWAlert').show().text(msg);
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
|||||||
@@ -49,7 +49,6 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
||||||
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
||||||
<button type="button" class="input-group-text" style="cursor:pointer;" onclick="var i=document.getElementById('pass_user'),ic=this.querySelector('i');if(i.type==='password'){i.type='text';ic.className='bi bi-eye-slash';}else{i.type='password';ic.className='bi bi-eye';}" tabindex="-1" aria-label="Toggle password visibility"><i class="bi bi-eye"></i></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="d-flex justify-content-between mt-4" style="position: relative">
|
<div class="d-flex justify-content-between mt-4" style="position: relative">
|
||||||
|
|||||||
@@ -267,7 +267,6 @@
|
|||||||
<small class="text-muted">{{ lang.admin.password_reset_info }}</small>
|
<small class="text-muted">{{ lang.admin.password_reset_info }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% endif %}
|
|
||||||
<div data-acl="{{ acl.extend_sender_acl }}" class="row mb-4">
|
<div data-acl="{{ acl.extend_sender_acl }}" class="row mb-4">
|
||||||
<label class="control-label col-sm-2" for="extended_sender_acl">{{ lang.edit.extended_sender_acl }}</label>
|
<label class="control-label col-sm-2" for="extended_sender_acl">{{ lang.edit.extended_sender_acl }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
@@ -280,6 +279,7 @@
|
|||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
{% endif %}
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<label class="control-label col-sm-2" for="protocol_access">{{ lang.edit.allowed_protocols }}</label>
|
<label class="control-label col-sm-2" for="protocol_access">{{ lang.edit.allowed_protocols }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
|
|||||||
@@ -56,7 +56,6 @@
|
|||||||
<div class="input-group">
|
<div class="input-group">
|
||||||
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
<div class="input-group-text"><i class="bi bi-lock-fill"></i></div>
|
||||||
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
<input name="pass_user" type="password" id="pass_user" class="form-control" placeholder="{{ lang.login.password }}" required="" autocomplete="current-password">
|
||||||
<button type="button" class="input-group-text" style="cursor:pointer;" onclick="var i=document.getElementById('pass_user'),ic=this.querySelector('i');if(i.type==='password'){i.type='text';ic.className='bi bi-eye-slash';}else{i.type='password';ic.className='bi bi-eye';}" tabindex="-1" aria-label="Toggle password visibility"><i class="bi bi-eye"></i></button>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 text-muted" style="font-size: 0.9rem;">
|
<div class="mt-2 text-muted" style="font-size: 0.9rem;">
|
||||||
|
|||||||
+4
-4
@@ -42,7 +42,7 @@ services:
|
|||||||
- mysql
|
- mysql
|
||||||
|
|
||||||
redis-mailcow:
|
redis-mailcow:
|
||||||
image: redis:7.4.10-alpine
|
image: redis:7.4.6-alpine
|
||||||
entrypoint: ["/bin/sh","/redis-conf.sh"]
|
entrypoint: ["/bin/sh","/redis-conf.sh"]
|
||||||
volumes:
|
volumes:
|
||||||
- redis-vol-1:/data/
|
- redis-vol-1:/data/
|
||||||
@@ -65,7 +65,7 @@ services:
|
|||||||
- redis
|
- redis
|
||||||
|
|
||||||
clamd-mailcow:
|
clamd-mailcow:
|
||||||
image: ghcr.io/mailcow/clamd:1.4.6-1
|
image: ghcr.io/mailcow/clamd:1.71
|
||||||
restart: always
|
restart: always
|
||||||
depends_on:
|
depends_on:
|
||||||
unbound-mailcow:
|
unbound-mailcow:
|
||||||
@@ -200,7 +200,7 @@ services:
|
|||||||
- phpfpm
|
- phpfpm
|
||||||
|
|
||||||
sogo-mailcow:
|
sogo-mailcow:
|
||||||
image: ghcr.io/mailcow/sogo:5.12.10-1
|
image: ghcr.io/mailcow/sogo:5.12.9-1
|
||||||
environment:
|
environment:
|
||||||
- DBNAME=${DBNAME}
|
- DBNAME=${DBNAME}
|
||||||
- DBUSER=${DBUSER}
|
- DBUSER=${DBUSER}
|
||||||
@@ -382,7 +382,7 @@ services:
|
|||||||
- postfix
|
- postfix
|
||||||
|
|
||||||
postfix-tlspol-mailcow:
|
postfix-tlspol-mailcow:
|
||||||
image: ghcr.io/mailcow/postfix-tlspol:1.11.0
|
image: ghcr.io/mailcow/postfix-tlspol:1.8.23
|
||||||
depends_on:
|
depends_on:
|
||||||
unbound-mailcow:
|
unbound-mailcow:
|
||||||
condition: service_healthy
|
condition: service_healthy
|
||||||
|
|||||||
Reference in New Issue
Block a user