1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-13 18:10:26 +00:00

Compare commits

..

1 Commits

Author SHA1 Message Date
FreddleSpl0it a5590dac96 [SOGo] Add path compatibility symlink for custom theming 2026-03-11 08:50:36 +01:00
33 changed files with 106 additions and 1801 deletions
@@ -14,7 +14,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Mark/Close Stale Issues and Pull Requests 🗑️ - name: Mark/Close Stale Issues and Pull Requests 🗑️
uses: actions/stale@v10.3.0 uses: actions/stale@v10.2.0
with: with:
repo-token: ${{ secrets.STALE_ACTION_PAT }} repo-token: ${{ secrets.STALE_ACTION_PAT }}
days-before-stale: 60 days-before-stale: 60
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Run the Action - name: Run the Action
uses: devops-infra/action-pull-request@v1.2.0 uses: devops-infra/action-pull-request@v1.0.2
with: with:
github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }} github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
title: Automatic PR to nightly from ${{ github.event.repository.updated_at}} title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}
+7 -38
View File
@@ -253,20 +253,10 @@ while true; do
unset VALIDATED_CONFIG_DOMAINS_SUBDOMAINS unset VALIDATED_CONFIG_DOMAINS_SUBDOMAINS
declare -a VALIDATED_CONFIG_DOMAINS_SUBDOMAINS declare -a VALIDATED_CONFIG_DOMAINS_SUBDOMAINS
for SUBDOMAIN in "${ADDITIONAL_WC_ARR[@]}"; do for SUBDOMAIN in "${ADDITIONAL_WC_ARR[@]}"; do
FULL_SUBDOMAIN="${SUBDOMAIN}.${SQL_DOMAIN}" if [[ "${SUBDOMAIN}.${SQL_DOMAIN}" != "${MAILCOW_HOSTNAME}" ]]; then
if check_domain "${SUBDOMAIN}.${SQL_DOMAIN}"; then
# Skip if subdomain matches MAILCOW_HOSTNAME VALIDATED_CONFIG_DOMAINS_SUBDOMAINS+=("${SUBDOMAIN}.${SQL_DOMAIN}")
if [[ "${FULL_SUBDOMAIN}" == "${MAILCOW_HOSTNAME}" ]]; then fi
continue
fi
# Skip if subdomain is covered by a wildcard in ADDITIONAL_SAN
if is_covered_by_wildcard "${FULL_SUBDOMAIN}"; then
log_f "Subdomain '${FULL_SUBDOMAIN}' is covered by wildcard - skipping explicit subdomain"
continue
fi
# Validate and add subdomain
if check_domain "${FULL_SUBDOMAIN}"; then
VALIDATED_CONFIG_DOMAINS_SUBDOMAINS+=("${FULL_SUBDOMAIN}")
fi fi
done done
VALIDATED_CONFIG_DOMAINS+=("${VALIDATED_CONFIG_DOMAINS_SUBDOMAINS[*]}") VALIDATED_CONFIG_DOMAINS+=("${VALIDATED_CONFIG_DOMAINS_SUBDOMAINS[*]}")
@@ -283,10 +273,7 @@ while true; do
fi fi
# Only add mta-sts subdomain for alias domains # Only add mta-sts subdomain for alias domains
if [[ "mta-sts.${alias_domain}" != "${MAILCOW_HOSTNAME}" ]]; then if [[ "mta-sts.${alias_domain}" != "${MAILCOW_HOSTNAME}" ]]; then
# Skip if mta-sts subdomain is covered by a wildcard if check_domain "mta-sts.${alias_domain}"; then
if is_covered_by_wildcard "mta-sts.${alias_domain}"; then
log_f "Alias domain mta-sts subdomain 'mta-sts.${alias_domain}' is covered by wildcard - skipping"
elif check_domain "mta-sts.${alias_domain}"; then
VALIDATED_CONFIG_DOMAINS+=("mta-sts.${alias_domain}") VALIDATED_CONFIG_DOMAINS+=("mta-sts.${alias_domain}")
fi fi
fi fi
@@ -321,31 +308,13 @@ while true; do
done done
fi fi
# Check if MAILCOW_HOSTNAME is covered by a wildcard in ADDITIONAL_SAN
MAILCOW_HOSTNAME_COVERED=0
if [[ ! -z ${VALIDATED_MAILCOW_HOSTNAME} ]]; then
if is_covered_by_wildcard "${VALIDATED_MAILCOW_HOSTNAME}"; then
MAILCOW_PARENT_DOMAIN=$(echo ${VALIDATED_MAILCOW_HOSTNAME} | cut -d. -f2-)
log_f "MAILCOW_HOSTNAME '${VALIDATED_MAILCOW_HOSTNAME}' is covered by wildcard '*.${MAILCOW_PARENT_DOMAIN}' - skipping explicit hostname"
MAILCOW_HOSTNAME_COVERED=1
fi
fi
# Unique domains for server certificate # Unique domains for server certificate
if [[ ${ENABLE_SSL_SNI} == "y" ]]; then if [[ ${ENABLE_SSL_SNI} == "y" ]]; then
# create certificate for server name and fqdn SANs only # create certificate for server name and fqdn SANs only
if [[ ${MAILCOW_HOSTNAME_COVERED} == "1" ]]; then SERVER_SAN_VALIDATED=(${VALIDATED_MAILCOW_HOSTNAME} $(echo ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
SERVER_SAN_VALIDATED=($(echo ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
else
SERVER_SAN_VALIDATED=(${VALIDATED_MAILCOW_HOSTNAME} $(echo ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
fi
else else
# create certificate for all domains, including all subdomains from other domains [*] # create certificate for all domains, including all subdomains from other domains [*]
if [[ ${MAILCOW_HOSTNAME_COVERED} == "1" ]]; then SERVER_SAN_VALIDATED=(${VALIDATED_MAILCOW_HOSTNAME} $(echo ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
SERVER_SAN_VALIDATED=($(echo ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
else
SERVER_SAN_VALIDATED=(${VALIDATED_MAILCOW_HOSTNAME} $(echo ${VALIDATED_CONFIG_DOMAINS[*]} ${ADDITIONAL_VALIDATED_SAN[*]} | xargs -n1 | sort -u | xargs))
fi
fi fi
if [[ ! -z ${SERVER_SAN_VALIDATED[*]} ]]; then if [[ ! -z ${SERVER_SAN_VALIDATED[*]} ]]; then
CERT_NAME=${SERVER_SAN_VALIDATED[0]} CERT_NAME=${SERVER_SAN_VALIDATED[0]}
-29
View File
@@ -135,32 +135,3 @@ verify_challenge_path(){
return 1 return 1
fi fi
} }
# Check if a domain is covered by a wildcard (*.example.com) in ADDITIONAL_SAN
# Usage: is_covered_by_wildcard "subdomain.example.com"
# Returns: 0 if covered, 1 if not covered
# Note: Only returns 0 (covered) when DNS-01 challenge is enabled,
# as wildcards cannot be validated with HTTP-01 challenge
is_covered_by_wildcard() {
local DOMAIN=$1
# Only skip if DNS challenge is enabled (wildcards require DNS-01)
if [[ ${ACME_DNS_CHALLENGE} != "y" ]]; then
return 1
fi
# Return early if no ADDITIONAL_SAN is set
if [[ -z ${ADDITIONAL_SAN} ]]; then
return 1
fi
# Extract parent domain (e.g., mail.example.com -> example.com)
local PARENT_DOMAIN=$(echo ${DOMAIN} | cut -d. -f2-)
# Check if ADDITIONAL_SAN contains a wildcard for this parent domain
if [[ "${ADDITIONAL_SAN}" == *"*.${PARENT_DOMAIN}"* ]]; then
return 0 # Covered by wildcard
fi
return 1 # Not covered
}
@@ -47,7 +47,7 @@ try:
if max_score == "": if max_score == "":
max_score = 9999.0 max_score = 9999.0
def query_mysql(query, params = None, headers = True, update = False): def query_mysql(query, headers = True, update = False):
while True: while True:
try: try:
cnx = MySQLdb.connect(user=os.environ.get('DBUSER'), password=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci") cnx = MySQLdb.connect(user=os.environ.get('DBUSER'), password=os.environ.get('DBPASS'), database=os.environ.get('DBNAME'), charset="utf8mb4", collation="utf8mb4_general_ci")
@@ -57,10 +57,7 @@ try:
else: else:
break break
cur = cnx.cursor() cur = cnx.cursor()
if params: cur.execute(query)
cur.execute(query, params)
else:
cur.execute(query)
if not update: if not update:
result = [] result = []
columns = tuple( [d[0] for d in cur.description] ) columns = tuple( [d[0] for d in cur.description] )
@@ -79,7 +76,7 @@ try:
def notify_rcpt(rcpt, msg_count, quarantine_acl, category): def notify_rcpt(rcpt, msg_count, quarantine_acl, category):
if category == "add_header": category = "add header" if category == "add_header": category = "add header"
meta_query = query_mysql('SELECT `qhash`, id, subject, score, sender, created, action FROM quarantine WHERE notified = 0 AND rcpt = %s AND score < %s AND (action = %s OR "all" = %s)', (rcpt, max_score, category, category)) meta_query = query_mysql('SELECT `qhash`, id, subject, score, sender, created, action FROM quarantine WHERE notified = 0 AND rcpt = "%s" AND score < %f AND (action = "%s" OR "all" = "%s")' % (rcpt, max_score, category, category))
print("%s: %d of %d messages qualify for notification" % (rcpt, len(meta_query), msg_count)) print("%s: %d of %d messages qualify for notification" % (rcpt, len(meta_query), msg_count))
if len(meta_query) == 0: if len(meta_query) == 0:
return return
@@ -133,7 +130,7 @@ try:
server.sendmail(msg['From'], [str(redirect)] + [str(bcc)], text) server.sendmail(msg['From'], [str(redirect)] + [str(bcc)], text)
server.quit() server.quit()
for res in meta_query: for res in meta_query:
query_mysql('UPDATE quarantine SET notified = 1 WHERE id = %s', (res['id'],), update = True) query_mysql('UPDATE quarantine SET notified = 1 WHERE id = "%d"' % (res['id']), update = True)
r.hset('Q_LAST_NOTIFIED', record['rcpt'], time_now) r.hset('Q_LAST_NOTIFIED', record['rcpt'], time_now)
break break
except Exception as ex: except Exception as ex:
@@ -141,7 +138,7 @@ try:
print('%s' % (ex)) print('%s' % (ex))
time.sleep(3) time.sleep(3)
records = query_mysql('SELECT IFNULL(user_acl.quarantine, 0) AS quarantine_acl, count(id) AS counter, rcpt FROM quarantine LEFT OUTER JOIN user_acl ON user_acl.username = rcpt WHERE notified = 0 AND score < %s AND rcpt in (SELECT username FROM mailbox) GROUP BY rcpt', (max_score,)) records = query_mysql('SELECT IFNULL(user_acl.quarantine, 0) AS quarantine_acl, count(id) AS counter, rcpt FROM quarantine LEFT OUTER JOIN user_acl ON user_acl.username = rcpt WHERE notified = 0 AND score < %f AND rcpt in (SELECT username FROM mailbox) GROUP BY rcpt' % (max_score))
for record in records: for record in records:
attrs = '' attrs = ''
@@ -159,7 +156,7 @@ try:
except Exception as ex: except Exception as ex:
print('Could not determine last notification for %s, assuming never' % (record['rcpt'])) print('Could not determine last notification for %s, assuming never' % (record['rcpt']))
last_notification = 0 last_notification = 0
attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = %s', (record['rcpt'],)) attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt']))
attrs = attrs_json[0]['attributes'] attrs = attrs_json[0]['attributes']
if isinstance(attrs, str): if isinstance(attrs, str):
# if attr is str then just load it # if attr is str then just load it
+1 -1
View File
@@ -1,4 +1,4 @@
FROM nginx:1.30.2-alpine FROM nginx:alpine
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
ENV PIP_BREAK_SYSTEM_PACKAGES=1 ENV PIP_BREAK_SYSTEM_PACKAGES=1
+7 -3
View File
@@ -1,6 +1,6 @@
# SOGo built from source to enable security patch application # SOGo built from source to enable security patch application
# Repository: https://github.com/Alinto/sogo # Repository: https://github.com/Alinto/sogo
# Version: SOGo-5.12.8 # Version: SOGo-5.12.5
# #
# Applied security patches: # Applied security patches:
# - # -
@@ -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.8 ARG SOGO_VERSION=SOGo-5.12.5
ARG SOPE_VERSION=SOPE-5.12.8 ARG SOPE_VERSION=SOPE-5.12.5
# 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>.*)$
@@ -161,6 +161,10 @@ RUN ln -s /usr/local/sbin/sogod /usr/sbin/sogod \
&& ln -s /usr/local/sbin/sogo-ealarms-notify /usr/sbin/sogo-ealarms-notify \ && ln -s /usr/local/sbin/sogo-ealarms-notify /usr/sbin/sogo-ealarms-notify \
&& ln -s /usr/local/sbin/sogo-slapd-sockd /usr/sbin/sogo-slapd-sockd && ln -s /usr/local/sbin/sogo-slapd-sockd /usr/sbin/sogo-slapd-sockd
# Create compatibility symlink for old SOGo documentation path
# Allows volume mounts using /usr/lib/GNUstep to work with /usr/local/lib/GNUstep
RUN ln -sf /usr/local/lib/GNUstep /usr/lib/GNUstep
# Copy configuration files and scripts # Copy configuration files and scripts
COPY ./bootstrap-sogo.sh /bootstrap-sogo.sh COPY ./bootstrap-sogo.sh /bootstrap-sogo.sh
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
+1 -4
View File
@@ -2,14 +2,11 @@ FROM alpine:3.23
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
# install unbound from alpine:edge to get security patches
RUN apk add --no-cache --repository=https://dl-cdn.alpinelinux.org/alpine/edge/main unbound
# install other packages from regular alpine stable repo
RUN apk add --update --no-cache \ RUN apk add --update --no-cache \
curl \ curl \
bind-tools \ bind-tools \
coreutils \ coreutils \
unbound \
bash \ bash \
openssl \ openssl \
drill \ drill \
+13 -88
View File
@@ -1,8 +1,7 @@
# Whitelist generated by Postwhite v3.4 on Fri May 1 00:43:37 UTC 2026 # Whitelist generated by Postwhite v3.4 on Sun Mar 1 00:29:01 UTC 2026
# https://github.com/stevejenkins/postwhite/ # https://github.com/stevejenkins/postwhite/
# 2249 total rules # 2174 total rules
2a00:1450:4000::/36 permit 2a00:1450:4000::/36 permit
2a00:1450:4864::/56 permit
2a01:111:f400::/48 permit 2a01:111:f400::/48 permit
2a01:111:f403:2800::/53 permit 2a01:111:f403:2800::/53 permit
2a01:111:f403:8000::/51 permit 2a01:111:f403:8000::/51 permit
@@ -32,11 +31,8 @@
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
2c0f:fb50:4864::/56 permit
2.207.151.32/27 permit
2.207.151.53 permit 2.207.151.53 permit
2.207.217.30 permit 2.207.217.30 permit
2.207.223.160/27 permit
3.64.237.68 permit 3.64.237.68 permit
3.65.3.180 permit 3.65.3.180 permit
3.70.123.177 permit 3.70.123.177 permit
@@ -62,8 +58,8 @@
8.40.222.0/23 permit 8.40.222.0/23 permit
8.40.222.250/31 permit 8.40.222.250/31 permit
12.130.86.238 permit 12.130.86.238 permit
13.107.213.40 permit 13.107.213.51 permit
13.107.246.40 permit 13.107.246.51 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
13.110.209.0/24 permit 13.110.209.0/24 permit
@@ -281,7 +277,6 @@
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
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.6.74.205 permit
@@ -373,7 +368,6 @@
64.132.88.0/23 permit 64.132.88.0/23 permit
64.132.92.0/24 permit 64.132.92.0/24 permit
64.181.194.190 permit 64.181.194.190 permit
64.181.213.254 permit
64.207.219.7 permit 64.207.219.7 permit
64.207.219.8 permit 64.207.219.8 permit
64.207.219.9 permit 64.207.219.9 permit
@@ -459,11 +453,7 @@
66.218.75.252/31 permit 66.218.75.252/31 permit
66.218.75.254 permit 66.218.75.254 permit
66.220.144.128/25 permit 66.220.144.128/25 permit
66.220.144.178 permit
66.220.144.179 permit
66.220.155.0/24 permit 66.220.155.0/24 permit
66.220.155.178 permit
66.220.155.179 permit
66.220.157.0/25 permit 66.220.157.0/25 permit
66.231.80.0/20 permit 66.231.80.0/20 permit
66.240.227.0/24 permit 66.240.227.0/24 permit
@@ -528,8 +518,6 @@
69.162.98.0/24 permit 69.162.98.0/24 permit
69.169.224.0/20 permit 69.169.224.0/20 permit
69.171.232.0/24 permit 69.171.232.0/24 permit
69.171.232.180 permit
69.171.232.181 permit
69.171.244.0/23 permit 69.171.244.0/23 permit
70.42.149.35 permit 70.42.149.35 permit
72.3.185.0/24 permit 72.3.185.0/24 permit
@@ -651,7 +639,6 @@
77.238.189.148/30 permit 77.238.189.148/30 permit
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
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
@@ -670,9 +657,6 @@
82.165.159.45 permit 82.165.159.45 permit
82.165.159.130 permit 82.165.159.130 permit
82.165.159.131 permit 82.165.159.131 permit
84.8.68.0/25 permit
84.8.192.128/25 permit
84.8.224.128/25 permit
85.9.206.169 permit 85.9.206.169 permit
85.9.210.45 permit 85.9.210.45 permit
85.158.136.0/21 permit 85.158.136.0/21 permit
@@ -1424,20 +1408,6 @@
129.146.88.28 permit 129.146.88.28 permit
129.146.147.105 permit 129.146.147.105 permit
129.146.236.58 permit 129.146.236.58 permit
129.148.135.0/25 permit
129.148.148.0/25 permit
129.148.164.0/25 permit
129.148.180.0/25 permit
129.148.215.0/25 permit
129.149.6.0/25 permit
129.149.22.0/25 permit
129.149.38.0/25 permit
129.149.52.0/25 permit
129.149.68.0/25 permit
129.149.84.0/25 permit
129.149.100.0/25 permit
129.149.118.0/25 permit
129.149.126.0/25 permit
129.151.67.221 permit 129.151.67.221 permit
129.153.62.216 permit 129.153.62.216 permit
129.153.104.71 permit 129.153.104.71 permit
@@ -1450,19 +1420,16 @@
129.159.22.159 permit 129.159.22.159 permit
129.159.87.137 permit 129.159.87.137 permit
129.213.195.191 permit 129.213.195.191 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.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.253.30.0/24 permit 131.253.30.0/24 permit
131.253.121.0/26 permit 131.253.121.0/26 permit
132.145.13.209 permit 132.145.13.209 permit
132.226.26.225 permit 132.226.26.225 permit
132.226.49.32 permit 132.226.49.32 permit
132.226.56.24 permit 132.226.56.24 permit
134.98.248.128/25 permit
134.128.64.0/19 permit 134.128.64.0/19 permit
134.128.96.0/19 permit 134.128.96.0/19 permit
134.170.27.8 permit 134.170.27.8 permit
@@ -1493,10 +1460,6 @@
136.147.182.0/24 permit 136.147.182.0/24 permit
136.147.224.0/20 permit 136.147.224.0/20 permit
136.179.50.206 permit 136.179.50.206 permit
136.248.224.128/25 permit
136.248.232.128/25 permit
138.1.108.0/25 permit
138.1.170.0/24 permit
139.60.152.0/22 permit 139.60.152.0/22 permit
139.138.35.44 permit 139.138.35.44 permit
139.138.46.121 permit 139.138.46.121 permit
@@ -1505,7 +1468,6 @@
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.167.79.86 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
141.148.55.217 permit 141.148.55.217 permit
@@ -1544,9 +1506,6 @@
146.88.28.0/24 permit 146.88.28.0/24 permit
146.148.116.76 permit 146.148.116.76 permit
147.154.32.0/25 permit 147.154.32.0/25 permit
147.154.63.0/24 permit
147.154.126.0/24 permit
147.154.191.0/24 permit
147.243.1.47 permit 147.243.1.47 permit
147.243.1.48 permit 147.243.1.48 permit
147.243.1.153 permit 147.243.1.153 permit
@@ -1558,16 +1517,12 @@
149.72.234.184 permit 149.72.234.184 permit
149.72.248.236 permit 149.72.248.236 permit
149.97.173.180 permit 149.97.173.180 permit
149.118.160.128/25 permit
150.136.21.199 permit 150.136.21.199 permit
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.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.140.0/25 permit
155.248.148.0/25 permit
155.248.208.51 permit 155.248.208.51 permit
155.248.220.138 permit 155.248.220.138 permit
155.248.234.149 permit 155.248.234.149 permit
@@ -1576,14 +1531,10 @@
157.58.30.128/25 permit 157.58.30.128/25 permit
157.58.196.96/29 permit 157.58.196.96/29 permit
157.58.249.3 permit 157.58.249.3 permit
157.137.32.128/25 permit
157.137.96.128/25 permit
157.151.208.65 permit 157.151.208.65 permit
157.255.1.64/29 permit 157.255.1.64/29 permit
158.101.211.207 permit 158.101.211.207 permit
158.247.16.0/20 permit 158.247.16.0/20 permit
158.247.100.0/25 permit
159.13.4.0/25 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
@@ -1617,7 +1568,6 @@
161.71.64.0/20 permit 161.71.64.0/20 permit
162.88.4.0/23 permit 162.88.4.0/23 permit
162.88.8.0/24 permit 162.88.8.0/24 permit
162.88.24.0/23 permit
162.88.24.0/24 permit 162.88.24.0/24 permit
162.88.25.0/24 permit 162.88.25.0/24 permit
162.88.36.0/24 permit 162.88.36.0/24 permit
@@ -1635,12 +1585,10 @@
164.152.23.32 permit 164.152.23.32 permit
164.152.25.241 permit 164.152.25.241 permit
164.177.132.168/30 permit 164.177.132.168/30 permit
165.1.100.0/25 permit
165.173.128.0/24 permit 165.173.128.0/24 permit
165.173.180.1 permit 165.173.180.1 permit
165.173.180.250/31 permit 165.173.180.250/31 permit
165.173.182.250/31 permit 165.173.182.250/31 permit
165.173.189.205 permit
166.78.68.0/22 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
@@ -1659,12 +1607,9 @@
167.89.75.126 permit 167.89.75.126 permit
167.89.75.136 permit 167.89.75.136 permit
167.89.75.164 permit 167.89.75.164 permit
167.89.101.2 permit
167.89.101.192/28 permit
167.220.67.232/29 permit 167.220.67.232/29 permit
168.107.248.128/25 permit
168.110.160.128/25 permit
168.110.248.128/25 permit
168.129.184.128/25 permit
168.129.248.128/25 permit
168.138.5.36 permit 168.138.5.36 permit
168.138.73.51 permit 168.138.73.51 permit
168.138.77.31 permit 168.138.77.31 permit
@@ -1681,7 +1626,6 @@
169.148.144.0/25 permit 169.148.144.0/25 permit
169.148.144.10 permit 169.148.144.10 permit
169.148.146.0/23 permit 169.148.146.0/23 permit
169.148.174.10 permit
169.148.175.3 permit 169.148.175.3 permit
169.148.179.3 permit 169.148.179.3 permit
169.148.188.0/24 permit 169.148.188.0/24 permit
@@ -1801,24 +1745,8 @@
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
192.22.32.128/25 permit
192.22.96.128/25 permit
192.22.160.128/25 permit
192.22.224.128/25 permit
192.28.128.0/18 permit 192.28.128.0/18 permit
192.29.24.0/25 permit
192.29.44.0/25 permit
192.29.72.0/25 permit
192.29.88.0/25 permit
192.29.103.128/25 permit 192.29.103.128/25 permit
192.29.134.0/25 permit
192.29.151.128/25 permit
192.29.172.0/25 permit
192.29.178.0/25 permit
192.29.200.0/25 permit
192.29.216.0/25 permit
192.29.232.0/25 permit
192.29.248.0/25 permit
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
@@ -1826,6 +1754,11 @@
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
192.254.112.60 permit
192.254.112.98/31 permit
192.254.113.10 permit
192.254.113.101 permit
192.254.114.176 permit
193.109.254.0/23 permit 193.109.254.0/23 permit
193.122.128.100 permit 193.122.128.100 permit
193.123.56.63 permit 193.123.56.63 permit
@@ -1994,7 +1927,6 @@
207.211.30.128/25 permit 207.211.30.128/25 permit
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.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
@@ -2002,8 +1934,6 @@
208.43.21.28/30 permit 208.43.21.28/30 permit
208.43.21.64/29 permit 208.43.21.64/29 permit
208.43.21.72/30 permit 208.43.21.72/30 permit
208.56.9.224 permit
208.56.13.196 permit
208.64.132.0/22 permit 208.64.132.0/22 permit
208.71.40.63 permit 208.71.40.63 permit
208.71.40.64/31 permit 208.71.40.64/31 permit
@@ -2030,7 +1960,6 @@
208.71.42.214 permit 208.71.42.214 permit
208.72.249.240/29 permit 208.72.249.240/29 permit
208.75.120.0/22 permit 208.75.120.0/22 permit
208.76.62.0/23 permit
208.76.62.0/24 permit 208.76.62.0/24 permit
208.76.63.0/24 permit 208.76.63.0/24 permit
208.82.237.96/29 permit 208.82.237.96/29 permit
@@ -2191,7 +2120,6 @@
216.136.168.80/28 permit 216.136.168.80/28 permit
216.139.64.0/19 permit 216.139.64.0/19 permit
216.145.221.0/24 permit 216.145.221.0/24 permit
216.146.32.0/23 permit
216.146.32.0/24 permit 216.146.32.0/24 permit
216.146.33.0/24 permit 216.146.33.0/24 permit
216.198.0.0/18 permit 216.198.0.0/18 permit
@@ -2212,7 +2140,6 @@
223.165.120.0/23 permit 223.165.120.0/23 permit
2001:0868:0100:0600::/64 permit 2001:0868:0100:0600::/64 permit
2001:4860:4000::/36 permit 2001:4860:4000::/36 permit
2001:4860:4864::/56 permit
2001:748:100:40::2:0/112 permit 2001:748:100:40::2:0/112 permit
2001:748:400:1300::3 permit 2001:748:400:1300::3 permit
2001:748:400:1300::4 permit 2001:748:400:1300::4 permit
@@ -2230,13 +2157,10 @@
2001:748:400:3301::3 permit 2001:748:400:3301::3 permit
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
2603:1061:14:72::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
2607:f8b0:4000::/36 permit 2607:f8b0:4000::/36 permit
2607:f8b0:4864::/56 permit
2620:109:c003:104::/64 permit 2620:109:c003:104::/64 permit
2620:109:c003:104::215 permit 2620:109:c003:104::215 permit
2620:109:c006:104::/64 permit 2620:109:c006:104::/64 permit
@@ -2248,7 +2172,8 @@
2620:10d:c09c:400::8:1 permit 2620:10d:c09c:400::8:1 permit
2620:119:50c0:207::/64 permit 2620:119:50c0:207::/64 permit
2620:119:50c0:207::215 permit 2620:119:50c0:207::215 permit
2620:1ec:46::51 permit
2620:1ec:bdf::51 permit
2800:3f0:4000::/36 permit 2800:3f0:4000::/36 permit
2800:3f0:4864::/56 permit
49.12.4.251 permit # checks.mailcow.email 49.12.4.251 permit # checks.mailcow.email
2a01:4f8:c17:7906::10 permit # checks.mailcow.email 2a01:4f8:c17:7906::10 permit # checks.mailcow.email
-4
View File
@@ -287,8 +287,6 @@ function user_login($user, $pass, $extra = null){
return false; return false;
} }
$row['attributes'] = json_decode($row['attributes'], true);
// check for tfa authenticators // check for tfa authenticators
$authenticators = get_tfa($user); $authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) { if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
@@ -345,8 +343,6 @@ function user_login($user, $pass, $extra = null){
return false; return false;
} }
$row['attributes'] = json_decode($row['attributes'], true);
// check for tfa authenticators // check for tfa authenticators
$authenticators = get_tfa($user); $authenticators = get_tfa($user);
if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) { if (isset($authenticators['additional']) && is_array($authenticators['additional']) && count($authenticators['additional']) > 0 && !$is_internal) {
-8
View File
@@ -108,14 +108,6 @@ function fwdhost($_action, $_data = null) {
} }
break; break;
case 'delete': case 'delete':
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'access_denied'
);
return false;
}
$hosts = (array)$_data['forwardinghost']; $hosts = (array)$_data['forwardinghost'];
foreach ($hosts as $host) { foreach ($hosts as $host) {
try { try {
-39
View File
@@ -1111,21 +1111,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : 0; $relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : 0;
$quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']); $quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
$quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']); $quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
// Validate quarantine_category
if (!in_array($quarantine_category, array('add_header', 'reject', 'all'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'quarantine_category_invalid'
);
return false;
}
$quota_b = ($quota_m * 1048576); $quota_b = ($quota_m * 1048576);
$attribute_hash = (!empty($_data['attribute_hash'])) ? $_data['attribute_hash'] : ''; $attribute_hash = (!empty($_data['attribute_hash'])) ? $_data['attribute_hash'] : '';
if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){ if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){
$force_pw_update = 0; $force_pw_update = 0;
}
if ($authsource == 'generic-oidc'){
$force_tfa = 0; $force_tfa = 0;
} }
$mailbox_attrs = json_encode( $mailbox_attrs = json_encode(
@@ -1742,15 +1731,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler']); $attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler']);
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']); $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']); $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
// Validate quarantine_category
if (!in_array($attr["quarantine_category"], array('add_header', 'reject', 'all'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
'msg' => 'quarantine_category_invalid'
);
return false;
}
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
$attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : ""; $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : "";
$attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']); $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update']);
@@ -2080,14 +2060,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return false; return false;
} }
foreach ($usernames as $username) { foreach ($usernames as $username) {
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
continue;
}
if ($_data['spam_score'] == "default") { if ($_data['spam_score'] == "default") {
$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :username
AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')"); AND (`option` = 'lowspamlevel' OR `option` = 'highspamlevel')");
@@ -3154,8 +3126,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
} }
if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){ if (in_array($authsource, array('keycloak', 'generic-oidc', 'ldap'))){
$force_pw_update = 0; $force_pw_update = 0;
}
if ($authsource == 'generic-oidc'){
$force_tfa = 0; $force_tfa = 0;
} }
$pw_recovery_email = (isset($_data['pw_recovery_email']) && $authsource == 'mailcow') ? $_data['pw_recovery_email'] : $is_now['attributes']['recovery_email']; $pw_recovery_email = (isset($_data['pw_recovery_email']) && $authsource == 'mailcow') ? $_data['pw_recovery_email'] : $is_now['attributes']['recovery_email'];
@@ -3816,15 +3786,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : $is_now['tagged_mail_handler']; $attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : $is_now['tagged_mail_handler'];
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification']; $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category']; $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
// Validate quarantine_category
if (!in_array($attr["quarantine_category"], array('add_header', 'reject', 'all'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_extra),
'msg' => 'quarantine_category_invalid'
);
continue;
}
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame']; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];
$attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value']; $attr["rl_value"] = (!empty($_data['rl_value'])) ? $_data['rl_value'] : $is_now['rl_value'];
$attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update']; $attr["force_pw_update"] = isset($_data['force_pw_update']) ? intval($_data['force_pw_update']) : $is_now['force_pw_update'];
+1 -1
View File
@@ -89,7 +89,7 @@ $globalVariables = [
'app_links' => $app_links, 'app_links' => $app_links,
'app_links_processed' => $app_links_processed, 'app_links_processed' => $app_links_processed,
'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'), 'is_root_uri' => (parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) == '/'),
'uri' => parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) ?: '/', 'uri' => $_SERVER['REQUEST_URI'],
]; ];
foreach ($globalVariables as $globalVariableName => $globalVariableValue) { foreach ($globalVariables as $globalVariableName => $globalVariableValue) {
+1 -3
View File
@@ -13,9 +13,7 @@ $twig = new Environment($loader, [
// functions // functions
$twig->addFunction(new TwigFunction('query_string', function (array $params = []) { $twig->addFunction(new TwigFunction('query_string', function (array $params = []) {
$allowed = ['lang', 'mobileconfig']; return http_build_query(array_merge($_GET, $params));
$filtered = array_intersect_key($_GET, array_flip($allowed));
return http_build_query(array_merge($filtered, $params));
})); }));
$twig->addFunction(new TwigFunction('is_uri', function (string $uri, string $where = null) { $twig->addFunction(new TwigFunction('is_uri', function (string $uri, string $where = null) {
-1
View File
@@ -112,7 +112,6 @@ $AVAILABLE_LANGUAGES = array(
'sv-se' => 'Svenska (Swedish)', 'sv-se' => 'Svenska (Swedish)',
'tr-tr' => 'Türkçe (Turkish)', 'tr-tr' => 'Türkçe (Turkish)',
'uk-ua' => 'Українська (Ukrainian)', 'uk-ua' => 'Українська (Ukrainian)',
'uz-uz' => 'Oʻzbekcha (Uzbek)',
'vi-vn' => 'Tiếng Việt (Vietnamese)', 'vi-vn' => 'Tiếng Việt (Vietnamese)',
'zh-cn' => '简体中文 (Simplified Chinese)', 'zh-cn' => '简体中文 (Simplified Chinese)',
'zh-tw' => '繁體中文 (Traditional Chinese)', 'zh-tw' => '繁體中文 (Traditional Chinese)',
+2 -2
View File
@@ -345,7 +345,7 @@ $(document).ready(function() {
$('.main-logo-dark').addClass('d-none'); $('.main-logo-dark').addClass('d-none');
if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png'); if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_dark.png');
if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png'); if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_dark.png');
localStorage.setItem('mailcow_theme', 'light'); localStorage.setItem('theme', 'light');
}else{ }else{
$('head').append('<link id="dark-mode-theme" rel="stylesheet" type="text/css" href="/css/themes/mailcow-darkmode.css">'); $('head').append('<link id="dark-mode-theme" rel="stylesheet" type="text/css" href="/css/themes/mailcow-darkmode.css">');
$('#dark-mode-toggle').prop('checked', true); $('#dark-mode-toggle').prop('checked', true);
@@ -353,7 +353,7 @@ $(document).ready(function() {
$('.main-logo-dark').removeClass('d-none'); $('.main-logo-dark').removeClass('d-none');
if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png'); if ($('#rspamd_logo').length) $('#rspamd_logo').attr('src', '/img/rspamd_logo_light.png');
if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png'); if ($('#rspamd_logo_sm').length) $('#rspamd_logo_sm').attr('src', '/img/rspamd_logo_light.png');
localStorage.setItem('mailcow_theme', 'dark'); localStorage.setItem('theme', 'dark');
} }
} }
-5
View File
@@ -1128,11 +1128,6 @@ jQuery(function($){
item.ua = escapeHtml(item.ua); item.ua = escapeHtml(item.ua);
} }
item.ua = '<span style="font-size:small">' + item.ua + '</span>'; item.ua = '<span style="font-size:small">' + item.ua + '</span>';
if (item.user == null) {
item.user = 'unknown';
} else {
item.user = escapeHtml(item.user);
}
if (item.service == "activesync") { if (item.service == "activesync") {
item.service = '<span class="badge fs-6 bg-info">ActiveSync</span>'; item.service = '<span class="badge fs-6 bg-info">ActiveSync</span>';
} }
+3 -4
View File
@@ -1,6 +1,5 @@
$(document).ready(function() { $(document).ready(function() {
var theme = localStorage.getItem("mailcow_theme"); var theme = localStorage.getItem("theme");
if (theme !== null) { localStorage.clear();
localStorage.setItem("mailcow_theme", theme); localStorage.setItem("theme", theme);
}
}); });
+10 -14
View File
@@ -102,21 +102,18 @@ jQuery(function($){
{ {
title: 'ID', title: 'ID',
data: 'id', data: 'id',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang.qid, title: lang.qid,
data: 'qid', data: 'qid',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang.sender, title: lang.sender,
data: 'sender', data: 'sender',
className: 'senders-mw220', className: 'senders-mw220',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang.subj, title: lang.subj,
@@ -131,8 +128,7 @@ jQuery(function($){
{ {
title: lang.rcpt, title: lang.rcpt,
data: 'rcpt', data: 'rcpt',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang.danger, title: lang.danger,
@@ -230,18 +226,18 @@ jQuery(function($){
} }
if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) { if (typeof data.fuzzy_hashes === 'object' && data.fuzzy_hashes !== null && data.fuzzy_hashes.length !== 0) {
$.each(data.fuzzy_hashes, function (index, value) { $.each(data.fuzzy_hashes, function (index, value) {
$('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + escapeHtml(value) + '</p>'); $('#qid_detail_fuzzy').append('<p style="font-family:monospace">' + value + '</p>');
}); });
} else { } else {
$('#qid_detail_fuzzy').append('-'); $('#qid_detail_fuzzy').append('-');
} }
if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') { if (typeof data.score !== 'undefined' && typeof data.action !== 'undefined') {
if (data.action == "add header") { if (data.action == "add header") {
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + escapeHtml(data.score) + '</b> - ' + lang.junk_folder + '</span>'); $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.junk_folder + '</span>');
} else if (data.action == "reject") { } else if (data.action == "reject") {
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + escapeHtml(data.score) + '</b> - ' + lang.rejected + '</span>'); $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-danger"><b>' + data.score + '</b> - ' + lang.rejected + '</span>');
} else if (data.action == "rewrite subject") { } else if (data.action == "rewrite subject") {
$('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + escapeHtml(data.score) + '</b> - ' + lang.rewrite_subject + '</span>'); $('#qid_detail_score').append('<span class="label-rspamd-action badge fs-6 bg-warning"><b>' + data.score + '</b> - ' + lang.rewrite_subject + '</span>');
} }
} }
if (typeof data.recipients !== 'undefined') { if (typeof data.recipients !== 'undefined') {
@@ -258,8 +254,8 @@ jQuery(function($){
qAtts.text(''); qAtts.text('');
$.each(data.attachments, function(index, value) { $.each(data.attachments, function(index, value) {
qAtts.append( qAtts.append(
'<p><a href="/inc/ajax/qitem_details.php?id=' + escapeHtml(qitem) + '&amp;att=' + index + '" target="_blank">' + escapeHtml(value[0]) + '</a> (' + escapeHtml(value[1]) + ')' + '<p><a href="/inc/ajax/qitem_details.php?id=' + qitem + '&att=' + index + '" target="_blank">' + value[0] + '</a> (' + value[1] + ')' +
' - <small><a href="' + escapeHtml(value[3]) + '" target="_blank">' + lang.check_hash + '</a></small></p>' ' - <small><a href="' + value[3] + '" target="_blank">' + lang.check_hash + '</a></small></p>'
); );
}); });
} }
+5 -8
View File
@@ -48,13 +48,13 @@ jQuery(function($){
url: "/api/v1/get/mailq/all", url: "/api/v1/get/mailq/all",
dataSrc: function(data){ dataSrc: function(data){
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.chkbox = '<input type="checkbox" class="form-check-input" data-id="mailqitems" name="multi_select" value="' + escapeHtml(item.queue_id) + '" />'; item.chkbox = '<input type="checkbox" class="form-check-input" data-id="mailqitems" name="multi_select" value="' + item.queue_id + '" />';
rcpts = $.map(item.recipients, function(i) { rcpts = $.map(item.recipients, function(i) {
return escapeHtml(i); return escapeHtml(i);
}); });
item.recipients = rcpts.join('<hr style="margin:1px!important">'); item.recipients = rcpts.join('<hr style="margin:1px!important">');
item.action = '<div class="btn-group">' + item.action = '<div class="btn-group">' +
'<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + escapeHtml(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.show_message + '</a>' + '<a href="#" data-bs-toggle="modal" data-bs-target="#showQueuedMsg" data-queue-id="' + encodeURI(item.queue_id) + '" class="btn btn-xs btn-secondary">' + lang.show_message + '</a>' +
'</div>'; '</div>';
}); });
return data; return data;
@@ -79,14 +79,12 @@ jQuery(function($){
{ {
title: 'QID', title: 'QID',
data: 'queue_id', data: 'queue_id',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: 'Queue', title: 'Queue',
data: 'queue_name', data: 'queue_name',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang_admin.arrival_time, title: lang_admin.arrival_time,
@@ -108,8 +106,7 @@ jQuery(function($){
{ {
title: lang_admin.sender, title: lang_admin.sender,
data: 'sender', data: 'sender',
defaultContent: '', defaultContent: ''
render: $.fn.dataTable.render.text()
}, },
{ {
title: lang_admin.recipients, title: lang_admin.recipients,
+2 -2
View File
@@ -98,8 +98,8 @@ jQuery(function($){
var local_datetime = datetime.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"}); var local_datetime = datetime.toLocaleDateString(undefined, {year: "numeric", month: "2-digit", day: "2-digit", hour: "2-digit", minute: "2-digit", second: "2-digit"});
var service = '<div class="badge bg-secondary">' + item.service.toUpperCase() + '</div>'; var service = '<div class="badge bg-secondary">' + item.service.toUpperCase() + '</div>';
var app_password = item.app_password ? ' <a href="/edit/app-passwd/' + item.app_password + '"><i class="bi bi-key-fill"></i><span class="ms-1">' + escapeHtml(item.app_password_name || "App") + '</span></a>' : ''; var app_password = item.app_password ? ' <a href="/edit/app-passwd/' + item.app_password + '"><i class="bi bi-key-fill"></i><span class="ms-1">' + escapeHtml(item.app_password_name || "App") + '</span></a>' : '';
var real_rip = item.real_rip.startsWith("Web") ? escapeHtml(item.real_rip) : '<a href="https://bgp.tools/prefix/' + escapeHtml(item.real_rip) + '" target="_blank">' + escapeHtml(item.real_rip) + "</a>"; var real_rip = item.real_rip.startsWith("Web") ? item.real_rip : '<a href="https://bgp.tools/prefix/' + item.real_rip + '" target="_blank">' + item.real_rip + "</a>";
var ip_location = item.location ? ' <span class="flag-icon flag-icon-' + escapeHtml(item.location.toLowerCase()) + '"></span>' : ''; var ip_location = item.location ? ' <span class="flag-icon flag-icon-' + item.location.toLowerCase() + '"></span>' : '';
var ip_data = real_rip + ip_location + app_password; var ip_data = real_rip + ip_location + app_password;
$(".last-sasl-login").append(` $(".last-sasl-login").append(`
-17
View File
@@ -1,17 +0,0 @@
{
"acl": {
"login_as": "E-poçt qutusu istifadəçisi olaraq daxil ol",
"alias_domains": "Alternativ domenlər əlavə et",
"app_passwds": "Tətbiq parollarını idarə et",
"bcc_maps": "BCC yönləndirmə xəritələri",
"delimiter_action": "Ayırıcı əməliyyatı",
"domain_desc": "Domen təsvirini dəyiş",
"domain_relayhost": "Domen üçün relay serveri dəyiş",
"eas_reset": "EAS cihazlarını sıfırla",
"extend_sender_acl": "Göndərən ACL-ni xarici ünvanlarla genişləndirməyə icazə ver",
"filters": "Filtrlər",
"mailbox_relayhost": "E-poçt qutusu üçün relay serveri dəyiş",
"prohibited": "ACL tərəfindən məhdudlaşdırılıb",
"protocol_access": "Protokol girişini dəyiş"
}
}
-1
View File
@@ -512,7 +512,6 @@
"pushover_credentials_missing": "Pushover Token und/oder Key fehlen", "pushover_credentials_missing": "Pushover Token und/oder Key fehlen",
"pushover_key": "Pushover Key hat das falsche Format", "pushover_key": "Pushover Key hat das falsche Format",
"pushover_token": "Pushover Token hat das falsche Format", "pushover_token": "Pushover Token hat das falsche Format",
"quarantine_category_invalid": "Quarantäne-Kategorie muss eine der folgenden sein: add_header, reject, all",
"quota_not_0_not_numeric": "Speicherplatz muss numerisch und >= 0 sein", "quota_not_0_not_numeric": "Speicherplatz muss numerisch und >= 0 sein",
"recipient_map_entry_exists": "Eine Empfängerumschreibung für Objekt \"%s\" existiert bereits", "recipient_map_entry_exists": "Eine Empfängerumschreibung für Objekt \"%s\" existiert bereits",
"recovery_email_failed": "E-Mail zur Wiederherstellung konnte nicht gesendet werden. Bitte wenden Sie sich an Ihren Administrator.", "recovery_email_failed": "E-Mail zur Wiederherstellung konnte nicht gesendet werden. Bitte wenden Sie sich an Ihren Administrator.",
-1
View File
@@ -513,7 +513,6 @@
"pushover_credentials_missing": "Pushover token and or key missing", "pushover_credentials_missing": "Pushover token and or key missing",
"pushover_key": "Pushover key has a wrong format", "pushover_key": "Pushover key has a wrong format",
"pushover_token": "Pushover token has a wrong format", "pushover_token": "Pushover token has a wrong format",
"quarantine_category_invalid": "Quarantine category must be one of: add_header, reject, all",
"quota_not_0_not_numeric": "Quota must be numeric and >= 0", "quota_not_0_not_numeric": "Quota must be numeric and >= 0",
"recipient_map_entry_exists": "A Recipient map entry \"%s\" exists", "recipient_map_entry_exists": "A Recipient map entry \"%s\" exists",
"recovery_email_failed": "Could not send a recovery email. Please contact your administrator.", "recovery_email_failed": "Could not send a recovery email. Please contact your administrator.",
+2 -18
View File
@@ -1144,8 +1144,7 @@
"subscribeall": "Feliratkozás minden mappára", "subscribeall": "Feliratkozás minden mappára",
"syncjob": "Szinkronizálási feladat hozzáadása", "syncjob": "Szinkronizálási feladat hozzáadása",
"internal": "Belső", "internal": "Belső",
"internal_info": "Belső álnevek csak a saját domain vagy domain álnév számára elérhető.", "internal_info": "Belső álnevek csak a saját domain vagy domain álnév számára elérhető."
"sender_allowed": "Küldés engedélyezése ezzel az aliasszal"
}, },
"danger": { "danger": {
"access_denied": "Hozzáférés megtagatva vagy nem megfelelő űrlap adat", "access_denied": "Hozzáférés megtagatva vagy nem megfelelő űrlap adat",
@@ -1246,21 +1245,6 @@
"pushover_key": "A pushover kulcs rossz formátumú", "pushover_key": "A pushover kulcs rossz formátumú",
"pushover_token": "A Pushover token rossz formátumú", "pushover_token": "A Pushover token rossz formátumú",
"quota_not_0_not_numeric": "A kvótának numerikusnak és >= 0-nak kell lennie.", "quota_not_0_not_numeric": "A kvótának numerikusnak és >= 0-nak kell lennie.",
"recipient_map_entry_exists": "Létezik egy \"%s\" címzett-térkép bejegyzés", "recipient_map_entry_exists": "Létezik egy \"%s\" címzett-térkép bejegyzés"
"redis_error": "Redis hiba lépett fel: %s",
"relayhost_invalid": "A(z) %s elem érvénytelen a leképezésben.",
"release_send_failed": "Az üzenet felszabadítása sikertelen: %s",
"reset_f2b_regex": "A regex-szűrő időtúllépés miatt nem állt le. Próbálja újra, vagy várjon egy kicsit, és töltse újra az oldalt.",
"resource_invalid": "A(z) %s erőforrásnév érvénytelen",
"rl_timeframe": "Érvénytelen időkeret a lekérdezési korláthoz",
"rspamd_ui_pw_length": "A Rspamd UI jelszónak legalább 6 karakter hosszúnak kell lennie.",
"script_empty": "A szkript nem lehet üres",
"sender_acl_invalid": "A küldőhöz tartozó ACL-érték (%s) érvénytelen",
"set_acl_failed": "Az ACL beállítása meghiúsult",
"settings_map_invalid": "Érvénytelen beállítás-leképezési azonosító: %s",
"recovery_email_failed": "A helyreállítási email kiküldése sikertelen. Kérlek, lépj kapcsolatba az adminisztrátorral!",
"reset_token_limit_exceeded": "Túl sok visszaállítási kísérlet. Kérjük, várjon, mielőtt újra próbálkozna.",
"required_data_missing": "Hiányzik a(z) szükséges %s adat",
"tfa_removal_blocked": "A kétfaktoros hitelesítés nem távolítható el, mert elengedhetetlen a fiókod használatához."
} }
} }
+1 -2
View File
@@ -27,8 +27,7 @@
"tls_policy": "Versleutelingsbeleid", "tls_policy": "Versleutelingsbeleid",
"unlimited_quota": "Onbeperkte quota voor mailboxen", "unlimited_quota": "Onbeperkte quota voor mailboxen",
"domain_desc": "Wijzig domeinbeschrijving", "domain_desc": "Wijzig domeinbeschrijving",
"pw_reset": "Toegang om mailcow gebruikers wachtwoord te resetten", "pw_reset": "Toegang om mailcow gebruikers wachtwoord te resetten"
"domain_relayhost": "Verander relayhost voor een domein"
}, },
"add": { "add": {
"activate_filter_warn": "Alle andere filters worden gedeactiveerd zolang deze geactiveerd is.", "activate_filter_warn": "Alle andere filters worden gedeactiveerd zolang deze geactiveerd is.",
+2 -2
View File
@@ -189,7 +189,7 @@
"api_info": "API jest w trakcie prac. Dokumentację można znaleźć pod adresem <a href=\"/api\">/api</a>", "api_info": "API jest w trakcie prac. Dokumentację można znaleźć pod adresem <a href=\"/api\">/api</a>",
"api_key": "klucz API", "api_key": "klucz API",
"api_read_only": "Dostęp tylko do odczytu", "api_read_only": "Dostęp tylko do odczytu",
"api_read_write": "Dostęp do odczytu i zapisu", "api_read_write": "Dostęp tylko do odczytu",
"api_skip_ip_check": "Pomiń sprawdzenie IP dla API", "api_skip_ip_check": "Pomiń sprawdzenie IP dla API",
"app_hide": "Ukryj dla logowania", "app_hide": "Ukryj dla logowania",
"app_links": "Linki aplikacji", "app_links": "Linki aplikacji",
@@ -1226,7 +1226,7 @@
"decimal": ".", "decimal": ".",
"emptyTable": "Brak danych w tabeli", "emptyTable": "Brak danych w tabeli",
"expand_all": "Rozszerz wszystko", "expand_all": "Rozszerz wszystko",
"info": "Wyświetlanie od _START_ do _END_ z _TOTAL_ wpisów", "info": "Wyświetlanie od START do END z TOTAL wpisów",
"infoEmpty": "Wyświetlanie od 0 do 0 z 0 wpisów", "infoEmpty": "Wyświetlanie od 0 do 0 z 0 wpisów",
"infoFiltered": "(filtrowane z _MAX_ suma wpisów)", "infoFiltered": "(filtrowane z _MAX_ suma wpisów)",
"thousands": ",", "thousands": ",",
+30 -44
View File
@@ -38,7 +38,7 @@
"add_domain_only": "Adicionar somente domínio", "add_domain_only": "Adicionar somente domínio",
"add_domain_restart": "Adicionar domínio e reiniciar o SoGo", "add_domain_restart": "Adicionar domínio e reiniciar o SoGo",
"alias_address": "Endereço (s) de alias", "alias_address": "Endereço (s) de alias",
"alias_address_info": "<small>Endereço(s) de e-mail completo(s) ou @example.com, para capturar todas as mensagens de um domínio (separadas por vírgula). <b>Apenas domínios do Mailcow</b>.</small>", "alias_address_info": "<small>Endereço/s de e-mail completo ou @example .com, para capturar todas as mensagens de um domínio (separadas por vírgula). <b> somente domínios mailcow</b>.</small>",
"alias_domain": "Domínio de alias", "alias_domain": "Domínio de alias",
"alias_domain_info": "<small>Somente nomes de domínio válidos (separados por vírgula).</small>", "alias_domain_info": "<small>Somente nomes de domínio válidos (separados por vírgula).</small>",
"app_name": "Nome do aplicativo", "app_name": "Nome do aplicativo",
@@ -111,8 +111,7 @@
"validation_success": "Validado com sucesso", "validation_success": "Validado com sucesso",
"dry": "Simular sincronização", "dry": "Simular sincronização",
"internal": "Interno", "internal": "Interno",
"internal_info": "Aliases internos são acessíveis apenas a partir do próprio domínio ou alias de domínio.", "internal_info": "Aliases internos são acessíveis apenas a partir do próprio domínio ou alias de domínio."
"sender_allowed": "Permitir enviar como este alias"
}, },
"admin": { "admin": {
"access": "Acesso", "access": "Acesso",
@@ -152,13 +151,13 @@
"arrival_time": "Hora de chegada (hora do servidor)", "arrival_time": "Hora de chegada (hora do servidor)",
"authed_user": "Usuário autoritário", "authed_user": "Usuário autoritário",
"ays": "Tem certeza de que deseja continuar?", "ays": "Tem certeza de que deseja continuar?",
"ban_list_info": "Veja abaixo a lista de IPs banidos: <b>rede (tempo restante do banimento) - [ações]</b>.<br />IPs na fila para serem desbanidos serão removidos da lista de banimentos ativos em alguns segundos.<br />Rótulos vermelhos indicam banimentos permanentes ativos na lista de bloqueio.", "ban_list_info": "Veja uma lista de IPs banidos abaixo: <b>rede (tempo restante de banimento) - [ações]</b>. <br />Os IPs na fila para serem desbanidos serão removidos da lista de banimentos ativos em alguns segundos. <br />Rótulos vermelhos indicam proibições permanentes ativas na lista negra.",
"change_logo": "Alterar logotipo", "change_logo": "Alterar logotipo",
"logo_normal_label": "Normal", "logo_normal_label": "Normal",
"logo_dark_label": "Invertido para o modo escuro", "logo_dark_label": "Invertido para o modo escuro",
"configuration": "Configuração", "configuration": "Configuração",
"convert_html_to_text": "Converter HTML em texto sem formatação", "convert_html_to_text": "Converter HTML em texto sem formatação",
"copy_to_clipboard": "Copiado para a área de transferência!", "copy_to_clipboard": "Text copied to clipboard!",
"cors_settings": "Configurações do CORS", "cors_settings": "Configurações do CORS",
"credentials_transport_warning": "<b>Aviso</b>: Adicionar uma nova entrada no mapa de transporte atualizará as credenciais de todas as entradas com uma coluna correspondente do próximo salto.", "credentials_transport_warning": "<b>Aviso</b>: Adicionar uma nova entrada no mapa de transporte atualizará as credenciais de todas as entradas com uma coluna correspondente do próximo salto.",
"customer_id": "ID do cliente", "customer_id": "ID do cliente",
@@ -189,9 +188,9 @@
"excludes": "Exclui esses destinatários", "excludes": "Exclui esses destinatários",
"f2b_ban_time": "Tempo (s) de proibição", "f2b_ban_time": "Tempo (s) de proibição",
"f2b_ban_time_increment": "O tempo de banimento é incrementado com cada banimento", "f2b_ban_time_increment": "O tempo de banimento é incrementado com cada banimento",
"f2b_blacklist": "Redes/hosts na lista de bloqueio", "f2b_blacklist": "Redes/hosts na lista negra",
"f2b_filter": "Filtros Regex", "f2b_filter": "Filtros Regex",
"f2b_list_info": "Um host ou rede na lista de bloqueio sempre terá prioridade sobre uma entidade na lista de permissões. <b>As atualizações das listas levarão alguns segundos para serem aplicadas.</b>", "f2b_list_info": "Um host ou rede na lista negra sempre superará uma entidade na lista branca. <b>As atualizações da lista levarão alguns segundos para serem aplicadas.</b>",
"f2b_manage_external": "Gerenciar Fail2Ban externamente", "f2b_manage_external": "Gerenciar Fail2Ban externamente",
"f2b_manage_external_info": "O Fail2ban ainda manterá a lista de banimentos, mas não definirá ativamente regras para bloquear o tráfego. Use a lista de banimento gerada abaixo para bloquear externamente o tráfego.", "f2b_manage_external_info": "O Fail2ban ainda manterá a lista de banimentos, mas não definirá ativamente regras para bloquear o tráfego. Use a lista de banimento gerada abaixo para bloquear externamente o tráfego.",
"f2b_max_attempts": "Máximo de tentativas", "f2b_max_attempts": "Máximo de tentativas",
@@ -201,7 +200,7 @@
"f2b_parameters": "Parâmetros do Fail2ban", "f2b_parameters": "Parâmetros do Fail2ban",
"f2b_regex_info": "Registros considerados: SoGo, Postfix, Dovecot, PHP-FPM.", "f2b_regex_info": "Registros considerados: SoGo, Postfix, Dovecot, PHP-FPM.",
"f2b_retry_window": "Repita a (s) janela (s) para o máximo de tentativas", "f2b_retry_window": "Repita a (s) janela (s) para o máximo de tentativas",
"f2b_whitelist": "Redes/hosts na lista de permissões", "f2b_whitelist": "Redes/hosts incluídos na lista branca",
"filter_table": "Tabela de filtros", "filter_table": "Tabela de filtros",
"forwarding_hosts": "Anfitriões de encaminhamento", "forwarding_hosts": "Anfitriões de encaminhamento",
"forwarding_hosts_add_hint": "Você pode especificar endereços IPv4/IPv6, redes em notação CIDR, nomes de host (que serão resolvidos para endereços IP) ou nomes de domínio (que serão resolvidos para endereços IP consultando registros SPF ou, na ausência deles, registros MX).", "forwarding_hosts_add_hint": "Você pode especificar endereços IPv4/IPv6, redes em notação CIDR, nomes de host (que serão resolvidos para endereços IP) ou nomes de domínio (que serão resolvidos para endereços IP consultando registros SPF ou, na ausência deles, registros MX).",
@@ -223,7 +222,7 @@
"includes": "Inclua esses destinatários", "includes": "Inclua esses destinatários",
"ip_check": "Verificação de IP", "ip_check": "Verificação de IP",
"ip_check_disabled": "A verificação de IP está desativada. Você pode ativá-lo em <br><strong>Sistema > Configuração > Opções > Personalizar</strong>", "ip_check_disabled": "A verificação de IP está desativada. Você pode ativá-lo em <br><strong>Sistema > Configuração > Opções > Personalizar</strong>",
"ip_check_opt_in": "Opte por usar o serviço de terceiros <strong>ipv4.mailcow.email</strong> e <strong>ipv6.mailcow.email</strong> para resolver endereços IP externos.", "ip_check_opt_in": "Opte por usar o serviço de terceiros <strong>ipv4.mailcow.email.</strong> e <strong>ipv6.mailcow.email</strong> para resolver endereços IP externos.",
"is_mx_based": "Baseado em MX", "is_mx_based": "Baseado em MX",
"last_applied": "Aplicado pela última vez", "last_applied": "Aplicado pela última vez",
"license_info": "Uma licença não é necessária, mas ajuda no desenvolvimento.<br><a href=\"https://www.servercow.de/mailcow? Lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Registre seu GUID aqui</a> ou <a href=\"https://www.servercow.de/mailcow? Lang=en#support\" target=\"_blank\" alt=\"Support order\">comprar suporte para sua instalação de mailcow.</a>", "license_info": "Uma licença não é necessária, mas ajuda no desenvolvimento.<br><a href=\"https://www.servercow.de/mailcow? Lang=en#sal\" target=\"_blank\" alt=\"SAL order\">Registre seu GUID aqui</a> ou <a href=\"https://www.servercow.de/mailcow? Lang=en#support\" target=\"_blank\" alt=\"Support order\">comprar suporte para sua instalação de mailcow.</a>",
@@ -245,7 +244,7 @@
"oauth2_add_client": "Adicionar cliente OAuth2", "oauth2_add_client": "Adicionar cliente OAuth2",
"oauth2_client_id": "ID do cliente", "oauth2_client_id": "ID do cliente",
"oauth2_client_secret": "Segredo do cliente", "oauth2_client_secret": "Segredo do cliente",
"oauth2_info": "A implementação do OAuth2 suporta o tipo de concessão \"Código de Autorização\" e emite tokens de atualização.<br>\nO servidor também emite automaticamente novos tokens de atualização após um token de atualização ter sido usado.<br>\nO escopo padrão é <i>profile</i>. Somente usuários de caixa de correio podem ser autenticados com o OAuth2. Se o parâmetro de escopo for omitido, o padrão será <i>profile</i>.<br>\nO parâmetro <i>state</i> deve ser enviado pelo cliente como parte da solicitação de autorização.<br><br>\nCaminhos para solicitações à API OAuth2: <br>\n\n<ul>\n <li>Ponto de extremidade de autorização: <code>/oauth/authorize</code></li>\n <li>Endpoint do token: <code>/oauth/token</code></li>\n <li>Página de recursos: <code>/oauth/profile</code></li>\n</ul>\n\nRegenerar o segredo do cliente não expirará os códigos de autorização existentes, mas impedirá a renovação do token.<br><br>\nA revogação dos tokens de cliente causará o encerramento imediato de todas as sessões ativas. Todos os clientes precisarão se autenticar novamente.", "oauth2_info": "A implementação OAuth2 suporta o tipo de concessão \"Código de Autorização\" e emite tokens de atualização.<br>\nO servidor também emite automaticamente novos tokens de atualização, depois que um token de atualização foi usado.<br><br>\n&#8226; O escopo padrão é <i>perfil</i>. Somente usuários com caixa de e-mail podem ser autenticados contra o OAuth2. Se o parâmetro de escopo for omitido, ele voltará para <i>perfil</i>.<br>\nCaminhos para solicitações OAuth2 API: <br>\n<ul>\n<li>Endpoint de autorização: <code>/oauth/authorize</code></li>\n<li>Endpoint token: <code>/oauth/token</code></li>\n<li>Página de recursos: <code>/oauth/profile</code></li>\n</ul>\nRegenerar o segredo do cliente não expirará os códigos de autorização existentes, mas eles não renovarão seu token.<br><br>\nA revogação dos tokens do cliente causará o término imediato de todas as sessões ativas. Todos os clientes precisam se autenticar novamente.",
"oauth2_redirect_uri": "URI de redirecionamento", "oauth2_redirect_uri": "URI de redirecionamento",
"oauth2_renew_secret": "Gere um novo segredo de cliente", "oauth2_renew_secret": "Gere um novo segredo de cliente",
"oauth2_revoke_tokens": "Revogar todos os tokens do cliente", "oauth2_revoke_tokens": "Revogar todos os tokens do cliente",
@@ -321,8 +320,8 @@
"rspamd_com_settings": "Um nome de configuração será gerado automaticamente, veja os exemplos de predefinições abaixo. Para obter mais detalhes, consulte a documentação <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">do Rspamd</a>", "rspamd_com_settings": "Um nome de configuração será gerado automaticamente, veja os exemplos de predefinições abaixo. Para obter mais detalhes, consulte a documentação <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">do Rspamd</a>",
"rspamd_global_filters": "Mapas de filtro globais", "rspamd_global_filters": "Mapas de filtro globais",
"rspamd_global_filters_agree": "Eu vou ter cuidado!", "rspamd_global_filters_agree": "Eu vou ter cuidado!",
"rspamd_global_filters_info": "Os mapas de filtros globais contêm diferentes tipos de listas globais de bloqueio e de permissões.", "rspamd_global_filters_info": "Os mapas de filtros globais contêm diferentes tipos de listas negras e brancas globais.",
"rspamd_global_filters_regex": "Os nomes explicam sua finalidade. Todo o conteúdo deve conter uma expressão regular válida no formato \"/padrão/opções\" (por exemplo, <code>/.[+@domain.tld](mailto:+@domain.tld)/i</code>).<br>\nEmbora verificações básicas sejam executadas em cada linha de regex, a funcionalidade do Rspamd pode ser comprometida se ele não conseguir ler a sintaxe corretamente.<br>\nO Rspamd tentará ler o conteúdo do mapa quando ele for alterado. Se você tiver problemas, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">reinicie o Rspamd</a> para forçar o recarregamento do mapa.<br>Elementos na lista de bloqueio são excluídos da quarentena.", "rspamd_global_filters_regex": "Seus nomes explicam seu propósito. <code>Todo o conteúdo deve conter uma expressão regular válida no formato /padrão/opções (por exemplo, /. + @domain\\ .tld/i</code>). <br>\r\n Embora verificações rudimentares estejam sendo executadas em cada linha de regex, a funcionalidade do Rspamd pode ser interrompida se não conseguir ler a sintaxe corretamente. <br>\r\n O Rspamd tentará ler o conteúdo do mapa quando alterado. Se você tiver problemas, <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">reinicie o Rspamd</a> para forçar o recarregamento do mapa. <br>Os elementos da lista negra são excluídos da quarentena.",
"rspamd_settings_map": "Mapa de configurações do Rspamd", "rspamd_settings_map": "Mapa de configurações do Rspamd",
"sal_level": "Nível de humor", "sal_level": "Nível de humor",
"save": "Salvar alterações", "save": "Salvar alterações",
@@ -557,9 +556,7 @@
"mode_invalid": "Modo %s é inválido", "mode_invalid": "Modo %s é inválido",
"mx_invalid": "Registro MX %s é inválido", "mx_invalid": "Registro MX %s é inválido",
"required_data_missing": "Dados obrigatórios %s estão ausentes", "required_data_missing": "Dados obrigatórios %s estão ausentes",
"version_invalid": "Versão %s é inválida", "version_invalid": "Versão %s é inválida"
"tfa_removal_blocked": "A autenticação de dois fatores não pode ser removida, pois é obrigatória para a sua conta.",
"quarantine_category_invalid": "A categoria da quarentena deve ser uma das seguintes: add_header, reject, all"
}, },
"datatables": { "datatables": {
"collapse_all": "Recolher tudo", "collapse_all": "Recolher tudo",
@@ -730,7 +727,7 @@
"pushover_verify": "Verifique as credenciais", "pushover_verify": "Verifique as credenciais",
"quota_mb": "Cota (MiB)", "quota_mb": "Cota (MiB)",
"quota_warning_bcc": "Aviso de cota BCC", "quota_warning_bcc": "Aviso de cota BCC",
"quota_warning_bcc_info": "Os avisos serão enviados em cópias separadas para os seguintes destinatários. O assunto será precedido pelo nome de usuário correspondente entre colchetes, por exemplo: <code>Aviso de cota (user@example.com)</code>.", "quota_warning_bcc_info": "Os avisos serão enviados em cópias separadas para os seguintes destinatários. O assunto será sufixado pelo nome de usuário correspondente entre colchetes, por exemplo: <code>Aviso de cota (</code>user@example.com).",
"ratelimit": "Limite de taxa", "ratelimit": "Limite de taxa",
"redirect_uri": "URL de redirecionamento/retorno de chamada", "redirect_uri": "URL de redirecionamento/retorno de chamada",
"relay_all": "Retransmita todos os destinatários", "relay_all": "Retransmita todos os destinatários",
@@ -749,17 +746,17 @@
"sieve_desc": "Breve descrição", "sieve_desc": "Breve descrição",
"sieve_type": "Tipo de filtro", "sieve_type": "Tipo de filtro",
"skipcrossduplicates": "Ignore mensagens duplicadas entre pastas (primeiro a chegar, primeiro a ser servido)", "skipcrossduplicates": "Ignore mensagens duplicadas entre pastas (primeiro a chegar, primeiro a ser servido)",
"sogo_access": "Encaminhamento direto para o SOGo", "sogo_access": "Encaminhamento direto para o SOGoo",
"sogo_access_info": "Após o login, o usuário é automaticamente redirecionado para o SOGo.", "sogo_access_info": "Depois de fazer login, o usuário é automaticamente redirecionado para o SOGo.",
"sogo_visible": "O alias é visível no SoGo", "sogo_visible": "O alias é visível no SoGo",
"sogo_visible_info": "Essa opção afeta somente objetos, que podem ser exibidos no SoGo (endereços de alias compartilhados ou não compartilhados apontando para pelo menos uma mailbox local). Se estiver oculto, um alias não aparecerá como remetente selecionável no SoGo.", "sogo_visible_info": "Essa opção afeta somente objetos, que podem ser exibidos no SoGo (endereços de alias compartilhados ou não compartilhados apontando para pelo menos uma mailbox local). Se estiver oculto, um alias não aparecerá como remetente selecionável no SoGo.",
"spam_alias": "Crie ou altere endereços de alias com limite de tempo", "spam_alias": "Crie ou altere endereços de alias com limite de tempo",
"spam_filter": "Filtro de spam", "spam_filter": "Filtro de spam",
"spam_policy": "Adicionar ou remover itens da lista de permissões/bloqueio", "spam_policy": "Adicionar ou remover itens da lista branca/negra",
"spam_score": "Defina uma pontuação de spam personalizada", "spam_score": "Defina uma pontuação de spam personalizada",
"subfolder2": "Sincronizar na subpasta no destino <br><small>(vazio = não usar subpasta</small>)", "subfolder2": "Sincronizar na subpasta no destino <br><small>(vazio = não usar subpasta</small>)",
"syncjob": "Editar tarefa de sincronização", "syncjob": "Editar tarefa de sincronização",
"target_address": "Ir para o(s) endereço(s) <small>(separados por vírgula)</small>", "target_address": "<small>Ir para endereço/es (separados por vírgula)</small>",
"target_domain": "Domínio de destino", "target_domain": "Domínio de destino",
"timeout1": "Tempo limite para conexão com o host remoto", "timeout1": "Tempo limite para conexão com o host remoto",
"timeout2": "Tempo limite para conexão com o host local", "timeout2": "Tempo limite para conexão com o host local",
@@ -784,9 +781,7 @@
"mta_sts_max_age_info": "Tempo em segundos que servidores de email de recepção podem armazenar esta política em cache até buscar novamente.", "mta_sts_max_age_info": "Tempo em segundos que servidores de email de recepção podem armazenar esta política em cache até buscar novamente.",
"mta_sts_mx": "Servidor MX", "mta_sts_mx": "Servidor MX",
"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_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."
}, },
"fido2": { "fido2": {
"confirm": "Confirme", "confirm": "Confirme",
@@ -807,7 +802,7 @@
"cancel": "Cancelar", "cancel": "Cancelar",
"confirm_delete": "Confirme a exclusão", "confirm_delete": "Confirme a exclusão",
"delete_now": "Excluir agora", "delete_now": "Excluir agora",
"delete_these_items": "Por favor, confirme as alterações feitas no seguinte ID de objeto.", "delete_these_items": "Confirme suas alterações no seguinte ID de objeto",
"hibp_check": "Verifique em haveibeenpwned.com", "hibp_check": "Verifique em haveibeenpwned.com",
"hibp_nok": "Combinado! Essa é uma senha potencialmente perigosa!", "hibp_nok": "Combinado! Essa é uma senha potencialmente perigosa!",
"hibp_ok": "Nenhuma combinação encontrada.", "hibp_ok": "Nenhuma combinação encontrada.",
@@ -975,7 +970,7 @@
"recipient_map_new": "Novo destinatário", "recipient_map_new": "Novo destinatário",
"recipient_map_new_info": "O destino do mapa do destinatário deve ser um endereço de e-mail válido ou um nome de domínio.", "recipient_map_new_info": "O destino do mapa do destinatário deve ser um endereço de e-mail válido ou um nome de domínio.",
"recipient_map_old": "Destinatário original", "recipient_map_old": "Destinatário original",
"recipient_map_old_info": "O destino original do mapa de destinatário deve ser um endereço de e-mail válido ou um nome de domínio.", "recipient_map_old_info": "O destino original do mapa de um destinatário deve ser um endereço de e-mail válido ou um nome de domínio.",
"recipient_maps": "Mapas de destinatários", "recipient_maps": "Mapas de destinatários",
"relay_all": "Retransmita todos os destinatários", "relay_all": "Retransmita todos os destinatários",
"relay_unknown": "Retransmitir mailboxes desconhecidas", "relay_unknown": "Retransmitir mailboxes desconhecidas",
@@ -1066,7 +1061,7 @@
"notified": "Notificado", "notified": "Notificado",
"qhandler_success": "Solicitação enviada com sucesso para o sistema. Agora você pode fechar a janela.", "qhandler_success": "Solicitação enviada com sucesso para o sistema. Agora você pode fechar a janela.",
"qid": "Respand AID", "qid": "Respand AID",
"qinfo": "O sistema de quarentena irá salvar no banco de dados os e-mails rejeitados (o remetente <em>não</em> terá a impressão de que o e-mail foi entregue), bem como os e-mails que são entregues como cópia na pasta de spam de uma mailbox.\n<br>“Aprender como spam e excluir” irá classificar a mensagem como spam por meio do Teorema de Bayes e também calcular hashes fuzzy para bloquear mensagens semelhantes no futuro.\n<br>Esteja ciente de que o aprendizado de múltiplas mensagens pode, dependendo do seu sistema, levar tempo. <br>Elementos na lista de bloqueio são excluídos da quarentena.", "qinfo": "O sistema de quarentena salvará as mensagens rejeitadas no banco de dados (o remetente <em>não</em> terá a impressão de uma mensagem entregue), bem como as mensagens, que são entregues como cópia na pasta Lixo eletrônico de uma mailbox.\n <br>“Aprenda como spam e exclua” aprenderá uma mensagem como spam por meio do Teorema de Bayes e também calculará hashes difusos para negar mensagens semelhantes no futuro.\n <br>Esteja ciente de que aprender várias mensagens pode ser demorado, dependendo do seu sistema. <br>Os elementos da lista negra são excluídos da quarentena.",
"qitem": "Item de quarentena", "qitem": "Item de quarentena",
"quarantine": "Quarentena", "quarantine": "Quarentena",
"quick_actions": "Ações", "quick_actions": "Ações",
@@ -1242,12 +1237,7 @@
"webauthn": "Autenticação WebAuthn", "webauthn": "Autenticação WebAuthn",
"waiting_usb_auth": "<i>Aguardando o dispositivo USB...</i> <br><br>Toque no botão no seu dispositivo USB agora.", "waiting_usb_auth": "<i>Aguardando o dispositivo USB...</i> <br><br>Toque no botão no seu dispositivo USB agora.",
"waiting_usb_register": "<i>Aguardando o dispositivo USB...</i> <br><br>Digite sua senha acima e confirme seu registro tocando no botão no seu dispositivo USB.", "waiting_usb_register": "<i>Aguardando o dispositivo USB...</i> <br><br>Digite sua senha acima e confirme seu registro tocando no botão no seu dispositivo USB.",
"yubi_otp": "Autenticação Yubico OTP", "yubi_otp": "Autenticação Yubico OTP"
"force_tfa": "Forçar o cadastro de 2FA no login",
"force_tfa_info": "O usuário será obrigado a configurar a autenticação de dois fatores antes de acessar o painel.",
"setup_title": "Autenticação de Dois Fatores Obrigatória",
"setup_required": "Sua conta exige autenticação de dois fatores. Configure um método de 2FA para continuar.",
"cancel_setup": "Cancelar e sair"
}, },
"user": { "user": {
"action": "Ação", "action": "Ação",
@@ -1286,7 +1276,7 @@
"delete_ays": "Confirme o processo de exclusão.", "delete_ays": "Confirme o processo de exclusão.",
"direct_aliases": "Endereços de alias diretos", "direct_aliases": "Endereços de alias diretos",
"direct_aliases_desc": "Os endereços de alias diretos são afetados pelo filtro de spam e pelas configurações da política TLS.", "direct_aliases_desc": "Os endereços de alias diretos são afetados pelo filtro de spam e pelas configurações da política TLS.",
"direct_protocol_access": "Este usuário da mailbox possui <b>acesso direto e externo</b> aos seguintes protocolos e aplicações. Esta configuração é controlada pelo seu administrador. Senhas de aplicativo podem ser criadas para conceder acesso a protocolos e aplicações específicos.<br>O botão “Webmail” fornece login único (SSO) para o SOGo e está sempre disponível.", "direct_protocol_access": "Esse usuário da mailbox tem <b>acesso externo direto</b> aos seguintes protocolos e aplicativos. Essa configuração é controlada pelo administrador. As senhas de aplicativos podem ser criadas para conceder acesso a protocolos e aplicativos individuais. <br>O botão “Login no webmail” fornece login único no SoGo e está sempre disponível.",
"eas_reset": "Redefinir o cache do dispositivo ActiveSync", "eas_reset": "Redefinir o cache do dispositivo ActiveSync",
"eas_reset_help": "Em muitos casos, uma redefinição do cache do dispositivo ajudará a recuperar um perfil quebrado do ActiveSync. <br><b>Atenção:</b> Todos os elementos serão baixados novamente!", "eas_reset_help": "Em muitos casos, uma redefinição do cache do dispositivo ajudará a recuperar um perfil quebrado do ActiveSync. <br><b>Atenção:</b> Todos os elementos serão baixados novamente!",
"eas_reset_now": "Reinicie agora", "eas_reset_now": "Reinicie agora",
@@ -1362,12 +1352,12 @@
"sogo_profile_reset": "Redefinir perfil SoGo", "sogo_profile_reset": "Redefinir perfil SoGo",
"sogo_profile_reset_help": "Isso destruirá o perfil SoGo de um usuário e <b>excluirá todos os dados de contato e calendário irrecuperáveis</b>.", "sogo_profile_reset_help": "Isso destruirá o perfil SoGo de um usuário e <b>excluirá todos os dados de contato e calendário irrecuperáveis</b>.",
"sogo_profile_reset_now": "Redefina o perfil agora", "sogo_profile_reset_now": "Redefina o perfil agora",
"spam_aliases": "Aliases de e-mail de spam", "spam_aliases": "Aliases de e-mail temporários",
"spam_score_reset": "Redefinir para o padrão do servidor", "spam_score_reset": "Redefinir para o padrão do servidor",
"spamfilter": "Filtro de spam", "spamfilter": "Filtro de spam",
"spamfilter_behavior": "Avaliação", "spamfilter_behavior": "Avaliação",
"spamfilter_bl": "Lista de bloqueio", "spamfilter_bl": "Lista negra",
"spamfilter_bl_desc": "Endereços de e-mail na lista de bloqueio para <b>sempre</b> classificar como spam e rejeitados. E-mails rejeitados <b>não</b> serão copiados para a quarentena. Coringas podem ser utilizados. O filtro é aplicado apenas a aliases diretos (aliases com uma única mailbox de destino), excluindo aliases catch-all e a própria mailbox.", "spamfilter_bl_desc": "Endereços de e-mail na lista negra para <b>sempre</b> serem classificados como spam e rejeitados. E-mails rejeitados <b>não</b> serão copiados para a quarentena. Podem ser usados curingas. Um filtro é aplicado a aliases diretos (aliases com uma única caixa de correio de destino), excluindo aliases abrangentes e a própria mailbox.",
"spamfilter_default_score": "Valores padrão", "spamfilter_default_score": "Valores padrão",
"spamfilter_green": "Verde: esta mensagem não é spam", "spamfilter_green": "Verde: esta mensagem não é spam",
"spamfilter_hint": "O primeiro valor descreve a “pontuação baixa de spam”, o segundo representa a “alta pontuação de spam”.", "spamfilter_hint": "O primeiro valor descreve a “pontuação baixa de spam”, o segundo representa a “alta pontuação de spam”.",
@@ -1378,8 +1368,8 @@
"spamfilter_table_empty": "Não há dados para exibir", "spamfilter_table_empty": "Não há dados para exibir",
"spamfilter_table_remove": "remover", "spamfilter_table_remove": "remover",
"spamfilter_table_rule": "Regra", "spamfilter_table_rule": "Regra",
"spamfilter_wl": "Lista de permissões", "spamfilter_wl": "Lista branca",
"spamfilter_wl_desc": "Endereços de e-mail na lista de permissões são configurados para <b>nunca</b> serem classificados como spam. Coringas podem ser utilizados. O filtro é aplicado apenas a aliases diretos (aliases com uma única mailbox de destino), excluindo aliases catch-all e a própria mailbox.", "spamfilter_wl_desc": "Os endereços de e-mail incluídos na lista branca são programados para <b>nunca</b> serem classificados como spam. Podem ser usados curingas. Um filtro é aplicado a aliases diretos (aliases com uma única mailbox de destino), excluindo aliases abrangentes e a própria mailbox.",
"spamfilter_yellow": "Amarelo: esta mensagem pode ser spam, será marcada como spam e movida para sua pasta de lixo eletrônico", "spamfilter_yellow": "Amarelo: esta mensagem pode ser spam, será marcada como spam e movida para sua pasta de lixo eletrônico",
"status": "Status", "status": "Status",
"sync_jobs": "Trabalhos de sincronização", "sync_jobs": "Trabalhos de sincronização",
@@ -1393,7 +1383,7 @@
"syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Não é possível se conectar ao servidor remoto", "syncjob_EXIT_CONNECTION_FAILURE_HOST1": "Não é possível se conectar ao servidor remoto",
"syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Nome de usuário ou senha incorretos", "syncjob_EXIT_AUTHENTICATION_FAILURE_USER1": "Nome de usuário ou senha incorretos",
"tag_handling": "Definir o tratamento para e-mails marcados", "tag_handling": "Definir o tratamento para e-mails marcados",
"tag_help_example": "Exemplo de endereço de e-mail com tag: eu+Facebook</b>@exemplo.org", "tag_help_example": "Exemplo de um endereço de e-mail marcado: me <b>+Facebook</b> @example .org",
"tag_help_explain": "Na subpasta: uma nova subpasta com o nome da tag será criada abaixo da CAIXA DE ENTRADA (“Caixa de entrada/Facebook”). <br>\r\nNo assunto: o nome das tags será anexado ao assunto do e-mail, por exemplo: “[Facebook] Minhas notícias”.", "tag_help_explain": "Na subpasta: uma nova subpasta com o nome da tag será criada abaixo da CAIXA DE ENTRADA (“Caixa de entrada/Facebook”). <br>\r\nNo assunto: o nome das tags será anexado ao assunto do e-mail, por exemplo: “[Facebook] Minhas notícias”.",
"tag_in_none": "Não faça nada", "tag_in_none": "Não faça nada",
"tag_in_subfolder": "Na subpasta", "tag_in_subfolder": "Na subpasta",
@@ -1418,11 +1408,7 @@
"authentication": "Autenticação", "authentication": "Autenticação",
"overview": "Visão geral", "overview": "Visão geral",
"protocols": "Protocolos", "protocols": "Protocolos",
"tfa_info": "A autenticação de dois fatores ajuda a proteger sua conta. Se você habilitá-la, precisará de senhas de aplicativo para fazer login em aplicativos ou serviços que não suportam autenticação de dois fatores (por exemplo, clientes de email).", "tfa_info": "A autenticação de dois fatores ajuda a proteger sua conta. Se você habilitá-la, precisará de senhas de aplicativo para fazer login em aplicativos ou serviços que não suportam autenticação de dois fatores (por exemplo, clientes de email)."
"expire_never": "Nunca expirar",
"forever": "Para sempre",
"pw_update_required": "Sua conta exige a alteração de senha. Defina uma nova senha para continuar.",
"spam_aliases_info": "Um alias de spam é um endereço de e-mail temporário que pode ser usado para proteger endereços de e-mail reais. <br>Opcionalmente, pode-se definir um tempo de expiração para que o alias seja automaticamente desativado após o período definido, descartando efetivamente endereços que tenham sido abusados ou vazados."
}, },
"warning": { "warning": {
"cannot_delete_self": "Não é possível excluir o usuário conectado", "cannot_delete_self": "Não é possível excluir o usuário conectado",
+1 -2
View File
@@ -558,8 +558,7 @@
"mode_invalid": "Način %s ni veljaven", "mode_invalid": "Način %s ni veljaven",
"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"
}, },
"debug": { "debug": {
"containers_info": "Informacije o zabojniku", "containers_info": "Informacije o zabojniku",
File diff suppressed because it is too large Load Diff
+3 -3
View File
@@ -11,8 +11,8 @@
<link rel="stylesheet" href="{{ css_path }}"> <link rel="stylesheet" href="{{ css_path }}">
<script> <script>
// check if darkmode is preferred by OS or set by localStorage // check if darkmode is preferred by OS or set by localStorage
if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && localStorage.getItem("mailcow_theme") !== "light" || if (window.matchMedia && window.matchMedia('(prefers-color-scheme: dark)').matches && localStorage.getItem("theme") !== "light" ||
localStorage.getItem("mailcow_theme") === "dark") { localStorage.getItem("theme") === "dark") {
var head = document.getElementsByTagName('head')[0]; var head = document.getElementsByTagName('head')[0];
var link = document.createElement('link'); var link = document.createElement('link');
link.id = 'dark-mode-theme'; link.id = 'dark-mode-theme';
@@ -193,7 +193,7 @@ $(window).scroll(function() {
}); });
// Select language and reopen active URL without POST // Select language and reopen active URL without POST
function setLang(sel) { function setLang(sel) {
$.post( '{{ uri|escape("js") }}', {lang: sel} ); $.post( '{{ uri }}', {lang: sel} );
window.location.href = window.location.pathname + window.location.search; window.location.href = window.location.pathname + window.location.search;
} }
// FIDO2 functions // FIDO2 functions
+1 -1
View File
@@ -23,7 +23,7 @@
<div class="row mb-4"> <div class="row mb-4">
<label class="control-label col-sm-2" for="script_data">Script:</label> <label class="control-label col-sm-2" for="script_data">Script:</label>
<div class="col-sm-10"> <div class="col-sm-10">
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control textarea-code" rows="20" id="script_data" name="script_data" required>{{ result.script_data }}</textarea> <textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control textarea-code" rows="20" id="script_data" name="script_data" required>{{ result.script_data|raw }}</textarea>
</div> </div>
</div> </div>
<div class="row mb-2"> <div class="row mb-2">
+5 -5
View File
@@ -1,7 +1,7 @@
services: services:
unbound-mailcow: unbound-mailcow:
image: ghcr.io/mailcow/unbound:1.25.1-1 image: ghcr.io/mailcow/unbound:1.25
environment: environment:
- TZ=${TZ} - TZ=${TZ}
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n} - SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
@@ -200,7 +200,7 @@ services:
- phpfpm - phpfpm
sogo-mailcow: sogo-mailcow:
image: ghcr.io/mailcow/sogo:5.12.8-1 image: ghcr.io/mailcow/sogo:5.12.5-4
environment: environment:
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
@@ -252,7 +252,7 @@ services:
- sogo - sogo
dovecot-mailcow: dovecot-mailcow:
image: ghcr.io/mailcow/dovecot:2.3.21.1-2 image: ghcr.io/mailcow/dovecot:2.3.21.1-1
depends_on: depends_on:
- mysql-mailcow - mysql-mailcow
- netfilter-mailcow - netfilter-mailcow
@@ -419,7 +419,7 @@ services:
- php-fpm-mailcow - php-fpm-mailcow
- sogo-mailcow - sogo-mailcow
- rspamd-mailcow - rspamd-mailcow
image: ghcr.io/mailcow/nginx:1.30.2-1 image: ghcr.io/mailcow/nginx:1.06
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
environment: environment:
@@ -465,7 +465,7 @@ services:
condition: service_started condition: service_started
unbound-mailcow: unbound-mailcow:
condition: service_healthy condition: service_healthy
image: ghcr.io/mailcow/acme:1.97 image: ghcr.io/mailcow/acme:1.96
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
environment: environment: