mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-06-17 20:10:32 +00:00
Compare commits
1 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| cb70023241 |
@@ -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]}
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ $_SESSION['acl']['tls_policy'] = "1";
|
|||||||
$_SESSION['acl']['quarantine_notification'] = "1";
|
$_SESSION['acl']['quarantine_notification'] = "1";
|
||||||
$_SESSION['acl']['quarantine_category'] = "1";
|
$_SESSION['acl']['quarantine_category'] = "1";
|
||||||
$_SESSION['acl']['ratelimit'] = "1";
|
$_SESSION['acl']['ratelimit'] = "1";
|
||||||
$_SESSION['acl']['sogo_access'] = "1";
|
$_SESSION['acl']['sogo_redirection'] = "1";
|
||||||
$_SESSION['acl']['protocol_access'] = "1";
|
$_SESSION['acl']['protocol_access'] = "1";
|
||||||
$_SESSION['acl']['mailbox_relayhost'] = "1";
|
$_SESSION['acl']['mailbox_relayhost'] = "1";
|
||||||
$_SESSION['acl']['unlimited_quota'] = "1";
|
$_SESSION['acl']['unlimited_quota'] = "1";
|
||||||
|
|||||||
@@ -66,7 +66,7 @@ $_SESSION['acl']['tls_policy'] = "1";
|
|||||||
$_SESSION['acl']['quarantine_notification'] = "1";
|
$_SESSION['acl']['quarantine_notification'] = "1";
|
||||||
$_SESSION['acl']['quarantine_category'] = "1";
|
$_SESSION['acl']['quarantine_category'] = "1";
|
||||||
$_SESSION['acl']['ratelimit'] = "1";
|
$_SESSION['acl']['ratelimit'] = "1";
|
||||||
$_SESSION['acl']['sogo_access'] = "1";
|
$_SESSION['acl']['sogo_redirection'] = "1";
|
||||||
$_SESSION['acl']['protocol_access'] = "1";
|
$_SESSION['acl']['protocol_access'] = "1";
|
||||||
$_SESSION['acl']['mailbox_relayhost'] = "1";
|
$_SESSION['acl']['mailbox_relayhost'] = "1";
|
||||||
$_SESSION['acl']['unlimited_quota'] = "1";
|
$_SESSION['acl']['unlimited_quota'] = "1";
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
# Whitelist generated by Postwhite v3.4 on Wed Apr 1 00:33:31 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/
|
||||||
# 2246 total rules
|
# 2174 total rules
|
||||||
2a00:1450:4000::/36 permit
|
2a00:1450:4000::/36 permit
|
||||||
2a01:111:f400::/48 permit
|
2a01:111:f400::/48 permit
|
||||||
2a01:111:f403:2800::/53 permit
|
2a01:111:f403:2800::/53 permit
|
||||||
@@ -31,10 +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
|
||||||
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
|
||||||
@@ -60,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.38 permit
|
13.107.213.51 permit
|
||||||
13.107.246.38 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
|
||||||
@@ -370,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
|
||||||
@@ -456,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
|
||||||
@@ -525,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
|
||||||
@@ -648,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
|
||||||
@@ -667,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
|
||||||
@@ -1421,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
|
||||||
@@ -1447,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
|
||||||
@@ -1490,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
|
||||||
@@ -1502,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
|
||||||
@@ -1541,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
|
||||||
@@ -1555,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
|
||||||
@@ -1573,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
|
||||||
@@ -1614,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
|
||||||
@@ -1632,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
|
||||||
@@ -1656,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
|
||||||
@@ -1797,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
|
||||||
@@ -1822,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
|
||||||
@@ -1990,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
|
||||||
@@ -1998,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
|
||||||
@@ -2026,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
|
||||||
@@ -2187,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
|
||||||
@@ -2208,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
|
||||||
@@ -2226,12 +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
|
|
||||||
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
|
||||||
@@ -2243,9 +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::38 permit
|
2620:1ec:46::51 permit
|
||||||
2620:1ec:bdf::38 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
|
||||||
|
|||||||
@@ -754,7 +754,7 @@ paths:
|
|||||||
- syncjobs
|
- syncjobs
|
||||||
- quarantine
|
- quarantine
|
||||||
- login_as
|
- login_as
|
||||||
- sogo_access
|
- sogo_redirection
|
||||||
- app_passwds
|
- app_passwds
|
||||||
- bcc_maps
|
- bcc_maps
|
||||||
- pushover
|
- pushover
|
||||||
@@ -807,7 +807,7 @@ paths:
|
|||||||
- syncjobs
|
- syncjobs
|
||||||
- quarantine
|
- quarantine
|
||||||
- login_as
|
- login_as
|
||||||
- sogo_access
|
- sogo_redirection
|
||||||
- app_passwds
|
- app_passwds
|
||||||
- bcc_maps
|
- bcc_maps
|
||||||
- pushover
|
- pushover
|
||||||
@@ -3423,7 +3423,7 @@ paths:
|
|||||||
- info@domain2.tld
|
- info@domain2.tld
|
||||||
- domain3.tld
|
- domain3.tld
|
||||||
- "*"
|
- "*"
|
||||||
sogo_access: "1"
|
sogo_redirection: "1"
|
||||||
username:
|
username:
|
||||||
- info@domain.tld
|
- info@domain.tld
|
||||||
tags: ["tag3", "tag4"]
|
tags: ["tag3", "tag4"]
|
||||||
@@ -3474,7 +3474,7 @@ paths:
|
|||||||
- info@domain2.tld
|
- info@domain2.tld
|
||||||
- domain3.tld
|
- domain3.tld
|
||||||
- "*"
|
- "*"
|
||||||
sogo_access: "1"
|
sogo_redirection: "1"
|
||||||
tags: ["tag3", "tag4"]
|
tags: ["tag3", "tag4"]
|
||||||
items:
|
items:
|
||||||
- info@domain.tld
|
- info@domain.tld
|
||||||
@@ -3506,7 +3506,7 @@ paths:
|
|||||||
sender_acl:
|
sender_acl:
|
||||||
description: list of allowed send from addresses
|
description: list of allowed send from addresses
|
||||||
type: object
|
type: object
|
||||||
sogo_access:
|
sogo_redirection:
|
||||||
description: is access to SOGo webmail active or not
|
description: is access to SOGo webmail active or not
|
||||||
type: boolean
|
type: boolean
|
||||||
type: object
|
type: object
|
||||||
@@ -4883,7 +4883,7 @@ paths:
|
|||||||
force_pw_update: "0"
|
force_pw_update: "0"
|
||||||
mailbox_format: "maildir:"
|
mailbox_format: "maildir:"
|
||||||
quarantine_notification: never
|
quarantine_notification: never
|
||||||
sogo_access: "1"
|
sogo_redirection: "1"
|
||||||
tls_enforce_in: "0"
|
tls_enforce_in: "0"
|
||||||
tls_enforce_out: "0"
|
tls_enforce_out: "0"
|
||||||
domain: doman3.tld
|
domain: doman3.tld
|
||||||
@@ -5807,7 +5807,7 @@ paths:
|
|||||||
force_pw_update: "0"
|
force_pw_update: "0"
|
||||||
mailbox_format: "maildir:"
|
mailbox_format: "maildir:"
|
||||||
quarantine_notification: never
|
quarantine_notification: never
|
||||||
sogo_access: "1"
|
sogo_redirection: "1"
|
||||||
tls_enforce_in: "0"
|
tls_enforce_in: "0"
|
||||||
tls_enforce_out: "0"
|
tls_enforce_out: "0"
|
||||||
custom_attributes: {}
|
custom_attributes: {}
|
||||||
|
|||||||
@@ -48,7 +48,12 @@ function acl($_action, $_scope = null, $_data = null, $_extra = null) {
|
|||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
$sogo_acl_changed = false;
|
||||||
foreach ($set_acls as $set_acl_key => $set_acl_val) {
|
foreach ($set_acls as $set_acl_key => $set_acl_val) {
|
||||||
|
// Track if sogo_access ACL changed
|
||||||
|
if ($set_acl_key == 'sogo_access' && $is_now[$set_acl_key] != $set_acl_val) {
|
||||||
|
$sogo_acl_changed = true;
|
||||||
|
}
|
||||||
$stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
|
$stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
|
||||||
WHERE `username` = :username");
|
WHERE `username` = :username");
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
@@ -60,6 +65,10 @@ function acl($_action, $_scope = null, $_data = null, $_extra = null) {
|
|||||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||||
'msg' => array('acl_saved', $username)
|
'msg' => array('acl_saved', $username)
|
||||||
);
|
);
|
||||||
|
// Update SOGo static view if sogo_access ACL changed
|
||||||
|
if ($sogo_acl_changed) {
|
||||||
|
update_sogo_static_view($username);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case 'domainadmin':
|
case 'domainadmin':
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
@@ -940,8 +940,12 @@ function update_sogo_static_view($mailbox = null) {
|
|||||||
|
|
||||||
$mailbox_exists = false;
|
$mailbox_exists = false;
|
||||||
if ($mailbox !== null) {
|
if ($mailbox !== null) {
|
||||||
// Check if the mailbox exists
|
// Check if the mailbox exists and should have SOGo access
|
||||||
$stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'");
|
$stmt = $pdo->prepare("SELECT m.username FROM mailbox m
|
||||||
|
LEFT JOIN user_acl u ON m.username = u.username
|
||||||
|
WHERE m.username = :mailbox
|
||||||
|
AND m.active = '1'
|
||||||
|
AND (u.sogo_access IS NULL OR u.sogo_access = 1)");
|
||||||
$stmt->execute(array(':mailbox' => $mailbox));
|
$stmt->execute(array(':mailbox' => $mailbox));
|
||||||
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
if ($row){
|
if ($row){
|
||||||
@@ -976,8 +980,10 @@ function update_sogo_static_view($mailbox = null) {
|
|||||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
||||||
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
||||||
LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username
|
LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username
|
||||||
|
LEFT OUTER JOIN user_acl ON user_acl.username = mailbox.username
|
||||||
WHERE
|
WHERE
|
||||||
mailbox.active = '1'
|
mailbox.active = '1'
|
||||||
|
AND (user_acl.sogo_access IS NULL OR user_acl.sogo_access = 1)
|
||||||
$subquery
|
$subquery
|
||||||
ON DUPLICATE KEY UPDATE
|
ON DUPLICATE KEY UPDATE
|
||||||
`domain` = VALUES(`domain`),
|
`domain` = VALUES(`domain`),
|
||||||
@@ -1005,7 +1011,27 @@ function update_sogo_static_view($mailbox = null) {
|
|||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
if ($mailbox_exists) {
|
||||||
|
// For single mailbox update, only delete this specific user
|
||||||
|
$stmt = $pdo->prepare("DELETE FROM _sogo_static_view
|
||||||
|
WHERE `c_uid` = :mailbox
|
||||||
|
AND `c_uid` NOT IN (
|
||||||
|
SELECT m.`username` FROM `mailbox` m
|
||||||
|
LEFT JOIN `user_acl` u ON m.`username` = u.`username`
|
||||||
|
WHERE m.`active` = '1'
|
||||||
|
AND m.`username` = :mailbox2
|
||||||
|
AND (u.`sogo_access` IS NULL OR u.`sogo_access` = 1)
|
||||||
|
)");
|
||||||
|
$stmt->execute(array(':mailbox' => $mailbox, ':mailbox2' => $mailbox));
|
||||||
|
} else {
|
||||||
|
// Full cleanup for all users
|
||||||
|
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (
|
||||||
|
SELECT m.`username` FROM `mailbox` m
|
||||||
|
LEFT JOIN `user_acl` u ON m.`username` = u.`username`
|
||||||
|
WHERE m.`active` = '1'
|
||||||
|
AND (u.`sogo_access` IS NULL OR u.`sogo_access` = 1)
|
||||||
|
);");
|
||||||
|
}
|
||||||
|
|
||||||
flush_memcached();
|
flush_memcached();
|
||||||
}
|
}
|
||||||
@@ -3490,9 +3516,14 @@ function set_user_loggedin_session($user) {
|
|||||||
session_regenerate_id(true);
|
session_regenerate_id(true);
|
||||||
$_SESSION['mailcow_cc_username'] = $user;
|
$_SESSION['mailcow_cc_username'] = $user;
|
||||||
$_SESSION['mailcow_cc_role'] = 'user';
|
$_SESSION['mailcow_cc_role'] = 'user';
|
||||||
$sogo_sso_pass = file_get_contents("/etc/sogo-sso/sogo-sso.pass");
|
|
||||||
$_SESSION['sogo-sso-user-allowed'][] = $user;
|
acl('to_session');
|
||||||
$_SESSION['sogo-sso-pass'] = $sogo_sso_pass;
|
if (hasACLAccess("sogo_access")) {
|
||||||
|
$sogo_sso_pass = file_get_contents("/etc/sogo-sso/sogo-sso.pass");
|
||||||
|
$_SESSION['sogo-sso-user-allowed'][] = $user;
|
||||||
|
$_SESSION['sogo-sso-pass'] = $sogo_sso_pass;
|
||||||
|
}
|
||||||
|
|
||||||
unset($_SESSION['pending_mailcow_cc_username']);
|
unset($_SESSION['pending_mailcow_cc_username']);
|
||||||
unset($_SESSION['pending_mailcow_cc_role']);
|
unset($_SESSION['pending_mailcow_cc_role']);
|
||||||
unset($_SESSION['pending_tfa_methods']);
|
unset($_SESSION['pending_tfa_methods']);
|
||||||
|
|||||||
@@ -1101,7 +1101,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$force_tfa = (isset($_data['force_tfa'])) ? intval($_data['force_tfa']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_tfa']);
|
$force_tfa = (isset($_data['force_tfa'])) ? intval($_data['force_tfa']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_tfa']);
|
||||||
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
$tls_enforce_in = (isset($_data['tls_enforce_in'])) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
||||||
$tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
|
$tls_enforce_out = (isset($_data['tls_enforce_out'])) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
|
||||||
$sogo_access = (isset($_data['sogo_access'])) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']);
|
$sogo_redirection = (isset($_data['sogo_redirection'])) ? intval($_data['sogo_redirection']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_redirection']);
|
||||||
$imap_access = (isset($_data['imap_access'])) ? intval($_data['imap_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
|
$imap_access = (isset($_data['imap_access'])) ? intval($_data['imap_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['imap_access']);
|
||||||
$pop3_access = (isset($_data['pop3_access'])) ? intval($_data['pop3_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
|
$pop3_access = (isset($_data['pop3_access'])) ? intval($_data['pop3_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['pop3_access']);
|
||||||
$smtp_access = (isset($_data['smtp_access'])) ? intval($_data['smtp_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
|
$smtp_access = (isset($_data['smtp_access'])) ? intval($_data['smtp_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['smtp_access']);
|
||||||
@@ -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(
|
||||||
@@ -1134,7 +1123,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
'force_tfa' => strval($force_tfa),
|
'force_tfa' => strval($force_tfa),
|
||||||
'tls_enforce_in' => strval($tls_enforce_in),
|
'tls_enforce_in' => strval($tls_enforce_in),
|
||||||
'tls_enforce_out' => strval($tls_enforce_out),
|
'tls_enforce_out' => strval($tls_enforce_out),
|
||||||
'sogo_access' => strval($sogo_access),
|
'sogo_redirection' => strval($sogo_redirection),
|
||||||
'imap_access' => strval($imap_access),
|
'imap_access' => strval($imap_access),
|
||||||
'pop3_access' => strval($pop3_access),
|
'pop3_access' => strval($pop3_access),
|
||||||
'smtp_access' => strval($smtp_access),
|
'smtp_access' => strval($smtp_access),
|
||||||
@@ -1325,6 +1314,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$_data['syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
$_data['syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
$_data['eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
$_data['eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
$_data['sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
$_data['sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$_data['sogo_access'] = (in_array('sogo_access', $_data['acl'])) ? 1 : 0;
|
||||||
$_data['pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
$_data['pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
$_data['quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
$_data['quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
$_data['quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
$_data['quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
@@ -1341,6 +1331,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$_data['syncjobs'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_syncjobs']);
|
$_data['syncjobs'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_syncjobs']);
|
||||||
$_data['eas_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_eas_reset']);
|
$_data['eas_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_eas_reset']);
|
||||||
$_data['sogo_profile_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_sogo_profile_reset']);
|
$_data['sogo_profile_reset'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_sogo_profile_reset']);
|
||||||
|
$_data['sogo_access'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_sogo_access']);
|
||||||
$_data['pushover'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_pushover']);
|
$_data['pushover'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_pushover']);
|
||||||
$_data['quarantine'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine']);
|
$_data['quarantine'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine']);
|
||||||
$_data['quarantine_attachments'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_attachments']);
|
$_data['quarantine_attachments'] = intval($MAILBOX_DEFAULT_ATTRIBUTES['acl_quarantine_attachments']);
|
||||||
@@ -1352,9 +1343,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
|
|
||||||
try {
|
try {
|
||||||
$stmt = $pdo->prepare("INSERT INTO `user_acl`
|
$stmt = $pdo->prepare("INSERT INTO `user_acl`
|
||||||
(`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`,
|
(`username`, `spam_alias`, `tls_policy`, `spam_score`, `spam_policy`, `delimiter_action`, `syncjobs`, `eas_reset`, `sogo_profile_reset`, `sogo_access`,
|
||||||
`pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`, `pw_reset`)
|
`pushover`, `quarantine`, `quarantine_attachments`, `quarantine_notification`, `quarantine_category`, `app_passwds`, `pw_reset`)
|
||||||
VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset,
|
VALUES (:username, :spam_alias, :tls_policy, :spam_score, :spam_policy, :delimiter_action, :syncjobs, :eas_reset, :sogo_profile_reset, :sogo_access,
|
||||||
:pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds, :pw_reset) ");
|
:pushover, :quarantine, :quarantine_attachments, :quarantine_notification, :quarantine_category, :app_passwds, :pw_reset) ");
|
||||||
$stmt->execute(array(
|
$stmt->execute(array(
|
||||||
':username' => $username,
|
':username' => $username,
|
||||||
@@ -1366,6 +1357,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
':syncjobs' => $_data['syncjobs'],
|
':syncjobs' => $_data['syncjobs'],
|
||||||
':eas_reset' => $_data['eas_reset'],
|
':eas_reset' => $_data['eas_reset'],
|
||||||
':sogo_profile_reset' => $_data['sogo_profile_reset'],
|
':sogo_profile_reset' => $_data['sogo_profile_reset'],
|
||||||
|
':sogo_access' => $_data['sogo_access'],
|
||||||
':pushover' => $_data['pushover'],
|
':pushover' => $_data['pushover'],
|
||||||
':quarantine' => $_data['quarantine'],
|
':quarantine' => $_data['quarantine'],
|
||||||
':quarantine_attachments' => $_data['quarantine_attachments'],
|
':quarantine_attachments' => $_data['quarantine_attachments'],
|
||||||
@@ -1742,20 +1734,11 @@ 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']);
|
||||||
$attr["force_tfa"] = isset($_data['force_tfa']) ? intval($_data['force_tfa']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_tfa']);
|
$attr["force_tfa"] = isset($_data['force_tfa']) ? intval($_data['force_tfa']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['force_tfa']);
|
||||||
$attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_access']);
|
$attr["sogo_redirection"] = isset($_data['sogo_redirection']) ? intval($_data['sogo_redirection']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['sogo_redirection']);
|
||||||
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : 1;
|
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : 1;
|
||||||
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in']);
|
||||||
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
|
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out']);
|
||||||
@@ -1786,6 +1769,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_sogo_access'] = (in_array('sogo_access', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
@@ -1803,6 +1787,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$attr['acl_syncjobs'] = 0;
|
$attr['acl_syncjobs'] = 0;
|
||||||
$attr['acl_eas_reset'] = 0;
|
$attr['acl_eas_reset'] = 0;
|
||||||
$attr['acl_sogo_profile_reset'] = 0;
|
$attr['acl_sogo_profile_reset'] = 0;
|
||||||
|
$attr['acl_sogo_access'] = 0;
|
||||||
$attr['acl_pushover'] = 0;
|
$attr['acl_pushover'] = 0;
|
||||||
$attr['acl_quarantine'] = 0;
|
$attr['acl_quarantine'] = 0;
|
||||||
$attr['acl_quarantine_attachments'] = 0;
|
$attr['acl_quarantine_attachments'] = 0;
|
||||||
@@ -2080,14 +2065,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')");
|
||||||
@@ -3131,7 +3108,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
|
||||||
(int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
|
(int)$force_pw_update = (isset($_data['force_pw_update'])) ? intval($_data['force_pw_update']) : intval($is_now['attributes']['force_pw_update']);
|
||||||
(int)$force_tfa = (isset($_data['force_tfa'])) ? intval($_data['force_tfa']) : intval($is_now['attributes']['force_tfa']);
|
(int)$force_tfa = (isset($_data['force_tfa'])) ? intval($_data['force_tfa']) : intval($is_now['attributes']['force_tfa']);
|
||||||
(int)$sogo_access = (isset($_data['sogo_access']) && hasACLAccess("sogo_access")) ? intval($_data['sogo_access']) : intval($is_now['attributes']['sogo_access']);
|
(int)$sogo_redirection = (isset($_data['sogo_redirection'])) ? intval($_data['sogo_redirection']) : intval($is_now['attributes']['sogo_redirection']);
|
||||||
(int)$imap_access = (isset($_data['imap_access']) && hasACLAccess("protocol_access")) ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
(int)$imap_access = (isset($_data['imap_access']) && hasACLAccess("protocol_access")) ? intval($_data['imap_access']) : intval($is_now['attributes']['imap_access']);
|
||||||
(int)$pop3_access = (isset($_data['pop3_access']) && hasACLAccess("protocol_access")) ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
(int)$pop3_access = (isset($_data['pop3_access']) && hasACLAccess("protocol_access")) ? intval($_data['pop3_access']) : intval($is_now['attributes']['pop3_access']);
|
||||||
(int)$smtp_access = (isset($_data['smtp_access']) && hasACLAccess("protocol_access")) ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
(int)$smtp_access = (isset($_data['smtp_access']) && hasACLAccess("protocol_access")) ? intval($_data['smtp_access']) : intval($is_now['attributes']['smtp_access']);
|
||||||
@@ -3154,8 +3131,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'];
|
||||||
@@ -3429,7 +3404,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
`authsource` = :authsource,
|
`authsource` = :authsource,
|
||||||
`attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
|
`attributes` = JSON_SET(`attributes`, '$.force_pw_update', :force_pw_update),
|
||||||
`attributes` = JSON_SET(`attributes`, '$.force_tfa', :force_tfa),
|
`attributes` = JSON_SET(`attributes`, '$.force_tfa', :force_tfa),
|
||||||
`attributes` = JSON_SET(`attributes`, '$.sogo_access', :sogo_access),
|
`attributes` = JSON_SET(`attributes`, '$.sogo_redirection', :sogo_redirection),
|
||||||
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
|
`attributes` = JSON_SET(`attributes`, '$.imap_access', :imap_access),
|
||||||
`attributes` = JSON_SET(`attributes`, '$.sieve_access', :sieve_access),
|
`attributes` = JSON_SET(`attributes`, '$.sieve_access', :sieve_access),
|
||||||
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
|
`attributes` = JSON_SET(`attributes`, '$.pop3_access', :pop3_access),
|
||||||
@@ -3447,7 +3422,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
':attribute_hash' => $attribute_hash,
|
':attribute_hash' => $attribute_hash,
|
||||||
':force_pw_update' => $force_pw_update,
|
':force_pw_update' => $force_pw_update,
|
||||||
':force_tfa' => $force_tfa,
|
':force_tfa' => $force_tfa,
|
||||||
':sogo_access' => $sogo_access,
|
':sogo_redirection' => $sogo_redirection,
|
||||||
':imap_access' => $imap_access,
|
':imap_access' => $imap_access,
|
||||||
':pop3_access' => $pop3_access,
|
':pop3_access' => $pop3_access,
|
||||||
':sieve_access' => $sieve_access,
|
':sieve_access' => $sieve_access,
|
||||||
@@ -3816,19 +3791,10 @@ 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'];
|
||||||
$attr["sogo_access"] = isset($_data['sogo_access']) ? intval($_data['sogo_access']) : $is_now['sogo_access'];
|
$attr["sogo_redirection"] = isset($_data['sogo_redirection']) ? intval($_data['sogo_redirection']) : $is_now['sogo_redirection'];
|
||||||
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active'];
|
$attr["active"] = isset($_data['active']) ? intval($_data['active']) : $is_now['active'];
|
||||||
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
|
$attr["tls_enforce_in"] = isset($_data['tls_enforce_in']) ? intval($_data['tls_enforce_in']) : $is_now['tls_enforce_in'];
|
||||||
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
|
$attr["tls_enforce_out"] = isset($_data['tls_enforce_out']) ? intval($_data['tls_enforce_out']) : $is_now['tls_enforce_out'];
|
||||||
@@ -3856,6 +3822,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||||||
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
$attr['acl_syncjobs'] = (in_array('syncjobs', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
$attr['acl_eas_reset'] = (in_array('eas_reset', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
$attr['acl_sogo_profile_reset'] = (in_array('sogo_profile_reset', $_data['acl'])) ? 1 : 0;
|
||||||
|
$attr['acl_sogo_access'] = (in_array('sogo_access', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
$attr['acl_pushover'] = (in_array('pushover', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
$attr['acl_quarantine'] = (in_array('quarantine', $_data['acl'])) ? 1 : 0;
|
||||||
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
$attr['acl_quarantine_attachments'] = (in_array('quarantine_attachments', $_data['acl'])) ? 1 : 0;
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ function init_db_schema()
|
|||||||
try {
|
try {
|
||||||
global $pdo;
|
global $pdo;
|
||||||
|
|
||||||
$db_version = "19022026_1220";
|
$db_version = "12032026_1300";
|
||||||
|
|
||||||
$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));
|
||||||
@@ -506,6 +506,7 @@ function init_db_schema()
|
|||||||
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
"eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"sogo_profile_reset" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"sogo_profile_reset" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
|
"sogo_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"pushover" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"pushover" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
// quarantine is for quarantine actions, todo: rename
|
// quarantine is for quarantine actions, todo: rename
|
||||||
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
@@ -705,7 +706,7 @@ function init_db_schema()
|
|||||||
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"login_as" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"login_as" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"sogo_access" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"sogo_redirection" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||||
"pushover" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
"pushover" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||||
@@ -1397,7 +1398,10 @@ function init_db_schema()
|
|||||||
$pdo->query("UPDATE `admin` SET `attributes` = JSON_SET(`attributes`, '$.force_tfa', \"0\") WHERE JSON_VALUE(`attributes`, '$.force_tfa') IS NULL;");
|
$pdo->query("UPDATE `admin` SET `attributes` = JSON_SET(`attributes`, '$.force_tfa', \"0\") WHERE JSON_VALUE(`attributes`, '$.force_tfa') IS NULL;");
|
||||||
$pdo->query("UPDATE `admin` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.force_pw_update') IS NULL;");
|
$pdo->query("UPDATE `admin` SET `attributes` = JSON_SET(`attributes`, '$.force_pw_update', \"0\") WHERE JSON_VALUE(`attributes`, '$.force_pw_update') IS NULL;");
|
||||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sieve_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.sieve_access') IS NULL;");
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sieve_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.sieve_access') IS NULL;");
|
||||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.sogo_access') IS NULL;");
|
// Migrate sogo_access attribute to sogo_redirection
|
||||||
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_redirection', JSON_VALUE(`attributes`, '$.sogo_access')) WHERE JSON_VALUE(`attributes`, '$.sogo_access') IS NOT NULL;");
|
||||||
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_REMOVE(`attributes`, '$.sogo_access') WHERE JSON_VALUE(`attributes`, '$.sogo_access') IS NOT NULL;");
|
||||||
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.sogo_redirection', \"1\") WHERE JSON_VALUE(`attributes`, '$.sogo_redirection') IS NULL;");
|
||||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.imap_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.imap_access') IS NULL;");
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.imap_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.imap_access') IS NULL;");
|
||||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.pop3_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.pop3_access') IS NULL;");
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.pop3_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.pop3_access') IS NULL;");
|
||||||
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.smtp_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.smtp_access') IS NULL;");
|
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.smtp_access', \"1\") WHERE JSON_VALUE(`attributes`, '$.smtp_access') IS NULL;");
|
||||||
@@ -1421,6 +1425,10 @@ function init_db_schema()
|
|||||||
// Fix domain_admins
|
// Fix domain_admins
|
||||||
$pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
|
$pdo->query("DELETE FROM `domain_admins` WHERE `domain` = 'ALL';");
|
||||||
|
|
||||||
|
// Migrate template sogo_access to sogo_redirection
|
||||||
|
$pdo->query("UPDATE `templates` SET `attributes` = JSON_SET(`attributes`, '$.sogo_redirection', JSON_VALUE(`attributes`, '$.sogo_access')) WHERE `type` = 'mailbox' AND JSON_VALUE(`attributes`, '$.sogo_access') IS NOT NULL;");
|
||||||
|
$pdo->query("UPDATE `templates` SET `attributes` = JSON_REMOVE(`attributes`, '$.sogo_access') WHERE `type` = 'mailbox' AND JSON_VALUE(`attributes`, '$.sogo_access') IS NOT NULL;");
|
||||||
|
|
||||||
// add default templates
|
// add default templates
|
||||||
$default_domain_template = array(
|
$default_domain_template = array(
|
||||||
"template" => "Default",
|
"template" => "Default",
|
||||||
@@ -1456,7 +1464,7 @@ function init_db_schema()
|
|||||||
"rl_value" => "",
|
"rl_value" => "",
|
||||||
"force_pw_update" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_pw_update']),
|
"force_pw_update" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_pw_update']),
|
||||||
"force_tfa" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_tfa']),
|
"force_tfa" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['force_tfa']),
|
||||||
"sogo_access" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sogo_access']),
|
"sogo_redirection" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['sogo_redirection']),
|
||||||
"active" => 1,
|
"active" => 1,
|
||||||
"tls_enforce_in" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_in']),
|
"tls_enforce_in" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_in']),
|
||||||
"tls_enforce_out" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_out']),
|
"tls_enforce_out" => intval($GLOBALS['MAILBOX_DEFAULT_ATTRIBUTES']['tls_enforce_out']),
|
||||||
@@ -1472,6 +1480,7 @@ function init_db_schema()
|
|||||||
"acl_syncjobs" => 0,
|
"acl_syncjobs" => 0,
|
||||||
"acl_eas_reset" => 1,
|
"acl_eas_reset" => 1,
|
||||||
"acl_sogo_profile_reset" => 0,
|
"acl_sogo_profile_reset" => 0,
|
||||||
|
"acl_sogo_access" => 1,
|
||||||
"acl_pushover" => 1,
|
"acl_pushover" => 1,
|
||||||
"acl_quarantine" => 1,
|
"acl_quarantine" => 1,
|
||||||
"acl_quarantine_attachments" => 1,
|
"acl_quarantine_attachments" => 1,
|
||||||
|
|||||||
@@ -81,8 +81,9 @@ if (isset($_POST["verify_tfa_login"])) {
|
|||||||
header("Location: /");
|
header("Location: /");
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
if (intval($user_details['attributes']['sogo_access']) == 1 &&
|
if (intval($user_details['attributes']['sogo_redirection']) == 1 &&
|
||||||
intval($user_details['attributes']['force_pw_update']) != 1 &&
|
intval($user_details['attributes']['force_pw_update']) != 1 &&
|
||||||
|
hasACLAccess('sogo_access') &&
|
||||||
getenv('SKIP_SOGO') != "y" &&
|
getenv('SKIP_SOGO') != "y" &&
|
||||||
!$is_dual) {
|
!$is_dual) {
|
||||||
header("Location: /SOGo/so/");
|
header("Location: /SOGo/so/");
|
||||||
@@ -161,8 +162,9 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
|
|||||||
header("Location: /");
|
header("Location: /");
|
||||||
die();
|
die();
|
||||||
}
|
}
|
||||||
if (intval($user_details['attributes']['sogo_access']) == 1 &&
|
if (intval($user_details['attributes']['sogo_redirection']) == 1 &&
|
||||||
intval($user_details['attributes']['force_pw_update']) != 1 &&
|
intval($user_details['attributes']['force_pw_update']) != 1 &&
|
||||||
|
hasACLAccess('sogo_access') &&
|
||||||
getenv('SKIP_SOGO') != "y" &&
|
getenv('SKIP_SOGO') != "y" &&
|
||||||
!$is_dual) {
|
!$is_dual) {
|
||||||
header("Location: /SOGo/so/");
|
header("Location: /SOGo/so/");
|
||||||
|
|||||||
@@ -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) {
|
||||||
|
|||||||
@@ -196,8 +196,8 @@ $MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false;
|
|||||||
// Force 2FA enrollment at next login
|
// Force 2FA enrollment at next login
|
||||||
$MAILBOX_DEFAULT_ATTRIBUTES['force_tfa'] = false;
|
$MAILBOX_DEFAULT_ATTRIBUTES['force_tfa'] = false;
|
||||||
|
|
||||||
// Enable SOGo access - Users will be redirected to SOGo after login (set to false to disable redirect by default)
|
// Enable SOGo redirection - Users will be redirected to SOGo after login (set to false to disable redirect by default)
|
||||||
$MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true;
|
$MAILBOX_DEFAULT_ATTRIBUTES['sogo_redirection'] = true;
|
||||||
|
|
||||||
// How to handle tagged emails
|
// How to handle tagged emails
|
||||||
// none - No special handling
|
// none - No special handling
|
||||||
|
|||||||
+3
-1
@@ -12,7 +12,9 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||||||
if (empty($_SESSION['pending_tfa_setup']) && empty($_SESSION['pending_pw_update'])) {
|
if (empty($_SESSION['pending_tfa_setup']) && empty($_SESSION['pending_pw_update'])) {
|
||||||
$user_details = mailbox("get", "mailbox_details", $_SESSION['mailcow_cc_username']);
|
$user_details = mailbox("get", "mailbox_details", $_SESSION['mailcow_cc_username']);
|
||||||
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
|
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
|
||||||
if (intval($user_details['attributes']['sogo_access']) == 1 && !$is_dual && getenv('SKIP_SOGO') != "y") {
|
if (intval($user_details['attributes']['sogo_redirection']) == 1 &&
|
||||||
|
hasACLAccess('sogo_access') &&
|
||||||
|
!$is_dual && getenv('SKIP_SOGO') != "y") {
|
||||||
header("Location: /SOGo/so/");
|
header("Location: /SOGo/so/");
|
||||||
} else {
|
} else {
|
||||||
header("Location: /user");
|
header("Location: /user");
|
||||||
|
|||||||
@@ -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');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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>';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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);
|
||||||
}
|
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -385,6 +385,9 @@ $(document).ready(function() {
|
|||||||
if (template.acl_sogo_profile_reset == 1){
|
if (template.acl_sogo_profile_reset == 1){
|
||||||
acl.push("sogo_profile_reset");
|
acl.push("sogo_profile_reset");
|
||||||
}
|
}
|
||||||
|
if (template.acl_sogo_access == 1){
|
||||||
|
acl.push("sogo_access");
|
||||||
|
}
|
||||||
if (template.acl_pushover == 1){
|
if (template.acl_pushover == 1){
|
||||||
acl.push("pushover");
|
acl.push("pushover");
|
||||||
}
|
}
|
||||||
@@ -424,10 +427,10 @@ $(document).ready(function() {
|
|||||||
} else {
|
} else {
|
||||||
$('#force_pw_update').prop('checked', false);
|
$('#force_pw_update').prop('checked', false);
|
||||||
}
|
}
|
||||||
if (template.sogo_access == 1){
|
if (template.sogo_redirection == 1){
|
||||||
$('#sogo_access').prop('checked', true);
|
$('#sogo_redirection').prop('checked', true);
|
||||||
} else {
|
} else {
|
||||||
$('#sogo_access').prop('checked', false);
|
$('#sogo_redirection').prop('checked', false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// load tags
|
// load tags
|
||||||
@@ -1241,7 +1244,7 @@ jQuery(function($){
|
|||||||
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>';
|
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.eas_access = '<i class="text-' + (item.attributes.eas_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.eas_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.eas_access == 1 ? '1' : '0') + '</span></i>';
|
item.attributes.eas_access = '<i class="text-' + (item.attributes.eas_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.eas_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.eas_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.dav_access = '<i class="text-' + (item.attributes.dav_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.dav_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.dav_access == 1 ? '1' : '0') + '</span></i>';
|
item.attributes.dav_access = '<i class="text-' + (item.attributes.dav_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.dav_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.dav_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>';
|
item.attributes.sogo_redirection = '<i class="text-' + (item.attributes.sogo_redirection == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_redirection == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_redirection == 1 ? '1' : '0') + '</span></i>';
|
||||||
if (item.attributes.quarantine_notification === 'never') {
|
if (item.attributes.quarantine_notification === 'never') {
|
||||||
item.attributes.quarantine_notification = lang.never;
|
item.attributes.quarantine_notification = lang.never;
|
||||||
} else if (item.attributes.quarantine_notification === 'hourly') {
|
} else if (item.attributes.quarantine_notification === 'hourly') {
|
||||||
@@ -1360,8 +1363,8 @@ jQuery(function($){
|
|||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
title: 'SOGO',
|
title: 'SOGO redirection',
|
||||||
data: 'attributes.sogo_access',
|
data: 'attributes.sogo_redirection',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -226,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') {
|
||||||
@@ -254,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) + '&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>'
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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(`
|
||||||
|
|||||||
@@ -1,5 +0,0 @@
|
|||||||
{
|
|
||||||
"acl": {
|
|
||||||
"login_as": "E-poçt qutusu istifadəçisi olaraq daxil ol"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -22,14 +22,15 @@
|
|||||||
"ratelimit": "Rate limit",
|
"ratelimit": "Rate limit",
|
||||||
"recipient_maps": "Empfängerumschreibungen",
|
"recipient_maps": "Empfängerumschreibungen",
|
||||||
"smtp_ip_access": "Verwalten der erlaubten Hosts für SMTP",
|
"smtp_ip_access": "Verwalten der erlaubten Hosts für SMTP",
|
||||||
"sogo_access": "Verwalten des SOGo-Zugriffsrechts erlauben",
|
"sogo_access": "SOGo-Nutzung erlauben",
|
||||||
"sogo_profile_reset": "SOGo-Profil zurücksetzen",
|
"sogo_profile_reset": "SOGo-Profil zurücksetzen",
|
||||||
"spam_alias": "Temporäre E-Mail-Aliasse",
|
"spam_alias": "Temporäre E-Mail-Aliasse",
|
||||||
"spam_policy": "Deny/Allowlist",
|
"spam_policy": "Deny/Allowlist",
|
||||||
"spam_score": "Spam-Bewertung",
|
"spam_score": "Spam-Bewertung",
|
||||||
"syncjobs": "Sync Jobs",
|
"syncjobs": "Sync Jobs",
|
||||||
"tls_policy": "Verschlüsselungsrichtlinie",
|
"tls_policy": "Verschlüsselungsrichtlinie",
|
||||||
"unlimited_quota": "Unendliche Quota für Mailboxen"
|
"unlimited_quota": "Unendliche Quota für Mailboxen",
|
||||||
|
"sogo_redirection": "Verwalten der SOGo-Weiterleitung erlauben"
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"activate_filter_warn": "Alle anderen Filter dieses Typs werden deaktiviert, falls dieses Script aktiviert wird.",
|
"activate_filter_warn": "Alle anderen Filter dieses Typs werden deaktiviert, falls dieses Script aktiviert wird.",
|
||||||
@@ -512,7 +513,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.",
|
||||||
@@ -768,8 +768,6 @@
|
|||||||
"sieve_desc": "Kurze Beschreibung",
|
"sieve_desc": "Kurze Beschreibung",
|
||||||
"sieve_type": "Filtertyp",
|
"sieve_type": "Filtertyp",
|
||||||
"skipcrossduplicates": "Duplikate auch über Ordner hinweg überspringen (\"first come, first serve\")",
|
"skipcrossduplicates": "Duplikate auch über Ordner hinweg überspringen (\"first come, first serve\")",
|
||||||
"sogo_access": "Direktes weiterleiten an SOGo",
|
|
||||||
"sogo_access_info": "Nach dem Einloggen wird der Benutzer automatisch an SOGo weitergeleitet.",
|
|
||||||
"sogo_visible": "Alias in SOGo sichtbar",
|
"sogo_visible": "Alias in SOGo sichtbar",
|
||||||
"sogo_visible_info": "Diese Option hat lediglich Einfluss auf Objekte, die in SOGo darstellbar sind (geteilte oder nicht-geteilte Alias-Adressen mit dem Ziel mindestens einer lokalen Mailbox).",
|
"sogo_visible_info": "Diese Option hat lediglich Einfluss auf Objekte, die in SOGo darstellbar sind (geteilte oder nicht-geteilte Alias-Adressen mit dem Ziel mindestens einer lokalen Mailbox).",
|
||||||
"spam_alias": "Anpassen temporärer Alias-Adressen",
|
"spam_alias": "Anpassen temporärer Alias-Adressen",
|
||||||
@@ -786,7 +784,9 @@
|
|||||||
"unchanged_if_empty": "Unverändert, wenn leer",
|
"unchanged_if_empty": "Unverändert, wenn leer",
|
||||||
"username": "Benutzername",
|
"username": "Benutzername",
|
||||||
"validate_save": "Validieren und speichern",
|
"validate_save": "Validieren und speichern",
|
||||||
"pushover_sound": "Ton"
|
"pushover_sound": "Ton",
|
||||||
|
"sogo_redirection": "Direktes weiterleiten an SOGo",
|
||||||
|
"sogo_redirection_info": "Nach dem Einloggen wird der Benutzer automatisch an SOGo weitergeleitet."
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"confirm": "Bestätigen",
|
"confirm": "Bestätigen",
|
||||||
|
|||||||
@@ -22,14 +22,15 @@
|
|||||||
"ratelimit": "Rate limit",
|
"ratelimit": "Rate limit",
|
||||||
"recipient_maps": "Recipient maps",
|
"recipient_maps": "Recipient maps",
|
||||||
"smtp_ip_access": "Change allowed hosts for SMTP",
|
"smtp_ip_access": "Change allowed hosts for SMTP",
|
||||||
"sogo_access": "Allow management of SOGo access",
|
"sogo_access": "Allow SOGo usage",
|
||||||
"sogo_profile_reset": "Reset SOGo profile",
|
"sogo_profile_reset": "Reset SOGo profile",
|
||||||
"spam_alias": "Temporary aliases",
|
"spam_alias": "Temporary aliases",
|
||||||
"spam_policy": "Denylist/Allowlist",
|
"spam_policy": "Denylist/Allowlist",
|
||||||
"spam_score": "Spam score",
|
"spam_score": "Spam score",
|
||||||
"syncjobs": "Sync jobs",
|
"syncjobs": "Sync jobs",
|
||||||
"tls_policy": "TLS policy",
|
"tls_policy": "TLS policy",
|
||||||
"unlimited_quota": "Unlimited quota for mailboxes"
|
"unlimited_quota": "Unlimited quota for mailboxes",
|
||||||
|
"sogo_redirection": "Allow management of SOGo forwarding"
|
||||||
},
|
},
|
||||||
"add": {
|
"add": {
|
||||||
"activate_filter_warn": "All other filters will be deactivated, when active is checked.",
|
"activate_filter_warn": "All other filters will be deactivated, when active is checked.",
|
||||||
@@ -513,7 +514,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.",
|
||||||
@@ -769,8 +769,6 @@
|
|||||||
"sieve_desc": "Short description",
|
"sieve_desc": "Short description",
|
||||||
"sieve_type": "Filter type",
|
"sieve_type": "Filter type",
|
||||||
"skipcrossduplicates": "Skip duplicate messages across folders (first come, first serve)",
|
"skipcrossduplicates": "Skip duplicate messages across folders (first come, first serve)",
|
||||||
"sogo_access": "Direct forwarding to SOGo",
|
|
||||||
"sogo_access_info": "After logging in, the user is automatically redirected to SOGo.",
|
|
||||||
"sogo_visible": "Alias is visible in SOGo",
|
"sogo_visible": "Alias is visible in SOGo",
|
||||||
"sogo_visible_info": "This option only affects objects, that can be displayed in SOGo (shared or non-shared alias addresses pointing to at least one local mailbox). If hidden, an alias will not appear as selectable sender in SOGo.",
|
"sogo_visible_info": "This option only affects objects, that can be displayed in SOGo (shared or non-shared alias addresses pointing to at least one local mailbox). If hidden, an alias will not appear as selectable sender in SOGo.",
|
||||||
"spam_alias": "Create or change time limited alias addresses",
|
"spam_alias": "Create or change time limited alias addresses",
|
||||||
@@ -786,7 +784,9 @@
|
|||||||
"title": "Edit object",
|
"title": "Edit object",
|
||||||
"unchanged_if_empty": "If unchanged leave blank",
|
"unchanged_if_empty": "If unchanged leave blank",
|
||||||
"username": "Username",
|
"username": "Username",
|
||||||
"validate_save": "Validate and save"
|
"validate_save": "Validate and save",
|
||||||
|
"sogo_redirection": "Direct forwarding to SOGo",
|
||||||
|
"sogo_redirection_info": "After logging in, the user is automatically redirected to SOGo."
|
||||||
},
|
},
|
||||||
"fido2": {
|
"fido2": {
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
|
|||||||
@@ -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."
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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,7 +151,7 @@
|
|||||||
"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",
|
||||||
@@ -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).",
|
||||||
@@ -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",
|
||||||
@@ -749,13 +746,13 @@
|
|||||||
"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",
|
||||||
@@ -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",
|
||||||
@@ -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 só é 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 só é 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",
|
||||||
@@ -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",
|
||||||
|
|||||||
@@ -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",
|
||||||
|
|||||||
@@ -65,7 +65,6 @@ if (isset($_GET['app_password'])) {
|
|||||||
$attr['protocols'][] = 'dav_access';
|
$attr['protocols'][] = 'dav_access';
|
||||||
}
|
}
|
||||||
app_passwd("add", $attr);
|
app_passwd("add", $attr);
|
||||||
$password = htmlspecialchars($password, ENT_NOQUOTES);
|
|
||||||
} else {
|
} else {
|
||||||
$app_password = false;
|
$app_password = false;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ if (isset($_SERVER['PHP_AUTH_USER'])) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
$login_check = check_login($username, $password, array('service' => $service));
|
$login_check = check_login($username, $password, array('service' => $service));
|
||||||
if ($login_check === 'user') {
|
if ($login_check === 'user' && hasACLAccess('sogo_access')) {
|
||||||
header("X-User: $username");
|
header("X-User: $username");
|
||||||
header("X-Auth: Basic ".base64_encode("$username:$password"));
|
header("X-Auth: Basic ".base64_encode("$username:$password"));
|
||||||
header("X-Auth-Type: Basic");
|
header("X-Auth-Type: Basic");
|
||||||
@@ -47,6 +47,7 @@ elseif (isset($_GET['login'])) {
|
|||||||
// check permissions (if dual_login is active, deny sso when acl is not given)
|
// check permissions (if dual_login is active, deny sso when acl is not given)
|
||||||
$login = html_entity_decode(rawurldecode($_GET["login"]));
|
$login = html_entity_decode(rawurldecode($_GET["login"]));
|
||||||
if (isset($_SESSION['mailcow_cc_role']) &&
|
if (isset($_SESSION['mailcow_cc_role']) &&
|
||||||
|
hasACLAccess('sogo_access') &&
|
||||||
(($_SESSION['acl']['login_as'] == "1" && $ALLOW_ADMIN_EMAIL_LOGIN !== 0) || ($is_dual === false && $login == $_SESSION['mailcow_cc_username']))) {
|
(($_SESSION['acl']['login_as'] == "1" && $ALLOW_ADMIN_EMAIL_LOGIN !== 0) || ($is_dual === false && $login == $_SESSION['mailcow_cc_username']))) {
|
||||||
if (filter_var($login, FILTER_VALIDATE_EMAIL)) {
|
if (filter_var($login, FILTER_VALIDATE_EMAIL)) {
|
||||||
if (user_get_alias_details($login) !== false) {
|
if (user_get_alias_details($login) !== false) {
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<input type="hidden" value="default" name="sender_acl">
|
<input type="hidden" value="default" name="sender_acl">
|
||||||
<input type="hidden" value="0" name="force_pw_update">
|
<input type="hidden" value="0" name="force_pw_update">
|
||||||
<input type="hidden" value="0" name="sogo_access">
|
<input type="hidden" value="0" name="sogo_redirection">
|
||||||
<input type="hidden" value="0" name="protocol_access">
|
<input type="hidden" value="0" name="protocol_access">
|
||||||
|
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
@@ -125,6 +125,7 @@
|
|||||||
<option value="syncjobs" {% if template.attributes.acl_syncjobs == '1' %} selected{% endif %}>{{ lang.acl["syncjobs"] }}</option>
|
<option value="syncjobs" {% if template.attributes.acl_syncjobs == '1' %} selected{% endif %}>{{ lang.acl["syncjobs"] }}</option>
|
||||||
<option value="eas_reset" {% if template.attributes.acl_eas_reset == '1' %} selected{% endif %}>{{ lang.acl["eas_reset"] }}</option>
|
<option value="eas_reset" {% if template.attributes.acl_eas_reset == '1' %} selected{% endif %}>{{ lang.acl["eas_reset"] }}</option>
|
||||||
<option value="sogo_profile_reset" {% if template.attributes.acl_sogo_profile_reset == '1' %} selected{% endif %}>{{ lang.acl["sogo_profile_reset"] }}</option>
|
<option value="sogo_profile_reset" {% if template.attributes.acl_sogo_profile_reset == '1' %} selected{% endif %}>{{ lang.acl["sogo_profile_reset"] }}</option>
|
||||||
|
<option value="sogo_access" {% if template.attributes.acl_sogo_access == '1' %} selected{% endif %}>{{ lang.acl["sogo_access"] }}</option>
|
||||||
<option value="pushover" {% if template.attributes.acl_pushover == '1' %} selected{% endif %}>{{ lang.acl["pushover"] }}</option>
|
<option value="pushover" {% if template.attributes.acl_pushover == '1' %} selected{% endif %}>{{ lang.acl["pushover"] }}</option>
|
||||||
<option value="quarantine" {% if template.attributes.acl_quarantine == '1' %} selected{% endif %}>{{ lang.acl["quarantine"] }}</option>
|
<option value="quarantine" {% if template.attributes.acl_quarantine == '1' %} selected{% endif %}>{{ lang.acl["quarantine"] }}</option>
|
||||||
<option value="quarantine_attachments" {% if template.attributes.acl_quarantine_attachments == '1' %} selected{% endif %}>{{ lang.acl["quarantine_attachments"] }}</option>
|
<option value="quarantine_attachments" {% if template.attributes.acl_quarantine_attachments == '1' %} selected{% endif %}>{{ lang.acl["quarantine_attachments"] }}</option>
|
||||||
@@ -169,8 +170,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access"{% if template.attributes.sogo_access == '1' %} checked{% endif %}> {{ lang.edit.sogo_access }}</label>
|
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_redirection"{% if template.attributes.sogo_redirection == '1' %} checked{% endif %}> {{ lang.edit.sogo_redirection }}</label>
|
||||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
<small class="text-muted">{{ lang.edit.sogo_redirection_info }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -25,7 +25,7 @@
|
|||||||
<input type="hidden" value="default" name="sender_acl">
|
<input type="hidden" value="default" name="sender_acl">
|
||||||
<input type="hidden" value="0" name="force_pw_update">
|
<input type="hidden" value="0" name="force_pw_update">
|
||||||
<input type="hidden" value="0" name="force_tfa">
|
<input type="hidden" value="0" name="force_tfa">
|
||||||
<input type="hidden" value="0" name="sogo_access">
|
<input type="hidden" value="0" name="sogo_redirection">
|
||||||
<input type="hidden" value="0" name="protocol_access">
|
<input type="hidden" value="0" name="protocol_access">
|
||||||
<div class="row mb-2">
|
<div class="row mb-2">
|
||||||
<label class="control-label col-sm-2">{{ lang.admin.iam }}</label>
|
<label class="control-label col-sm-2">{{ lang.admin.iam }}</label>
|
||||||
@@ -327,11 +327,11 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{% if not skip_sogo %}
|
{% if not skip_sogo %}
|
||||||
<div data-acl="{{ acl.sogo_access }}" class="row">
|
<div data-acl="{{ acl.sogo_redirection }}" class="row">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access"{% if result.attributes.sogo_access == '1' %} checked{% endif %}> {{ lang.edit.sogo_access }}</label>
|
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_redirection"{% if result.attributes.sogo_redirection == '1' %} checked{% endif %}> {{ lang.edit.sogo_redirection }}</label>
|
||||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
<small class="text-muted">{{ lang.edit.sogo_redirection_info }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -10,7 +10,7 @@
|
|||||||
<form class="form-horizontal" data-cached-form="true" data-id="add_mailbox" role="form" autocomplete="off">
|
<form class="form-horizontal" data-cached-form="true" data-id="add_mailbox" role="form" autocomplete="off">
|
||||||
<input type="hidden" value="0" name="force_pw_update">
|
<input type="hidden" value="0" name="force_pw_update">
|
||||||
<input type="hidden" value="0" name="force_tfa">
|
<input type="hidden" value="0" name="force_tfa">
|
||||||
<input type="hidden" value="0" name="sogo_access">
|
<input type="hidden" value="0" name="sogo_redirection">
|
||||||
<input type="hidden" value="0" name="protocol_access">
|
<input type="hidden" value="0" name="protocol_access">
|
||||||
<input type="hidden" value="mailcow" name="authsource">
|
<input type="hidden" value="mailcow" name="authsource">
|
||||||
|
|
||||||
@@ -166,6 +166,7 @@
|
|||||||
<option value="syncjobs">{{ lang.acl["syncjobs"] }}</option>
|
<option value="syncjobs">{{ lang.acl["syncjobs"] }}</option>
|
||||||
<option value="eas_reset" selected>{{ lang.acl["eas_reset"] }}</option>
|
<option value="eas_reset" selected>{{ lang.acl["eas_reset"] }}</option>
|
||||||
<option value="sogo_profile_reset">{{ lang.acl["sogo_profile_reset"] }}</option>
|
<option value="sogo_profile_reset">{{ lang.acl["sogo_profile_reset"] }}</option>
|
||||||
|
<option value="sogo_access" selected>{{ lang.acl["sogo_access"] }}</option>
|
||||||
<option value="pushover" selected>{{ lang.acl["pushover"] }}</option>
|
<option value="pushover" selected>{{ lang.acl["pushover"] }}</option>
|
||||||
<option value="quarantine" selected>{{ lang.acl["quarantine"] }}</option>
|
<option value="quarantine" selected>{{ lang.acl["quarantine"] }}</option>
|
||||||
<option value="quarantine_attachments" selected>{{ lang.acl["quarantine_attachments"] }}</option>
|
<option value="quarantine_attachments" selected>{{ lang.acl["quarantine_attachments"] }}</option>
|
||||||
@@ -217,8 +218,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access" id="sogo_access"> {{ lang.edit.sogo_access }}</label>
|
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_redirection" id="sogo_access"> {{ lang.edit.sogo_redirection }}</label>
|
||||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
<small class="text-muted">{{ lang.edit.sogo_redirection_info }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -247,7 +248,7 @@
|
|||||||
<input type="hidden" value="default" name="sender_acl">
|
<input type="hidden" value="default" name="sender_acl">
|
||||||
<input type="hidden" value="0" name="force_pw_update">
|
<input type="hidden" value="0" name="force_pw_update">
|
||||||
<input type="hidden" value="0" name="force_tfa">
|
<input type="hidden" value="0" name="force_tfa">
|
||||||
<input type="hidden" value="0" name="sogo_access">
|
<input type="hidden" value="0" name="sogo_redirection">
|
||||||
<input type="hidden" value="0" name="protocol_access">
|
<input type="hidden" value="0" name="protocol_access">
|
||||||
|
|
||||||
<div class="row mb-4">
|
<div class="row mb-4">
|
||||||
@@ -416,8 +417,8 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="offset-sm-2 col-sm-10">
|
<div class="offset-sm-2 col-sm-10">
|
||||||
<div class="form-check">
|
<div class="form-check">
|
||||||
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_access"> {{ lang.edit.sogo_access }}</label>
|
<label><input type="checkbox" class="form-check-input" value="1" name="sogo_redirection"> {{ lang.edit.sogo_redirection }}</label>
|
||||||
<small class="text-muted">{{ lang.edit.sogo_access_info }}</small>
|
<small class="text-muted">{{ lang.edit.sogo_redirection_info }}</small>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -23,10 +23,14 @@
|
|||||||
<a href="/sogo-auth.php?login={{ mailcow_cc_username }}" role="button" class="btn btn-primary btn-lg btn-block btn-xs-lg w-100">
|
<a href="/sogo-auth.php?login={{ mailcow_cc_username }}" role="button" class="btn btn-primary btn-lg btn-block btn-xs-lg w-100">
|
||||||
{{ lang.user.open_webmail_sso }} <i class="bi bi-arrow-right"></i>
|
{{ lang.user.open_webmail_sso }} <i class="bi bi-arrow-right"></i>
|
||||||
</a>
|
</a>
|
||||||
{% else %}
|
{% elseif acl.sogo_access == 1 %}
|
||||||
<a href="/SOGo/so" role="button" class="btn btn-primary btn-lg btn-block btn-xs-lg w-100">
|
<a href="/SOGo/so" role="button" class="btn btn-primary btn-lg btn-block btn-xs-lg w-100">
|
||||||
{{ lang.user.open_webmail_sso }} <i class="bi bi-arrow-right"></i>
|
{{ lang.user.open_webmail_sso }} <i class="bi bi-arrow-right"></i>
|
||||||
</a>
|
</a>
|
||||||
|
{% else %}
|
||||||
|
<button disabled class="btn btn-secondary btn-block btn-xs-lg w-100">
|
||||||
|
{{ lang.user.open_webmail_sso }} <i class="bi bi-arrow-right"></i>
|
||||||
|
</button>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
+2
-2
@@ -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
|
||||||
@@ -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:
|
||||||
|
|||||||
Reference in New Issue
Block a user