Compare commits
23 Commits
feat/f2b-b
...
2023-07
Author | SHA1 | Date | |
---|---|---|---|
|
a8bc4e3f37 | ||
|
815572f200 | ||
|
23fc54f2cf | ||
|
11407973b1 | ||
|
b9867e3fe0 | ||
|
3814c3294f | ||
|
9c44b5e546 | ||
|
cd635ec813 | ||
|
03831149f8 | ||
|
521120a448 | ||
|
ec8d298c36 | ||
|
03580cbf39 | ||
|
2b009c71c1 | ||
|
b903cf3888 | ||
|
6e9c024b3c | ||
|
8cd4ae1e34 | ||
|
689856b186 | ||
|
7b645303d6 | ||
|
408381bddb | ||
|
380cdab6fc | ||
|
03b7a8d639 | ||
|
bf6a61fa2d | ||
|
1de47072f8 |
1
.gitignore
vendored
1
.gitignore
vendored
@@ -36,6 +36,7 @@ data/conf/postfix/extra.cf
|
|||||||
data/conf/postfix/sni.map
|
data/conf/postfix/sni.map
|
||||||
data/conf/postfix/sni.map.db
|
data/conf/postfix/sni.map.db
|
||||||
data/conf/postfix/sql
|
data/conf/postfix/sql
|
||||||
|
data/conf/postfix/dns_blocklists.cf
|
||||||
data/conf/rspamd/custom/*
|
data/conf/rspamd/custom/*
|
||||||
data/conf/rspamd/local.d/*
|
data/conf/rspamd/local.d/*
|
||||||
data/conf/rspamd/override.d/*
|
data/conf/rspamd/override.d/*
|
||||||
|
@@ -16,7 +16,6 @@ import json
|
|||||||
import iptc
|
import iptc
|
||||||
import dns.resolver
|
import dns.resolver
|
||||||
import dns.exception
|
import dns.exception
|
||||||
import uuid
|
|
||||||
|
|
||||||
while True:
|
while True:
|
||||||
try:
|
try:
|
||||||
@@ -95,8 +94,6 @@ def verifyF2boptions(f2boptions):
|
|||||||
verifyF2boption(f2boptions,'retry_window', 600)
|
verifyF2boption(f2boptions,'retry_window', 600)
|
||||||
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
||||||
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
||||||
verifyF2boption(f2boptions,'banlist_id', str(uuid.uuid4()))
|
|
||||||
verifyF2boption(f2boptions,'manage_external', 0)
|
|
||||||
|
|
||||||
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
||||||
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
||||||
@@ -159,7 +156,6 @@ def mailcowChainOrder():
|
|||||||
exit_code = 2
|
exit_code = 2
|
||||||
|
|
||||||
def ban(address):
|
def ban(address):
|
||||||
global f2boptions
|
|
||||||
global lock
|
global lock
|
||||||
refreshF2boptions()
|
refreshF2boptions()
|
||||||
BAN_TIME = int(f2boptions['ban_time'])
|
BAN_TIME = int(f2boptions['ban_time'])
|
||||||
@@ -201,7 +197,7 @@ def ban(address):
|
|||||||
cur_time = int(round(time.time()))
|
cur_time = int(round(time.time()))
|
||||||
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||||
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
||||||
if type(ip) is ipaddress.IPv4Address and int(f2boptions['manage_external']) != 1:
|
if type(ip) is ipaddress.IPv4Address:
|
||||||
with lock:
|
with lock:
|
||||||
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW')
|
chain = iptc.Chain(iptc.Table(iptc.Table.FILTER), 'MAILCOW')
|
||||||
rule = iptc.Rule()
|
rule = iptc.Rule()
|
||||||
@@ -210,7 +206,7 @@ def ban(address):
|
|||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules:
|
if rule not in chain.rules:
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
elif int(f2boptions['manage_external']) != 1:
|
else:
|
||||||
with lock:
|
with lock:
|
||||||
chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW')
|
chain = iptc.Chain(iptc.Table6(iptc.Table6.FILTER), 'MAILCOW')
|
||||||
rule = iptc.Rule6()
|
rule = iptc.Rule6()
|
||||||
@@ -255,7 +251,6 @@ def unban(net):
|
|||||||
bans[net]['ban_counter'] += 1
|
bans[net]['ban_counter'] += 1
|
||||||
|
|
||||||
def permBan(net, unban=False):
|
def permBan(net, unban=False):
|
||||||
global f2boptions
|
|
||||||
global lock
|
global lock
|
||||||
if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network:
|
if type(ipaddress.ip_network(net, strict=False)) is ipaddress.IPv4Network:
|
||||||
with lock:
|
with lock:
|
||||||
@@ -264,7 +259,7 @@ def permBan(net, unban=False):
|
|||||||
rule.src = net
|
rule.src = net
|
||||||
target = iptc.Target(rule, "REJECT")
|
target = iptc.Target(rule, "REJECT")
|
||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules and not unban and int(f2boptions['manage_external']) != 1:
|
if rule not in chain.rules and not unban:
|
||||||
logCrit('Add host/network %s to blacklist' % net)
|
logCrit('Add host/network %s to blacklist' % net)
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||||
@@ -279,7 +274,7 @@ def permBan(net, unban=False):
|
|||||||
rule.src = net
|
rule.src = net
|
||||||
target = iptc.Target(rule, "REJECT")
|
target = iptc.Target(rule, "REJECT")
|
||||||
rule.target = target
|
rule.target = target
|
||||||
if rule not in chain.rules and not unban and int(f2boptions['manage_external']) != 1:
|
if rule not in chain.rules and not unban:
|
||||||
logCrit('Add host/network %s to blacklist' % net)
|
logCrit('Add host/network %s to blacklist' % net)
|
||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
r.hset('F2B_PERM_BANS', '%s' % net, int(round(time.time())))
|
||||||
@@ -558,7 +553,7 @@ def initChain():
|
|||||||
chain.insert_rule(rule)
|
chain.insert_rule(rule)
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
refreshF2boptions()
|
|
||||||
# In case a previous session was killed without cleanup
|
# In case a previous session was killed without cleanup
|
||||||
clear()
|
clear()
|
||||||
# Reinit MAILCOW chain
|
# Reinit MAILCOW chain
|
||||||
|
@@ -33,6 +33,7 @@ RUN groupadd -g 102 postfix \
|
|||||||
syslog-ng-core \
|
syslog-ng-core \
|
||||||
syslog-ng-mod-redis \
|
syslog-ng-mod-redis \
|
||||||
tzdata \
|
tzdata \
|
||||||
|
whois \
|
||||||
&& rm -rf /var/lib/apt/lists/* \
|
&& rm -rf /var/lib/apt/lists/* \
|
||||||
&& touch /etc/default/locale \
|
&& touch /etc/default/locale \
|
||||||
&& printf '#!/bin/bash\n/usr/sbin/postconf -c /opt/postfix/conf "$@"' > /usr/local/sbin/postconf \
|
&& printf '#!/bin/bash\n/usr/sbin/postconf -c /opt/postfix/conf "$@"' > /usr/local/sbin/postconf \
|
||||||
|
@@ -393,6 +393,111 @@ query = SELECT goto FROM spamalias
|
|||||||
AND validity >= UNIX_TIMESTAMP()
|
AND validity >= UNIX_TIMESTAMP()
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
|
if [ -n "$SPAMHAUS_DQS_KEY" ]; then
|
||||||
|
echo -e "\e[32mDetected SPAMHAUS_DQS_KEY variable from mailcow.conf...\e[0m"
|
||||||
|
echo -e "\e[33mUsing DQS Blocklists from Spamhaus!\e[0m"
|
||||||
|
cat <<EOF > /opt/postfix/conf/dns_blocklists.cf
|
||||||
|
# Autogenerated by mailcow
|
||||||
|
postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.1*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].0*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].1*-4
|
||||||
|
list.dnswl.org=127.0.[0..255].2*-6
|
||||||
|
list.dnswl.org=127.0.[0..255].3*-8
|
||||||
|
ix.dnsbl.manitu.net*2
|
||||||
|
bl.spamcop.net*2
|
||||||
|
bl.suomispam.net*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.2*3
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.4*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.1.2*1
|
||||||
|
backscatter.spameatingmonkey.net*2
|
||||||
|
bl.ipv6.spameatingmonkey.net*2
|
||||||
|
bl.spameatingmonkey.net*2
|
||||||
|
b.barracudacentral.org=127.0.0.2*7
|
||||||
|
bl.mailspike.net=127.0.0.2*5
|
||||||
|
bl.mailspike.net=127.0.0.[10;11;12]*4
|
||||||
|
dnsbl.sorbs.net=127.0.0.10*8
|
||||||
|
dnsbl.sorbs.net=127.0.0.5*6
|
||||||
|
dnsbl.sorbs.net=127.0.0.7*3
|
||||||
|
dnsbl.sorbs.net=127.0.0.8*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.6*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.9*2
|
||||||
|
${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.net=127.0.0.[4..7]*6
|
||||||
|
${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.[10;11]*8
|
||||||
|
${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.3*4
|
||||||
|
${SPAMHAUS_DQS_KEY}.zen.dq.spamhaus.org=127.0.0.2*3
|
||||||
|
${SPAMHAUS_DQS_KEY}.dbl.dq.spamhaus.net=127.0.0.3*4
|
||||||
|
${SPAMHAUS_DQS_KEY}.zrd.dq.spamhaus.net=127.0.0.2*3
|
||||||
|
EOF
|
||||||
|
|
||||||
|
else
|
||||||
|
if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null; then
|
||||||
|
echo -e "\e[31mThe AS of your IP is listed as a banned AS from Spamhaus!\e[0m"
|
||||||
|
echo -e "\e[33mNo SPAMHAUS_DQS_KEY found... Skipping Spamhaus blocklists entirely!\e[0m"
|
||||||
|
cat <<EOF > /opt/postfix/conf/dns_blocklists.cf
|
||||||
|
# Autogenerated by mailcow
|
||||||
|
postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.1*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].0*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].1*-4
|
||||||
|
list.dnswl.org=127.0.[0..255].2*-6
|
||||||
|
list.dnswl.org=127.0.[0..255].3*-8
|
||||||
|
ix.dnsbl.manitu.net*2
|
||||||
|
bl.spamcop.net*2
|
||||||
|
bl.suomispam.net*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.2*3
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.4*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.1.2*1
|
||||||
|
backscatter.spameatingmonkey.net*2
|
||||||
|
bl.ipv6.spameatingmonkey.net*2
|
||||||
|
bl.spameatingmonkey.net*2
|
||||||
|
b.barracudacentral.org=127.0.0.2*7
|
||||||
|
bl.mailspike.net=127.0.0.2*5
|
||||||
|
bl.mailspike.net=127.0.0.[10;11;12]*4
|
||||||
|
dnsbl.sorbs.net=127.0.0.10*8
|
||||||
|
dnsbl.sorbs.net=127.0.0.5*6
|
||||||
|
dnsbl.sorbs.net=127.0.0.7*3
|
||||||
|
dnsbl.sorbs.net=127.0.0.8*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.6*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.9*2
|
||||||
|
EOF
|
||||||
|
else
|
||||||
|
echo -e "\e[32mThe AS of your IP is NOT listed as a banned AS from Spamhaus!\e[0m"
|
||||||
|
echo -e "\e[33mUsing the open Spamhaus blocklists.\e[0m"
|
||||||
|
cat <<EOF > /opt/postfix/conf/dns_blocklists.cf
|
||||||
|
# Autogenerated by mailcow
|
||||||
|
postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.1*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].0*-2
|
||||||
|
list.dnswl.org=127.0.[0..255].1*-4
|
||||||
|
list.dnswl.org=127.0.[0..255].2*-6
|
||||||
|
list.dnswl.org=127.0.[0..255].3*-8
|
||||||
|
ix.dnsbl.manitu.net*2
|
||||||
|
bl.spamcop.net*2
|
||||||
|
bl.suomispam.net*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.2*3
|
||||||
|
hostkarma.junkemailfilter.com=127.0.0.4*2
|
||||||
|
hostkarma.junkemailfilter.com=127.0.1.2*1
|
||||||
|
backscatter.spameatingmonkey.net*2
|
||||||
|
bl.ipv6.spameatingmonkey.net*2
|
||||||
|
bl.spameatingmonkey.net*2
|
||||||
|
b.barracudacentral.org=127.0.0.2*7
|
||||||
|
bl.mailspike.net=127.0.0.2*5
|
||||||
|
bl.mailspike.net=127.0.0.[10;11;12]*4
|
||||||
|
dnsbl.sorbs.net=127.0.0.10*8
|
||||||
|
dnsbl.sorbs.net=127.0.0.5*6
|
||||||
|
dnsbl.sorbs.net=127.0.0.7*3
|
||||||
|
dnsbl.sorbs.net=127.0.0.8*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.6*2
|
||||||
|
dnsbl.sorbs.net=127.0.0.9*2
|
||||||
|
zen.spamhaus.org=127.0.0.[10;11]*8
|
||||||
|
zen.spamhaus.org=127.0.0.[4..7]*6
|
||||||
|
zen.spamhaus.org=127.0.0.3*4
|
||||||
|
zen.spamhaus.org=127.0.0.2*3
|
||||||
|
EOF
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
|
||||||
sed -i '/User overrides/q' /opt/postfix/conf/main.cf
|
sed -i '/User overrides/q' /opt/postfix/conf/main.cf
|
||||||
echo >> /opt/postfix/conf/main.cf
|
echo >> /opt/postfix/conf/main.cf
|
||||||
touch /opt/postfix/conf/extra.cf
|
touch /opt/postfix/conf/extra.cf
|
||||||
|
@@ -40,34 +40,6 @@ postscreen_blacklist_action = drop
|
|||||||
postscreen_cache_cleanup_interval = 24h
|
postscreen_cache_cleanup_interval = 24h
|
||||||
postscreen_cache_map = proxy:btree:$data_directory/postscreen_cache
|
postscreen_cache_map = proxy:btree:$data_directory/postscreen_cache
|
||||||
postscreen_dnsbl_action = enforce
|
postscreen_dnsbl_action = enforce
|
||||||
postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
|
|
||||||
hostkarma.junkemailfilter.com=127.0.0.1*-2
|
|
||||||
list.dnswl.org=127.0.[0..255].0*-2
|
|
||||||
list.dnswl.org=127.0.[0..255].1*-4
|
|
||||||
list.dnswl.org=127.0.[0..255].2*-6
|
|
||||||
list.dnswl.org=127.0.[0..255].3*-8
|
|
||||||
ix.dnsbl.manitu.net*2
|
|
||||||
bl.spamcop.net*2
|
|
||||||
bl.suomispam.net*2
|
|
||||||
hostkarma.junkemailfilter.com=127.0.0.2*3
|
|
||||||
hostkarma.junkemailfilter.com=127.0.0.4*2
|
|
||||||
hostkarma.junkemailfilter.com=127.0.1.2*1
|
|
||||||
backscatter.spameatingmonkey.net*2
|
|
||||||
bl.ipv6.spameatingmonkey.net*2
|
|
||||||
bl.spameatingmonkey.net*2
|
|
||||||
b.barracudacentral.org=127.0.0.2*7
|
|
||||||
bl.mailspike.net=127.0.0.2*5
|
|
||||||
bl.mailspike.net=127.0.0.[10;11;12]*4
|
|
||||||
dnsbl.sorbs.net=127.0.0.10*8
|
|
||||||
dnsbl.sorbs.net=127.0.0.5*6
|
|
||||||
dnsbl.sorbs.net=127.0.0.7*3
|
|
||||||
dnsbl.sorbs.net=127.0.0.8*2
|
|
||||||
dnsbl.sorbs.net=127.0.0.6*2
|
|
||||||
dnsbl.sorbs.net=127.0.0.9*2
|
|
||||||
zen.spamhaus.org=127.0.0.[10;11]*8
|
|
||||||
zen.spamhaus.org=127.0.0.[4..7]*6
|
|
||||||
zen.spamhaus.org=127.0.0.3*4
|
|
||||||
zen.spamhaus.org=127.0.0.2*3
|
|
||||||
postscreen_dnsbl_threshold = 6
|
postscreen_dnsbl_threshold = 6
|
||||||
postscreen_dnsbl_ttl = 5m
|
postscreen_dnsbl_ttl = 5m
|
||||||
postscreen_greet_action = enforce
|
postscreen_greet_action = enforce
|
||||||
|
@@ -68,3 +68,39 @@ WL_FWD_HOST {
|
|||||||
ENCRYPTED_CHAT {
|
ENCRYPTED_CHAT {
|
||||||
expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP";
|
expression = "CHAT_VERSION_HEADER & ENCRYPTED_PGP";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CLAMD_SPAM_FOUND {
|
||||||
|
expression = "CLAM_SECI_SPAM & !MAILCOW_WHITE";
|
||||||
|
description = "Probably Spam, Securite Spam Flag set through ClamAV";
|
||||||
|
score = 5;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAMD_BAD_PDF {
|
||||||
|
expression = "CLAM_SECI_PDF & !MAILCOW_WHITE";
|
||||||
|
description = "Bad PDF Found, Securite bad PDF Flag set through ClamAV";
|
||||||
|
score = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAMD_BAD_JPG {
|
||||||
|
expression = "CLAM_SECI_JPG & !MAILCOW_WHITE";
|
||||||
|
description = "Bad JPG Found, Securite bad JPG Flag set through ClamAV";
|
||||||
|
score = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAMD_ASCII_MALWARE {
|
||||||
|
expression = "CLAM_SECI_ASCII & !MAILCOW_WHITE";
|
||||||
|
description = "ASCII malware found, Securite ASCII malware Flag set through ClamAV";
|
||||||
|
score = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAMD_HTML_MALWARE {
|
||||||
|
expression = "CLAM_SECI_HTML & !MAILCOW_WHITE";
|
||||||
|
description = "HTML malware found, Securite HTML malware Flag set through ClamAV";
|
||||||
|
score = 8;
|
||||||
|
}
|
||||||
|
|
||||||
|
CLAMD_JS_MALWARE {
|
||||||
|
expression = "CLAM_SECI_JS & !MAILCOW_WHITE";
|
||||||
|
description = "JS malware found, Securite JS malware Flag set through ClamAV";
|
||||||
|
score = 8;
|
||||||
|
}
|
@@ -85,8 +85,6 @@ $cors_settings = cors('get');
|
|||||||
$cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allowed_origins']);
|
$cors_settings['allowed_origins'] = str_replace(", ", "\n", $cors_settings['allowed_origins']);
|
||||||
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
$cors_settings['allowed_methods'] = explode(", ", $cors_settings['allowed_methods']);
|
||||||
|
|
||||||
$f2b_data = fail2ban('get');
|
|
||||||
|
|
||||||
$template = 'admin.twig';
|
$template = 'admin.twig';
|
||||||
$template_data = [
|
$template_data = [
|
||||||
'tfa_data' => $tfa_data,
|
'tfa_data' => $tfa_data,
|
||||||
@@ -103,8 +101,7 @@ $template_data = [
|
|||||||
'domains' => $domains,
|
'domains' => $domains,
|
||||||
'all_domains' => $all_domains,
|
'all_domains' => $all_domains,
|
||||||
'mailboxes' => $mailboxes,
|
'mailboxes' => $mailboxes,
|
||||||
'f2b_data' => $f2b_data,
|
'f2b_data' => fail2ban('get'),
|
||||||
'f2b_banlist_url' => getBaseUrl() . "/api/v1/get/fail2ban/banlist/" . $f2b_data['banlist_id'],
|
|
||||||
'q_data' => quarantine('settings'),
|
'q_data' => quarantine('settings'),
|
||||||
'qn_data' => quota_notification('get'),
|
'qn_data' => quota_notification('get'),
|
||||||
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),
|
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),
|
||||||
@@ -115,7 +112,6 @@ $template_data = [
|
|||||||
'password_complexity' => password_complexity('get'),
|
'password_complexity' => password_complexity('get'),
|
||||||
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
'show_rspamd_global_filters' => @$_SESSION['show_rspamd_global_filters'],
|
||||||
'cors_settings' => $cors_settings,
|
'cors_settings' => $cors_settings,
|
||||||
'is_https' => isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on',
|
|
||||||
'lang_admin' => json_encode($lang['admin']),
|
'lang_admin' => json_encode($lang['admin']),
|
||||||
'lang_datatables' => json_encode($lang['datatables'])
|
'lang_datatables' => json_encode($lang['datatables'])
|
||||||
];
|
];
|
||||||
|
@@ -5602,6 +5602,50 @@ paths:
|
|||||||
description: You can list all mailboxes existing in system for a specific domain.
|
description: You can list all mailboxes existing in system for a specific domain.
|
||||||
operationId: Get mailboxes of a domain
|
operationId: Get mailboxes of a domain
|
||||||
summary: Get mailboxes of a domain
|
summary: Get mailboxes of a domain
|
||||||
|
/api/v1/edit/cors:
|
||||||
|
post:
|
||||||
|
responses:
|
||||||
|
"401":
|
||||||
|
$ref: "#/components/responses/Unauthorized"
|
||||||
|
"200":
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
examples:
|
||||||
|
response:
|
||||||
|
value:
|
||||||
|
- type: "success"
|
||||||
|
log: ["cors", "edit", {"allowed_origins": ["*", "mail.mailcow.tld"], "allowed_methods": ["POST", "GET", "DELETE", "PUT"]}]
|
||||||
|
msg: "cors_headers_edited"
|
||||||
|
description: OK
|
||||||
|
headers: { }
|
||||||
|
tags:
|
||||||
|
- Cross-Origin Resource Sharing (CORS)
|
||||||
|
description: >-
|
||||||
|
This endpoint allows you to manage Cross-Origin Resource Sharing (CORS) settings for the API.
|
||||||
|
CORS is a security feature implemented by web browsers to prevent unauthorized cross-origin requests.
|
||||||
|
By editing the CORS settings, you can specify which domains and which methods are permitted to access the API resources from outside the mailcow domain.
|
||||||
|
operationId: Edit Cross-Origin Resource Sharing (CORS) settings
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
example:
|
||||||
|
attr:
|
||||||
|
allowed_origins: ["*", "mail.mailcow.tld"]
|
||||||
|
allowed_methods: ["POST", "GET", "DELETE", "PUT"]
|
||||||
|
properties:
|
||||||
|
attr:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
allowed_origins:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
allowed_methods:
|
||||||
|
type: array
|
||||||
|
items:
|
||||||
|
type: string
|
||||||
|
summary: Edit Cross-Origin Resource Sharing (CORS) settings
|
||||||
|
|
||||||
tags:
|
tags:
|
||||||
- name: Domains
|
- name: Domains
|
||||||
@@ -5646,3 +5690,5 @@ tags:
|
|||||||
description: Get the status of your cow
|
description: Get the status of your cow
|
||||||
- name: Ratelimits
|
- name: Ratelimits
|
||||||
description: Edit domain ratelimits
|
description: Edit domain ratelimits
|
||||||
|
- name: Cross-Origin Resource Sharing (CORS)
|
||||||
|
description: Manage Cross-Origin Resource Sharing (CORS) settings
|
||||||
|
@@ -1,5 +1,5 @@
|
|||||||
<?php
|
<?php
|
||||||
function fail2ban($_action, $_data = null, $_extra = null) {
|
function fail2ban($_action, $_data = null) {
|
||||||
global $redis;
|
global $redis;
|
||||||
$_data_log = $_data;
|
$_data_log = $_data;
|
||||||
switch ($_action) {
|
switch ($_action) {
|
||||||
@@ -247,7 +247,6 @@ function fail2ban($_action, $_data = null, $_extra = null) {
|
|||||||
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
||||||
$wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist'];
|
$wl = (isset($_data['whitelist'])) ? $_data['whitelist'] : $is_now['whitelist'];
|
||||||
$bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist'];
|
$bl = (isset($_data['blacklist'])) ? $_data['blacklist'] : $is_now['blacklist'];
|
||||||
$manage_external = (isset($_data['manage_external'])) ? intval($_data['manage_external']) : 0;
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
@@ -267,8 +266,6 @@ function fail2ban($_action, $_data = null, $_extra = null) {
|
|||||||
$f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
|
$f2b_options['netban_ipv6'] = ($netban_ipv6 > 128) ? 128 : $netban_ipv6;
|
||||||
$f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts;
|
$f2b_options['max_attempts'] = ($max_attempts < 1) ? 1 : $max_attempts;
|
||||||
$f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window;
|
$f2b_options['retry_window'] = ($retry_window < 1) ? 1 : $retry_window;
|
||||||
$f2b_options['banlist_id'] = $is_now['banlist_id'];
|
|
||||||
$f2b_options['manage_external'] = ($manage_external > 0) ? 1 : 0;
|
|
||||||
try {
|
try {
|
||||||
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
||||||
$redis->Del('F2B_WHITELIST');
|
$redis->Del('F2B_WHITELIST');
|
||||||
@@ -332,71 +329,5 @@ function fail2ban($_action, $_data = null, $_extra = null) {
|
|||||||
'msg' => 'f2b_modified'
|
'msg' => 'f2b_modified'
|
||||||
);
|
);
|
||||||
break;
|
break;
|
||||||
case 'banlist':
|
|
||||||
try {
|
|
||||||
$f2b_options = json_decode($redis->Get('F2B_OPTIONS'), true);
|
|
||||||
}
|
|
||||||
catch (RedisException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
|
||||||
'msg' => array('redis_error', $e)
|
|
||||||
);
|
|
||||||
http_response_code(500);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
if (is_array($_extra)) {
|
|
||||||
$_extra = $_extra[0];
|
|
||||||
}
|
|
||||||
if ($_extra != $f2b_options['banlist_id']){
|
|
||||||
http_response_code(404);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ($_data) {
|
|
||||||
case 'get':
|
|
||||||
try {
|
|
||||||
$bl = $redis->hKeys('F2B_BLACKLIST');
|
|
||||||
$active_bans = $redis->hKeys('F2B_ACTIVE_BANS');
|
|
||||||
}
|
|
||||||
catch (RedisException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
|
||||||
'msg' => array('redis_error', $e)
|
|
||||||
);
|
|
||||||
http_response_code(500);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
$banlist = implode("\n", array_merge($bl, $active_bans));
|
|
||||||
return $banlist;
|
|
||||||
break;
|
|
||||||
case 'refresh':
|
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$f2b_options['banlist_id'] = uuid4();
|
|
||||||
try {
|
|
||||||
$redis->Set('F2B_OPTIONS', json_encode($f2b_options));
|
|
||||||
}
|
|
||||||
catch (RedisException $e) {
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'danger',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
|
||||||
'msg' => array('redis_error', $e)
|
|
||||||
);
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
$_SESSION['return'][] = array(
|
|
||||||
'type' => 'success',
|
|
||||||
'log' => array(__FUNCTION__, $_action, $_data_log, $_extra),
|
|
||||||
'msg' => 'f2b_banlist_refreshed'
|
|
||||||
);
|
|
||||||
return true;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -2246,21 +2246,6 @@ function cors($action, $data = null) {
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function getBaseURL() {
|
|
||||||
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
|
|
||||||
$host = $_SERVER['HTTP_HOST'];
|
|
||||||
$base_url = $protocol . '://' . $host;
|
|
||||||
|
|
||||||
return $base_url;
|
|
||||||
}
|
|
||||||
function uuid4() {
|
|
||||||
$data = openssl_random_pseudo_bytes(16);
|
|
||||||
|
|
||||||
$data[6] = chr(ord($data[6]) & 0x0f | 0x40);
|
|
||||||
$data[8] = chr(ord($data[8]) & 0x3f | 0x80);
|
|
||||||
|
|
||||||
return vsprintf('%s%s-%s-%s-%s-%s%s%s', str_split(bin2hex($data), 4));
|
|
||||||
}
|
|
||||||
|
|
||||||
function get_logs($application, $lines = false) {
|
function get_logs($application, $lines = false) {
|
||||||
if ($lines === false) {
|
if ($lines === false) {
|
||||||
|
@@ -70,8 +70,6 @@ try {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
catch (Exception $e) {
|
catch (Exception $e) {
|
||||||
// Stop when redis is not available
|
|
||||||
http_response_code(500);
|
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to Redis failed.<br /><br />The following error was reported:<br/><?=$e->getMessage();?></center>
|
<center style='font-family:sans-serif;'>Connection to Redis failed.<br /><br />The following error was reported:<br/><?=$e->getMessage();?></center>
|
||||||
<?php
|
<?php
|
||||||
@@ -100,7 +98,6 @@ try {
|
|||||||
}
|
}
|
||||||
catch (PDOException $e) {
|
catch (PDOException $e) {
|
||||||
// Stop when SQL connection fails
|
// Stop when SQL connection fails
|
||||||
http_response_code(500);
|
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
<center style='font-family:sans-serif;'>Connection to database failed.<br /><br />The following error was reported:<br/> <?=$e->getMessage();?></center>
|
||||||
<?php
|
<?php
|
||||||
@@ -108,7 +105,6 @@ exit;
|
|||||||
}
|
}
|
||||||
// Stop when dockerapi is not available
|
// Stop when dockerapi is not available
|
||||||
if (fsockopen("tcp://dockerapi", 443, $errno, $errstr) === false) {
|
if (fsockopen("tcp://dockerapi", 443, $errno, $errstr) === false) {
|
||||||
http_response_code(500);
|
|
||||||
?>
|
?>
|
||||||
<center style='font-family:sans-serif;'>Connection to dockerapi container failed.<br /><br />The following error was reported:<br/><?=$errno;?> - <?=$errstr;?></center>
|
<center style='font-family:sans-serif;'>Connection to dockerapi container failed.<br /><br />The following error was reported:<br/><?=$errno;?> - <?=$errstr;?></center>
|
||||||
<?php
|
<?php
|
||||||
|
@@ -371,11 +371,3 @@ function addTag(tagAddElem, tag = null){
|
|||||||
$(tagValuesElem).val(JSON.stringify(value_tags));
|
$(tagValuesElem).val(JSON.stringify(value_tags));
|
||||||
$(tagInputElem).val('');
|
$(tagInputElem).val('');
|
||||||
}
|
}
|
||||||
function copyToClipboard(id) {
|
|
||||||
var copyText = document.getElementById(id);
|
|
||||||
copyText.select();
|
|
||||||
copyText.setSelectionRange(0, 99999);
|
|
||||||
// only works with https connections
|
|
||||||
navigator.clipboard.writeText(copyText.value);
|
|
||||||
mailcow_alert_box(lang.copy_to_clipboard, "success");
|
|
||||||
}
|
|
@@ -504,16 +504,6 @@ if (isset($_GET['query'])) {
|
|||||||
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
$_SESSION['challenge'] = $WebAuthn->getChallenge();
|
||||||
return;
|
return;
|
||||||
break;
|
break;
|
||||||
case "fail2ban":
|
|
||||||
if (!isset($_SESSION['mailcow_cc_role'])){
|
|
||||||
switch ($object) {
|
|
||||||
case 'banlist':
|
|
||||||
header('Content-Type: text/plain');
|
|
||||||
echo fail2ban('banlist', 'get', $extra);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||||
switch ($category) {
|
switch ($category) {
|
||||||
@@ -1334,10 +1324,6 @@ if (isset($_GET['query'])) {
|
|||||||
break;
|
break;
|
||||||
case "fail2ban":
|
case "fail2ban":
|
||||||
switch ($object) {
|
switch ($object) {
|
||||||
case 'banlist':
|
|
||||||
header('Content-Type: text/plain');
|
|
||||||
echo fail2ban('banlist', 'get', $extra);
|
|
||||||
break;
|
|
||||||
default:
|
default:
|
||||||
$data = fail2ban('get');
|
$data = fail2ban('get');
|
||||||
process_get_return($data);
|
process_get_return($data);
|
||||||
@@ -1944,15 +1930,8 @@ if (isset($_GET['query'])) {
|
|||||||
process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
|
process_edit_return(fwdhost('edit', array_merge(array('fwdhost' => $items), $attr)));
|
||||||
break;
|
break;
|
||||||
case "fail2ban":
|
case "fail2ban":
|
||||||
switch ($object) {
|
|
||||||
case 'banlist':
|
|
||||||
process_edit_return(fail2ban('banlist', 'refresh', $items));
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
|
process_edit_return(fail2ban('edit', array_merge(array('network' => $items), $attr)));
|
||||||
break;
|
break;
|
||||||
}
|
|
||||||
break;
|
|
||||||
case "ui_texts":
|
case "ui_texts":
|
||||||
process_edit_return(customize('edit', 'ui_texts', $attr));
|
process_edit_return(customize('edit', 'ui_texts', $attr));
|
||||||
break;
|
break;
|
||||||
|
@@ -147,7 +147,6 @@
|
|||||||
"change_logo": "Logo ändern",
|
"change_logo": "Logo ändern",
|
||||||
"configuration": "Konfiguration",
|
"configuration": "Konfiguration",
|
||||||
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
"convert_html_to_text": "Konvertiere HTML zu reinem Text",
|
||||||
"copy_to_clipboard": "Text wurde in die Zwischenablage kopiert!",
|
|
||||||
"cors_settings": "CORS Einstellungen",
|
"cors_settings": "CORS Einstellungen",
|
||||||
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
"credentials_transport_warning": "<b>Warnung</b>: Das Hinzufügen einer neuen Regel bewirkt die Aktualisierung der Authentifizierungsdaten aller vorhandenen Einträge mit identischem Next Hop.",
|
||||||
"customer_id": "Kunde",
|
"customer_id": "Kunde",
|
||||||
@@ -181,8 +180,6 @@
|
|||||||
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
||||||
"f2b_filter": "Regex-Filter",
|
"f2b_filter": "Regex-Filter",
|
||||||
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
||||||
"f2b_manage_external": "Fail2Ban extern verwalten",
|
|
||||||
"f2b_manage_external_info": "Fail2ban wird die Banlist weiterhin pflegen, jedoch werden keine aktiven Regeln zum blockieren gesetzt. Die unten generierte Banlist, kann verwendet werden, um den Datenverkehr extern zu blockieren.",
|
|
||||||
"f2b_max_attempts": "Max. Versuche",
|
"f2b_max_attempts": "Max. Versuche",
|
||||||
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
||||||
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
||||||
@@ -1022,7 +1019,6 @@
|
|||||||
"domain_removed": "Domain %s wurde entfernt",
|
"domain_removed": "Domain %s wurde entfernt",
|
||||||
"dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet",
|
"dovecot_restart_success": "Dovecot wurde erfolgreich neu gestartet",
|
||||||
"eas_reset": "ActiveSync Gerät des Benutzers %s wurde zurückgesetzt",
|
"eas_reset": "ActiveSync Gerät des Benutzers %s wurde zurückgesetzt",
|
||||||
"f2b_banlist_refreshed": "Banlist ID wurde erfolgreich erneuert.",
|
|
||||||
"f2b_modified": "Änderungen an Fail2ban-Parametern wurden gespeichert",
|
"f2b_modified": "Änderungen an Fail2ban-Parametern wurden gespeichert",
|
||||||
"forwarding_host_added": "Weiterleitungs-Host %s wurde hinzugefügt",
|
"forwarding_host_added": "Weiterleitungs-Host %s wurde hinzugefügt",
|
||||||
"forwarding_host_removed": "Weiterleitungs-Host %s wurde entfernt",
|
"forwarding_host_removed": "Weiterleitungs-Host %s wurde entfernt",
|
||||||
|
@@ -151,7 +151,6 @@
|
|||||||
"change_logo": "Change logo",
|
"change_logo": "Change logo",
|
||||||
"configuration": "Configuration",
|
"configuration": "Configuration",
|
||||||
"convert_html_to_text": "Convert HTML to plain text",
|
"convert_html_to_text": "Convert HTML to plain text",
|
||||||
"copy_to_clipboard": "Text copied to clipboard!",
|
|
||||||
"cors_settings": "CORS Settings",
|
"cors_settings": "CORS Settings",
|
||||||
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
"credentials_transport_warning": "<b>Warning</b>: Adding a new transport map entry will update the credentials for all entries with a matching next hop column.",
|
||||||
"customer_id": "Customer ID",
|
"customer_id": "Customer ID",
|
||||||
@@ -185,8 +184,6 @@
|
|||||||
"f2b_blacklist": "Blacklisted networks/hosts",
|
"f2b_blacklist": "Blacklisted networks/hosts",
|
||||||
"f2b_filter": "Regex filters",
|
"f2b_filter": "Regex filters",
|
||||||
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
||||||
"f2b_manage_external": "Manage Fail2Ban externally",
|
|
||||||
"f2b_manage_external_info": "Fail2ban will still maintain the banlist, but it will not actively set rules to block traffic. Use the generated banlist below to externally block the traffic.",
|
|
||||||
"f2b_max_attempts": "Max. attempts",
|
"f2b_max_attempts": "Max. attempts",
|
||||||
"f2b_max_ban_time": "Max. ban time (s)",
|
"f2b_max_ban_time": "Max. ban time (s)",
|
||||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||||
@@ -1031,7 +1028,6 @@
|
|||||||
"domain_removed": "Domain %s has been removed",
|
"domain_removed": "Domain %s has been removed",
|
||||||
"dovecot_restart_success": "Dovecot was restarted successfully",
|
"dovecot_restart_success": "Dovecot was restarted successfully",
|
||||||
"eas_reset": "ActiveSync devices for user %s were reset",
|
"eas_reset": "ActiveSync devices for user %s were reset",
|
||||||
"f2b_banlist_refreshed": "Banlist ID has been successfully refreshed.",
|
|
||||||
"f2b_modified": "Changes to Fail2ban parameters have been saved",
|
"f2b_modified": "Changes to Fail2ban parameters have been saved",
|
||||||
"forwarding_host_added": "Forwarding host %s has been added",
|
"forwarding_host_added": "Forwarding host %s has been added",
|
||||||
"forwarding_host_removed": "Forwarding host %s has been removed",
|
"forwarding_host_removed": "Forwarding host %s has been removed",
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
<div class="tab-pane fade show active" id="tab-config-admins" role="tabpanel" aria-labelledby="tab-config-admins">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header bg-danger text-white d-flex fs-5">
|
<div class="card-header bg-danger text-white d-flex fs-5">
|
||||||
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
<button class="btn d-md-none text-white flex-grow-1 text-start" data-bs-target="#collapse-tab-config-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-admins">
|
||||||
@@ -227,7 +227,7 @@
|
|||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dadmins">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dadmins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dadmins">
|
||||||
{{ lang.admin.domain_admins }}
|
{{ lang.admin.domain_admins }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.domain_admins }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
<div class="tab-pane fade" id="tab-config-customize" role="tabpanel" aria-labelledby="tab-config-customize">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-customize">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-customize" data-bs-toggle="collapse" aria-controls="collapse-tab-config-customize">
|
||||||
{{ lang.admin.customize }}
|
{{ lang.admin.customize }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.customize }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
<div class="tab-pane fade" id="tab-config-dkim" role="tabpanel" aria-labelledby="tab-config-dkim">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-dkim">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-dkim" data-bs-toggle="collapse" aria-controls="collapse-tab-config-dkim">
|
||||||
{{ lang.admin.dkim_keys }}
|
{{ lang.admin.dkim_keys }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.dkim_keys }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
<div class="tab-pane fade" id="tab-config-f2b" role="tabpanel" aria-labelledby="tab-config-f2b">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-f2b">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-f2b" data-bs-toggle="collapse" aria-controls="collapse-tab-config-f2b">
|
||||||
{{ lang.admin.f2b_parameters }}
|
{{ lang.admin.f2b_parameters }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.f2b_parameters }}</span>
|
||||||
@@ -42,13 +42,6 @@
|
|||||||
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
<input type="number" class="form-control" id="f2b_netban_ipv6" name="netban_ipv6" value="{{ f2b_data.netban_ipv6 }}" required>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-4">
|
|
||||||
<div class="form-check form-switch">
|
|
||||||
<input class="form-check-input" type="checkbox" id="f2b_manage_external" value="1" name="manage_external" {% if f2b_data.manage_external == 1 %}checked{% endif %}>
|
|
||||||
<label class="form-check-label" for="f2b_manage_external">{{ lang.admin.f2b_manage_external }}</label>
|
|
||||||
</div>
|
|
||||||
<p class="text-muted">{{ lang.admin.f2b_manage_external_info }}</p>
|
|
||||||
</div>
|
|
||||||
<hr>
|
<hr>
|
||||||
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
<p class="text-muted">{{ lang.admin.f2b_list_info|raw }}</p>
|
||||||
<div class="mb-2">
|
<div class="mb-2">
|
||||||
@@ -97,27 +90,18 @@
|
|||||||
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
{% if not f2b_data.active_bans and not f2b_data.perm_bans %}
|
||||||
<i>{{ lang.admin.no_active_bans }}</i>
|
<i>{{ lang.admin.no_active_bans }}</i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
<form class="form-inline" data-id="f2b_banlist" role="form" method="post">
|
|
||||||
<div class="input-group mb-3">
|
|
||||||
<input type="text" class="form-control" aria-label="Banlist url" value="{{ f2b_banlist_url}}" id="banlist_url">
|
|
||||||
{% if is_https %}
|
|
||||||
<button class="btn btn-secondary" type="button" onclick="copyToClipboard('banlist_url')"><i class="bi bi-clipboard"></i></button>
|
|
||||||
{% endif %}
|
|
||||||
<button class="btn btn-secondary" type="button" data-action="edit_selected" data-item="{{ f2b_data.banlist_id }}" data-id="f2b_banlist" data-api-url='edit/fail2ban/banlist' data-api-attr='{}'><i class="bi bi-arrow-clockwise"></i></button>
|
|
||||||
</div>
|
|
||||||
</form>
|
|
||||||
{% for active_ban in f2b_data.active_bans %}
|
{% for active_ban in f2b_data.active_bans %}
|
||||||
<p>
|
<p>
|
||||||
<span class="badge fs-5 bg-info" style="padding:4px;font-size:85%;">
|
<span class="badge fs-5 bg-info py-0">
|
||||||
<i class="bi bi-funnel-fill"></i>
|
<i class="bi bi-funnel-fill"></i>
|
||||||
<a href="https://bgp.he.net/ip/{{ active_ban.ip }}" target="_blank" style="color:white">
|
<a href="https://bgp.he.net/ip/{{ active_ban.ip }}" target="_blank" style="color:white">
|
||||||
{{ active_ban.network }}
|
{{ active_ban.network }}
|
||||||
</a>
|
</a>
|
||||||
({{ active_ban.banned_until }}) -
|
({{ active_ban.banned_until }}) -
|
||||||
{% if active_ban.queued_for_unban == 0 %}
|
{% if active_ban.queued_for_unban == 0 %}
|
||||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[{{ lang.admin.queue_unban }}]</a>
|
<a class="btn btn-lg btn-link p-0 text-info" data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[{{ lang.admin.queue_unban }}]</a>
|
||||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
|
<a class="btn btn-lg btn-link p-0 text-info" data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
|
||||||
<a data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist (<b>needs restart</b>)]</a>
|
<a class="btn btn-lg btn-link p-0 text-info" data-action="edit_selected" data-item="{{ active_ban.network }}" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist (<b>needs restart</b>)]</a>
|
||||||
{% else %}
|
{% else %}
|
||||||
<i>{{ lang.admin.unban_pending }}</i>
|
<i>{{ lang.admin.unban_pending }}</i>
|
||||||
{% endif %}
|
{% endif %}
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
<div class="tab-pane fade" id="tab-config-fwdhosts" role="tabpanel" aria-labelledby="tab-config-fwdhosts">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-fwdhosts">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-fwdhosts" data-bs-toggle="collapse" aria-controls="collapse-tab-config-fwdhosts">
|
||||||
{{ lang.admin.forwarding_hosts }}
|
{{ lang.admin.forwarding_hosts }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.forwarding_hosts }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
<div class="tab-pane fade" id="tab-config-oauth2" role="tabpanel" aria-labelledby="tab-config-oauth2">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-oauth2">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-oauth2" data-bs-toggle="collapse" aria-controls="collapse-tab-config-oauth2">
|
||||||
{{ lang.admin.oauth2_apps }}
|
{{ lang.admin.oauth2_apps }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.oauth2_apps }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
<div class="tab-pane fade" id="tab-config-password-policy" role="tabpanel" aria-labelledby="tab-config-password-policy">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-password-policy">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-password-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-config-password-policy">
|
||||||
{{ lang.admin.password_policy }}
|
{{ lang.admin.password_policy }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.password_policy }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
<div class="tab-pane fade" id="tab-config-quarantine" role="tabpanel" aria-labelledby="tab-config-quarantine">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quarantine">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quarantine" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quarantine">
|
||||||
{{ lang.admin.quarantine }}
|
{{ lang.admin.quarantine }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.quarantine }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
<div class="tab-pane fade" id="tab-config-quota" role="tabpanel" aria-labelledby="tab-config-quota">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-quota">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-quota" data-bs-toggle="collapse" aria-controls="collapse-tab-config-quota">
|
||||||
{{ lang.admin.quota_notifications }}
|
{{ lang.admin.quota_notifications }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.quota_notifications }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
<div class="tab-pane fade" id="tab-config-rsettings" role="tabpanel" aria-labelledby="tab-config-rsettings">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-rsettings">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rsettings" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rsettings">
|
||||||
{{ lang.admin.rspamd_settings_map }}
|
{{ lang.admin.rspamd_settings_map }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.rspamd_settings_map }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-rspamd" role="tabpanel" aria-labelledby="tab-config-rspamd">
|
<div class="tab-pane fade" id="tab-config-rspamd" role="tabpanel" aria-labelledby="tab-config-rspamd">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rspamd" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-rspamd">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-rspamd" data-bs-toggle="collapse" aria-controls="collapse-tab-config-rspamd">
|
||||||
Rspamd UI
|
Rspamd UI
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">Rspamd UI</span>
|
<span class="d-none d-md-block">Rspamd UI</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-globalfilter-regex" role="tabpanel" aria-labelledby="tab-globalfilter-regex">
|
<div class="tab-pane fade" id="tab-globalfilter-regex" role="tabpanel" aria-labelledby="tab-globalfilter-regex">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-regex" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-regex">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-regex" data-bs-toggle="collapse" aria-controls="collapse-tab-config-regex">
|
||||||
{{ lang.admin.rspamd_global_filters }}
|
{{ lang.admin.rspamd_global_filters }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.rspamd_global_filters }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.rspamd_global_filters }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-config-ldap-admins" role="tabpanel" aria-labelledby="tab-config-ldap-admins">
|
<div class="tab-pane fade" id="tab-config-ldap-admins" role="tabpanel" aria-labelledby="tab-config-ldap-admins">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-ldap-admins" data-bs-toggle="collapse" aria-controls="ollapse-tab-config-ldap-admins">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-ldap-admins" data-bs-toggle="collapse" aria-controls="collapse-tab-config-ldap-admins">
|
||||||
{{ lang.admin.admins_ldap }}
|
{{ lang.admin.admins_ldap }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.admins_ldap }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.admins_ldap }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-routing" role="tabpanel" aria-labelledby="tab-routing">
|
<div class="tab-pane fade" id="tab-routing" role="tabpanel" aria-labelledby="tab-routing">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-routing" data-bs-toggle="collapse" aria-controls="ollapse-tab-routing">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-routing" data-bs-toggle="collapse" aria-controls="collapse-tab-routing">
|
||||||
{{ lang.admin.relayhosts }}
|
{{ lang.admin.relayhosts }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.relayhosts }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.relayhosts }}</span>
|
||||||
@@ -47,7 +47,7 @@
|
|||||||
|
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex">
|
<div class="card-header d-flex">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-maps" data-bs-toggle="collapse" aria-controls="ollapse-tab-maps">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-maps" data-bs-toggle="collapse" aria-controls="collapse-tab-maps">
|
||||||
{{ lang.admin.transport_maps }}
|
{{ lang.admin.transport_maps }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.transport_maps }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.transport_maps }}</span>
|
||||||
|
@@ -1,7 +1,7 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-sys-mails" role="tabpanel" aria-labelledby="tab-sys-mails">
|
<div class="tab-pane fade" id="tab-sys-mails" role="tabpanel" aria-labelledby="tab-sys-mails">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-sys-mails" data-bs-toggle="collapse" aria-controls="ollapse-tab-sys-mails">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-sys-mails" data-bs-toggle="collapse" aria-controls="collapse-tab-sys-mails">
|
||||||
{{ lang.admin.sys_mails }}
|
{{ lang.admin.sys_mails }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.admin.sys_mails }}</span>
|
<span class="d-none d-md-block">{{ lang.admin.sys_mails }}</span>
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-bcc" role="tabpanel" aria-labelledby="tab-bcc">
|
<div class="tab-pane fade" id="tab-bcc" role="tabpanel" aria-labelledby="tab-bcc">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-bcc" data-bs-toggle="collapse" aria-controls="collapse-tab-bcc">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-domain-aliases" role="tabpanel" aria-labelledby="tab-domain-aliases">
|
<div class="tab-pane fade" id="tab-domain-aliases" role="tabpanel" aria-labelledby="tab-domain-aliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domain-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-domain-aliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domain-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-domain-aliases">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade show active" id="tab-domains" role="tabpanel" aria-labelledby="tab-domains">
|
<div class="tab-pane fade show active" id="tab-domains" role="tabpanel" aria-labelledby="tab-domains">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-domains">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-domains">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-filters" role="tabpanel" aria-labelledby="tab-filters">
|
<div class="tab-pane fade" id="tab-filters" role="tabpanel" aria-labelledby="tab-filters">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-filters">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-filters" data-bs-toggle="collapse" aria-controls="collapse-tab-filters">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-mailboxes" role="tabpanel" aria-labelledby="tab-mailboxes">
|
<div class="tab-pane fade" id="tab-mailboxes" role="tabpanel" aria-labelledby="tab-mailboxes">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mailboxes" data-bs-toggle="collapse" aria-controls="collapse-tab-mailboxes">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mailboxes" data-bs-toggle="collapse" aria-controls="collapse-tab-mailboxes">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-mbox-aliases" role="tabpanel" aria-labelledby="tab-mbox-aliases">
|
<div class="tab-pane fade" id="tab-mbox-aliases" role="tabpanel" aria-labelledby="tab-mbox-aliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mbox-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-mbox-aliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-mbox-aliases" data-bs-toggle="collapse" aria-controls="collapse-tab-mbox-aliases">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-resources" role="tabpanel" aria-labelledby="tab-resources">
|
<div class="tab-pane fade" id="tab-resources" role="tabpanel" aria-labelledby="tab-resources">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-resources" data-bs-toggle="collapse" aria-controls="collapse-tab-resources">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-resources" data-bs-toggle="collapse" aria-controls="collapse-tab-resources">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-syncjobs" role="tabpanel" aria-labelledby="tab-syncjobs">
|
<div class="tab-pane fade" id="tab-syncjobs" role="tabpanel" aria-labelledby="tab-syncjobs">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-syncjobs">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-syncjobs">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade show" id="tab-templates-domains" role="tabpanel" aria-labelledby="tab-templates-domains">
|
<div class="tab-pane fade show" id="tab-templates-domains" role="tabpanel" aria-labelledby="tab-templates-domains">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-domains">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-domains" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-domains">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade show" id="tab-templates-mbox" role="tabpanel" aria-labelledby="tab-templates-mbox">
|
<div class="tab-pane fade show" id="tab-templates-mbox" role="tabpanel" aria-labelledby="tab-templates-mbox">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-mbox" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-mbox">
|
<button class="btn d-sm-block d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-templates-mbox" data-bs-toggle="collapse" aria-controls="collapse-tab-templates-mbox">
|
||||||
|
@@ -1,4 +1,4 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade{% if mailcow_cc_role != 'admin' %} d-none{% endif %}" id="tab-tls-policy" role="tabpanel" aria-labelledby="tab-tls-policy">
|
<div class="tab-pane fade{% if mailcow_cc_role != 'admin' %} d-none{% endif %}" id="tab-tls-policy" role="tabpanel" aria-labelledby="tab-tls-policy">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-tls-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-tls-policy">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-tls-policy" data-bs-toggle="collapse" aria-controls="collapse-tab-tls-policy">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="AppPasswds" role="tabpanel" aria-labelledby="AppPasswds">
|
<div class="tab-pane fade" id="AppPasswds" role="tabpanel" aria-labelledby="AppPasswds">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-AppPasswds" data-bs-toggle="collapse" aria-controls="collapse-tab-AppPasswds">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-AppPasswds" data-bs-toggle="collapse" aria-controls="collapse-tab-AppPasswds">
|
||||||
{{ lang.user.app_passwds }}
|
{{ lang.user.app_passwds }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.app_passwds }}
|
<span class="d-none d-md-block">{{ lang.user.app_passwds }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-AppPasswds" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-AppPasswds" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="mass-actions-user mb-4">
|
<div class="mass-actions-user mb-4">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="Pushover" role="tabpanel" aria-labelledby="Pushover">
|
<div class="tab-pane fade" id="Pushover" role="tabpanel" aria-labelledby="Pushover">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Pushover" data-bs-toggle="collapse" aria-controls="collapse-tab-Pushover">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Pushover" data-bs-toggle="collapse" aria-controls="collapse-tab-Pushover">
|
||||||
Pushover API
|
Pushover API
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">Pushover API
|
<span class="d-none d-md-block">Pushover API</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Pushover" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Pushover" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<form data-id="pushover" class="form well" method="post">
|
<form data-id="pushover" class="form well" method="post">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="SpamAliases" role="tabpanel" aria-labelledby="SpamAliases">
|
<div class="tab-pane fade" id="SpamAliases" role="tabpanel" aria-labelledby="SpamAliases">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-SpamAliases" data-bs-toggle="collapse" aria-controls="collapse-tab-SpamAliases">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-SpamAliases" data-bs-toggle="collapse" aria-controls="collapse-tab-SpamAliases">
|
||||||
{{ lang.user.spam_aliases }}
|
{{ lang.user.spam_aliases }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.spam_aliases }}
|
<span class="d-none d-md-block">{{ lang.user.spam_aliases }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-SpamAliases" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-SpamAliases" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="Spamfilter" role="tabpanel" aria-labelledby="Spamfilter">
|
<div class="tab-pane fade" id="Spamfilter" role="tabpanel" aria-labelledby="Spamfilter">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-Spamfilter">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Spamfilter" data-bs-toggle="collapse" aria-controls="collapse-tab-Spamfilter">
|
||||||
{{ lang.user.spamfilter }}
|
{{ lang.user.spamfilter }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.spamfilter }}
|
<span class="d-none d-md-block">{{ lang.user.spamfilter }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Spamfilter" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Spamfilter" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<h4>{{ lang.user.spamfilter_behavior }}</h4>
|
<h4>{{ lang.user.spamfilter_behavior }}</h4>
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="Syncjobs" role="tabpanel" aria-labelledby="Syncjobs">
|
<div class="tab-pane fade" id="Syncjobs" role="tabpanel" aria-labelledby="Syncjobs">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-Syncjobs">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-Syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-Syncjobs">
|
||||||
{{ lang.user.sync_jobs }}
|
{{ lang.user.sync_jobs }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.sync_jobs }}
|
<span class="d-none d-md-block">{{ lang.user.sync_jobs }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-Syncjobs" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-Syncjobs" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="mass-actions-user mb-4">
|
<div class="mass-actions-user mb-4">
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade in active show" id="tab-user-auth" role="tabpanel" aria-labelledby="tab-user-auth">
|
<div class="tab-pane fade in active show" id="tab-user-auth" role="tabpanel" aria-labelledby="tab-user-auth">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-auth" data-bs-toggle="collapse" aria-controls="collapse-tab-user-auth">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-auth" data-bs-toggle="collapse" aria-controls="collapse-tab-user-auth">
|
||||||
{{ lang.user.mailbox_general }}
|
{{ lang.user.mailbox_general }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_general }}
|
<span class="d-none d-md-block">{{ lang.user.mailbox_general }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-auth" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-auth" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
{% if mailboxdata.attributes.force_pw_update == '1' %}
|
{% if mailboxdata.attributes.force_pw_update == '1' %}
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-user-details" role="tabpanel" aria-labelledby="tab-user-details">
|
<div class="tab-pane fade" id="tab-user-details" role="tabpanel" aria-labelledby="tab-user-details">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-details" data-bs-toggle="collapse" aria-controls="collapse-tab-user-details">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-details" data-bs-toggle="collapse" aria-controls="collapse-tab-user-details">
|
||||||
{{ lang.user.mailbox_details }}
|
{{ lang.user.mailbox_details }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_details }}
|
<span class="d-none d-md-block">{{ lang.user.mailbox_details }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-details" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-details" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
<div class="row">
|
<div class="row">
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
<div class="col-sm-8 col-md-9 col-12">
|
<div class="col-sm-8 col-md-9 col-12">
|
||||||
<p>
|
<p>
|
||||||
{% if user_get_alias_details.aliases_also_send_as == '*' %}
|
{% if user_get_alias_details.aliases_also_send_as == '*' %}
|
||||||
{{ lang.user.sender_acl_disabled }}
|
{{ lang.user.sender_acl_disabled | raw }}
|
||||||
{% elseif user_get_alias_details.aliases_also_send_as %}
|
{% elseif user_get_alias_details.aliases_also_send_as %}
|
||||||
{{ user_get_alias_details.aliases_also_send_as }}
|
{{ user_get_alias_details.aliases_also_send_as }}
|
||||||
{% else %}
|
{% else %}
|
||||||
@@ -58,13 +58,13 @@
|
|||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.aliases_send_as_all }}:</div>
|
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.aliases_send_as_all }}:</div>
|
||||||
<div class="col-sm-8 col-md-9 col-12">
|
<div class="col-sm-8 col-md-9 col-12">
|
||||||
<p>{% if not user_get_alias_details.aliases_send_as_all %}<i class="bi bi-x-lg"></i>{% endif %}</p>
|
<p>{% if not user_get_alias_details.aliases_send_as_all %}<i class="bi bi-x-lg"></i>{% else %}{{ user_get_alias_details.aliases_send_as_all }}{% endif %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="row">
|
<div class="row">
|
||||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.is_catch_all }}:</div>
|
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.is_catch_all }}:</div>
|
||||||
<div class="col-sm-8 col-md-9 col-12">
|
<div class="col-sm-8 col-md-9 col-12">
|
||||||
<p>{% if not user_get_alias_details.is_catch_all %}<i class="bi bi-x-lg"></i>{% endif %}</p>
|
<p>{% if not user_get_alias_details.is_catch_all %}<i class="bi bi-x-lg"></i>{% else %}{{ user_get_alias_details.is_catch_all }}{% endif %}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
@@ -1,10 +1,10 @@
|
|||||||
<div role="tabpanel" class="tab-pane fade" id="tab-user-settings" role="tabpanel" aria-labelledby="tab-user-settings">
|
<div class="tab-pane fade" id="tab-user-settings" role="tabpanel" aria-labelledby="tab-user-settings">
|
||||||
<div class="card mb-4">
|
<div class="card mb-4">
|
||||||
<div class="card-header d-flex fs-5">
|
<div class="card-header d-flex fs-5">
|
||||||
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-user-settings">
|
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-user-settings" data-bs-toggle="collapse" aria-controls="collapse-tab-user-settings">
|
||||||
{{ lang.user.mailbox_settings }}
|
{{ lang.user.mailbox_settings }}
|
||||||
</button>
|
</button>
|
||||||
<span class="d-none d-md-block">{{ lang.user.mailbox_settings }}
|
<span class="d-none d-md-block">{{ lang.user.mailbox_settings }}</span>
|
||||||
</div>
|
</div>
|
||||||
<div id="collapse-tab-user-settings" class="card-body collapse" data-bs-parent="#user-content">
|
<div id="collapse-tab-user-settings" class="card-body collapse" data-bs-parent="#user-content">
|
||||||
{# Show tagging options #}
|
{# Show tagging options #}
|
||||||
|
@@ -297,7 +297,7 @@ services:
|
|||||||
- dovecot
|
- dovecot
|
||||||
|
|
||||||
postfix-mailcow:
|
postfix-mailcow:
|
||||||
image: mailcow/postfix:1.68
|
image: mailcow/postfix:1.69
|
||||||
depends_on:
|
depends_on:
|
||||||
- mysql-mailcow
|
- mysql-mailcow
|
||||||
volumes:
|
volumes:
|
||||||
@@ -317,6 +317,7 @@ services:
|
|||||||
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
- REDIS_SLAVEOF_IP=${REDIS_SLAVEOF_IP:-}
|
||||||
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
- REDIS_SLAVEOF_PORT=${REDIS_SLAVEOF_PORT:-}
|
||||||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||||
|
- SPAMHAUS_DQS_KEY=${SPAMHAUS_DQS_KEY:-}
|
||||||
cap_add:
|
cap_add:
|
||||||
- NET_BIND_SERVICE
|
- NET_BIND_SERVICE
|
||||||
ports:
|
ports:
|
||||||
@@ -426,7 +427,7 @@ services:
|
|||||||
- acme
|
- acme
|
||||||
|
|
||||||
netfilter-mailcow:
|
netfilter-mailcow:
|
||||||
image: mailcow/netfilter:1.53
|
image: mailcow/netfilter:1.52
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
depends_on:
|
depends_on:
|
||||||
- dovecot-mailcow
|
- dovecot-mailcow
|
||||||
@@ -511,7 +512,7 @@ services:
|
|||||||
- watchdog
|
- watchdog
|
||||||
|
|
||||||
dockerapi-mailcow:
|
dockerapi-mailcow:
|
||||||
image: mailcow/dockerapi:2.04
|
image: mailcow/dockerapi:2.05
|
||||||
security_opt:
|
security_opt:
|
||||||
- label=disable
|
- label=disable
|
||||||
restart: always
|
restart: always
|
||||||
|
@@ -21,7 +21,7 @@ if grep --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox grep
|
|||||||
if cp --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""; exit 1; fi
|
if cp --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox cp detected, please install coreutils, \"apk add --no-cache --upgrade coreutils\""; exit 1; fi
|
||||||
if sed --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox sed detected, please install gnu sed, \"apk add --no-cache --upgrade sed\""; exit 1; fi
|
if sed --help 2>&1 | head -n 1 | grep -q -i "busybox"; then echo "BusyBox sed detected, please install gnu sed, \"apk add --no-cache --upgrade sed\""; exit 1; fi
|
||||||
|
|
||||||
for bin in openssl curl docker git awk sha1sum; do
|
for bin in openssl curl docker git awk sha1sum grep cut whois; do
|
||||||
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
|
if [[ -z $(which ${bin}) ]]; then echo "Cannot find ${bin}, exiting..."; exit 1; fi
|
||||||
done
|
done
|
||||||
|
|
||||||
@@ -58,6 +58,23 @@ else
|
|||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
detect_bad_asn() {
|
||||||
|
if [[ curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) ]]; then
|
||||||
|
if ! $SPAMHAUS_DQS_KEY; then
|
||||||
|
echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix."
|
||||||
|
echo -e "\e[31mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!"
|
||||||
|
echo ""
|
||||||
|
echo -e "\e[31mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account"
|
||||||
|
echo -e "\e[31mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!"
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "\e[31mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS blocklists for Postfix."
|
||||||
|
echo -e "\e[33mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key..."
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
### If generate_config.sh is started with --dev or -d it will not check out nightly or master branch and will keep on the current branch
|
### If generate_config.sh is started with --dev or -d it will not check out nightly or master branch and will keep on the current branch
|
||||||
if [[ ${1} == "--dev" || ${1} == "-d" ]]; then
|
if [[ ${1} == "--dev" || ${1} == "-d" ]]; then
|
||||||
SKIP_BRANCH=y
|
SKIP_BRANCH=y
|
||||||
@@ -431,6 +448,13 @@ ACME_CONTACT=
|
|||||||
# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates
|
# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates
|
||||||
WEBAUTHN_ONLY_TRUSTED_VENDORS=n
|
WEBAUTHN_ONLY_TRUSTED_VENDORS=n
|
||||||
|
|
||||||
|
# Spamhaus Data Query Service Key
|
||||||
|
# Optional: Leave empty for none
|
||||||
|
# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.
|
||||||
|
# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.
|
||||||
|
# Otherwise it will work normally.
|
||||||
|
SPAMHAUS_DQS_KEY=
|
||||||
|
|
||||||
EOF
|
EOF
|
||||||
|
|
||||||
mkdir -p data/assets/ssl
|
mkdir -p data/assets/ssl
|
||||||
@@ -503,3 +527,5 @@ else
|
|||||||
echo '?>' >> data/web/inc/app_info.inc.php
|
echo '?>' >> data/web/inc/app_info.inc.php
|
||||||
echo -e "\e[33mCannot determine current git repository version...\e[0m"
|
echo -e "\e[33mCannot determine current git repository version...\e[0m"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
|
detect_bad_asn
|
@@ -1,6 +1,6 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
||||||
NEXTCLOUD_VERSION=27.0.0
|
NEXTCLOUD_VERSION=27.0.1
|
||||||
|
|
||||||
echo -ne "Checking prerequisites..."
|
echo -ne "Checking prerequisites..."
|
||||||
sleep 1
|
sleep 1
|
||||||
|
38
update.sh
38
update.sh
@@ -255,6 +255,25 @@ elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
|||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
detect_bad_asn() {
|
||||||
|
if curl -s http://fuzzy.mailcow.email/asn_list.txt | grep $(whois -h whois.radb.net $(curl -s http://ipv4.mailcow.email) | grep -i origin | tr -s " " | cut -d " " -f2 | head -1) > /dev/null ; then
|
||||||
|
if [ -z "$SPAMHAUS_DQS_KEY" ]; then
|
||||||
|
echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m"
|
||||||
|
echo -e "\e[33mmailcow did not detected a value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf!\e[0m"
|
||||||
|
sleep 2
|
||||||
|
echo ""
|
||||||
|
echo -e "\e[33mTo use the Spamhaus DNS Blocklists again, you will need to create a FREE account for their Data Query Service (DQS) at: https://www.spamhaus.com/free-trial/sign-up-for-a-free-data-query-service-account\e[0m"
|
||||||
|
echo -e "\e[33mOnce done, enter your DQS API key in mailcow.conf and mailcow will do the rest for you!\e[0m"
|
||||||
|
echo ""
|
||||||
|
sleep 2
|
||||||
|
|
||||||
|
else
|
||||||
|
echo -e "\e[33mYour server's public IP uses an AS that is blocked by Spamhaus to use their DNS public blocklists for Postfix.\e[0m"
|
||||||
|
echo -e "\e[32mmailcow detected a Value for the variable SPAMHAUS_DQS_KEY inside mailcow.conf. Postfix will use DQS with the given API key...\e[0m"
|
||||||
|
fi
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
############## End Function Section ##############
|
############## End Function Section ##############
|
||||||
|
|
||||||
# Check permissions
|
# Check permissions
|
||||||
@@ -301,7 +320,7 @@ umask 0022
|
|||||||
unset COMPOSE_COMMAND
|
unset COMPOSE_COMMAND
|
||||||
unset DOCKER_COMPOSE_VERSION
|
unset DOCKER_COMPOSE_VERSION
|
||||||
|
|
||||||
for bin in curl docker git awk sha1sum; do
|
for bin in curl docker git awk sha1sum grep cut whois; do
|
||||||
if [[ -z $(command -v ${bin}) ]]; then
|
if [[ -z $(command -v ${bin}) ]]; then
|
||||||
echo "Cannot find ${bin}, exiting..."
|
echo "Cannot find ${bin}, exiting..."
|
||||||
exit 1;
|
exit 1;
|
||||||
@@ -442,8 +461,11 @@ CONFIG_ARRAY=(
|
|||||||
"ACME_CONTACT"
|
"ACME_CONTACT"
|
||||||
"WATCHDOG_VERBOSE"
|
"WATCHDOG_VERBOSE"
|
||||||
"WEBAUTHN_ONLY_TRUSTED_VENDORS"
|
"WEBAUTHN_ONLY_TRUSTED_VENDORS"
|
||||||
|
"SPAMHAUS_DQS_KEY"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
detect_bad_asn
|
||||||
|
|
||||||
sed -i --follow-symlinks '$a\' mailcow.conf
|
sed -i --follow-symlinks '$a\' mailcow.conf
|
||||||
for option in ${CONFIG_ARRAY[@]}; do
|
for option in ${CONFIG_ARRAY[@]}; do
|
||||||
if [[ ${option} == "ADDITIONAL_SAN" ]]; then
|
if [[ ${option} == "ADDITIONAL_SAN" ]]; then
|
||||||
@@ -642,6 +664,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
|||||||
fi
|
fi
|
||||||
elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then
|
elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then
|
||||||
if ! grep -q ${option} mailcow.conf; then
|
if ! grep -q ${option} mailcow.conf; then
|
||||||
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo '# Additional server names for mailcow UI' >> mailcow.conf
|
echo '# Additional server names for mailcow UI' >> mailcow.conf
|
||||||
echo '#' >> mailcow.conf
|
echo '#' >> mailcow.conf
|
||||||
echo '# Specify alternative addresses for the mailcow UI to respond to' >> mailcow.conf
|
echo '# Specify alternative addresses for the mailcow UI to respond to' >> mailcow.conf
|
||||||
@@ -653,6 +676,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
|||||||
fi
|
fi
|
||||||
elif [[ ${option} == "ACME_CONTACT" ]]; then
|
elif [[ ${option} == "ACME_CONTACT" ]]; then
|
||||||
if ! grep -q ${option} mailcow.conf; then
|
if ! grep -q ${option} mailcow.conf; then
|
||||||
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo '# Lets Encrypt registration contact information' >> mailcow.conf
|
echo '# Lets Encrypt registration contact information' >> mailcow.conf
|
||||||
echo '# Optional: Leave empty for none' >> mailcow.conf
|
echo '# Optional: Leave empty for none' >> mailcow.conf
|
||||||
echo '# This value is only used on first order!' >> mailcow.conf
|
echo '# This value is only used on first order!' >> mailcow.conf
|
||||||
@@ -662,13 +686,25 @@ for option in ${CONFIG_ARRAY[@]}; do
|
|||||||
fi
|
fi
|
||||||
elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then
|
elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then
|
||||||
if ! grep -q ${option} mailcow.conf; then
|
if ! grep -q ${option} mailcow.conf; then
|
||||||
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo "# WebAuthn device manufacturer verification" >> mailcow.conf
|
echo "# WebAuthn device manufacturer verification" >> mailcow.conf
|
||||||
echo '# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed' >> mailcow.conf
|
echo '# After setting WEBAUTHN_ONLY_TRUSTED_VENDORS=y only devices from trusted manufacturers are allowed' >> mailcow.conf
|
||||||
echo '# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates' >> mailcow.conf
|
echo '# root certificates can be placed for validation under mailcow-dockerized/data/web/inc/lib/WebAuthn/rootCertificates' >> mailcow.conf
|
||||||
echo 'WEBAUTHN_ONLY_TRUSTED_VENDORS=n' >> mailcow.conf
|
echo 'WEBAUTHN_ONLY_TRUSTED_VENDORS=n' >> mailcow.conf
|
||||||
fi
|
fi
|
||||||
|
elif [[ ${option} == "SPAMHAUS_DQS_KEY" ]]; then
|
||||||
|
if ! grep -q ${option} mailcow.conf; then
|
||||||
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
|
echo "# Spamhaus Data Query Service Key" >> mailcow.conf
|
||||||
|
echo '# Optional: Leave empty for none' >> mailcow.conf
|
||||||
|
echo '# Enter your key here if you are using a blocked ASN (OVH, AWS, Cloudflare e.g) for the unregistered Spamhaus Blocklist.' >> mailcow.conf
|
||||||
|
echo '# If empty, it will completely disable Spamhaus blocklists if it detects that you are running on a server using a blocked AS.' >> mailcow.conf
|
||||||
|
echo '# Otherwise it will work as usual.' >> mailcow.conf
|
||||||
|
echo 'SPAMHAUS_DQS_KEY=' >> mailcow.conf
|
||||||
|
fi
|
||||||
elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then
|
elif [[ ${option} == "WATCHDOG_VERBOSE" ]]; then
|
||||||
if ! grep -q ${option} mailcow.conf; then
|
if ! grep -q ${option} mailcow.conf; then
|
||||||
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo '# Enable watchdog verbose logging' >> mailcow.conf
|
echo '# Enable watchdog verbose logging' >> mailcow.conf
|
||||||
echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf
|
echo 'WATCHDOG_VERBOSE=n' >> mailcow.conf
|
||||||
fi
|
fi
|
||||||
|
Reference in New Issue
Block a user