commit
52085cc3d5
|
@ -21,3 +21,6 @@ data/conf/nginx/*.conf
|
|||
data/conf/nginx/*.custom
|
||||
data/conf/nginx/*.bak
|
||||
data/conf/dovecot/extra.conf
|
||||
data/conf/rspamd/custom/*
|
||||
data/conf/portainer/
|
||||
docker-compose.override.yml
|
||||
|
|
|
@ -37,7 +37,7 @@ mkdir -p ${ACME_BASE}/acme/private
|
|||
restart_containers(){
|
||||
for container in $*; do
|
||||
log_f "Restarting ${container}..." no_nl
|
||||
C_REST_OUT=$(curl -X POST http://dockerapi:8080/containers/${container}/restart | jq -r '.msg')
|
||||
C_REST_OUT=$(curl -X POST --insecure https://dockerapi/containers/${container}/restart | jq -r '.msg')
|
||||
log_f "${C_REST_OUT}" no_date
|
||||
done
|
||||
}
|
||||
|
@ -125,7 +125,7 @@ else
|
|||
fi
|
||||
|
||||
log_f "Waiting for database... "
|
||||
while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do
|
||||
while ! mysqladmin ping --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do
|
||||
sleep 2
|
||||
done
|
||||
log_f "Initializing, please wait... "
|
||||
|
@ -161,19 +161,19 @@ while true; do
|
|||
fi
|
||||
|
||||
# Container ids may have changed
|
||||
CONTAINERS_RESTART=($(curl --silent http://dockerapi:8080/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("nginx-mailcow") or contains("postfix-mailcow") or contains("dovecot-mailcow")) | .id' | tr "\n" " "))
|
||||
CONTAINERS_RESTART=($(curl --silent --insecure https://dockerapi/containers/json | jq -r '.[] | {name: .Config.Labels["com.docker.compose.service"], id: .Id}' | jq -rc 'select( .name | tostring | contains("nginx-mailcow") or contains("postfix-mailcow") or contains("dovecot-mailcow")) | .id' | tr "\n" " "))
|
||||
|
||||
log_f "Waiting for domain table... " no_nl
|
||||
while [[ -z ${DOMAIN_TABLE} ]]; do
|
||||
curl --silent http://nginx/ >/dev/null 2>&1
|
||||
DOMAIN_TABLE=$(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs)
|
||||
DOMAIN_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'domain'" -Bs)
|
||||
[[ -z ${DOMAIN_TABLE} ]] && sleep 10
|
||||
done
|
||||
log_f "OK" no_date
|
||||
|
||||
while read domains; do
|
||||
SQL_DOMAIN_ARR+=("${domains}")
|
||||
done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0 UNION SELECT alias_domain FROM alias_domain" -Bs)
|
||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain WHERE backupmx=0 UNION SELECT alias_domain FROM alias_domain" -Bs)
|
||||
|
||||
for SQL_DOMAIN in "${SQL_DOMAIN_ARR[@]}"; do
|
||||
A_CONFIG=$(dig A autoconfig.${SQL_DOMAIN} +short | tail -n 1)
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
FROM python:2-alpine
|
||||
FROM alpine:3.8
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
RUN apk add -U --no-cache iptables ip6tables tzdata
|
||||
RUN pip install docker==3.0.1 flask flask-restful
|
||||
RUN apk add -U --no-cache python2 python-dev py-pip gcc musl-dev tzdata openssl-dev libffi-dev \
|
||||
&& pip2 install --upgrade docker==3.0.1 flask flask-restful pyOpenSSL \
|
||||
&& apk del python-dev py2-pip gcc
|
||||
|
||||
COPY server.py /
|
||||
|
||||
CMD ["python2", "-u", "/server.py"]
|
||||
|
|
|
@ -3,12 +3,16 @@ from flask_restful import Resource, Api
|
|||
from flask import jsonify
|
||||
from flask import request
|
||||
from threading import Thread
|
||||
from OpenSSL import crypto
|
||||
import docker
|
||||
import uuid
|
||||
import signal
|
||||
import time
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import ssl
|
||||
import socket
|
||||
|
||||
docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
|
||||
app = Flask(__name__)
|
||||
|
@ -93,22 +97,74 @@ class container_post(Resource):
|
|||
return sieve_return.output
|
||||
except Exception as e:
|
||||
return jsonify(type='danger', msg=str(e))
|
||||
# not in use...
|
||||
elif request.json['cmd'] == 'mail_crypt_generate' and request.json['username'] and request.json['old_password'] and request.json['new_password']:
|
||||
try:
|
||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
||||
# create if missing
|
||||
crypto_generate = container.exec_run(["/bin/bash", "-c", "/usr/local/bin/doveadm mailbox cryptokey generate -u '" + request.json['username'].replace("'", "'\\''") + "' -URf"], user='vmail')
|
||||
if crypto_generate.exit_code == 0:
|
||||
# open a shell, bind stdin and return socket
|
||||
cryptokey_shell = container.exec_run(["/bin/bash"], stdin=True, socket=True, user='vmail')
|
||||
# command to be piped to shell
|
||||
cryptokey_cmd = "/usr/local/bin/doveadm mailbox cryptokey password -u '" + request.json['username'].replace("'", "'\\''") + "' -n '" + request.json['new_password'].replace("'", "'\\''") + "' -o '" + request.json['old_password'].replace("'", "'\\''") + "'\n"
|
||||
# socket is .output
|
||||
cryptokey_socket = cryptokey_shell.output;
|
||||
try :
|
||||
# send command utf-8 encoded
|
||||
cryptokey_socket.sendall(cryptokey_cmd.encode('utf-8'))
|
||||
# we won't send more data than this
|
||||
cryptokey_socket.shutdown(socket.SHUT_WR)
|
||||
except socket.error:
|
||||
# exit on socket error
|
||||
return jsonify(type='danger', msg=str('socket error'))
|
||||
# read response
|
||||
cryptokey_response = recv_socket_data(cryptokey_socket)
|
||||
crypto_error = re.search('dcrypt_key_load_private.+failed.+error', cryptokey_response)
|
||||
if crypto_error is not None:
|
||||
return jsonify(type='danger', msg=str("dcrypt_key_load_private error"))
|
||||
return jsonify(type='success', msg=str("key pair generated"))
|
||||
else:
|
||||
return jsonify(type='danger', msg=str(crypto_generate.output))
|
||||
except Exception as e:
|
||||
return jsonify(type='danger', msg=str(e))
|
||||
elif request.json['cmd'] == 'maildir_cleanup' and request.json['maildir']:
|
||||
try:
|
||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
||||
sane_name = re.sub(r'\W+', '', request.json['maildir'])
|
||||
maildir_cleanup = container.exec_run(["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"], user='vmail')
|
||||
if maildir_cleanup.exit_code == 0:
|
||||
return jsonify(type='success', msg=str("moved to garbage"))
|
||||
else:
|
||||
return jsonify(type='danger', msg=str(maildir_cleanup.output))
|
||||
except Exception as e:
|
||||
return jsonify(type='danger', msg=str(e))
|
||||
elif request.json['cmd'] == 'worker_password' and request.json['raw']:
|
||||
try:
|
||||
for container in docker_client.containers.list(filters={"id": container_id}):
|
||||
hash = container.exec_run(["/bin/bash", "-c", "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null"], user='_rspamd')
|
||||
if hash.exit_code == 0:
|
||||
hash_stdout = str(hash.output)
|
||||
for line in hash_stdout.split("\n"):
|
||||
worker_shell = container.exec_run(["/bin/bash"], stdin=True, socket=True, user='_rspamd')
|
||||
worker_cmd = "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null\n"
|
||||
worker_socket = worker_shell.output;
|
||||
try :
|
||||
worker_socket.sendall(worker_cmd.encode('utf-8'))
|
||||
worker_socket.shutdown(socket.SHUT_WR)
|
||||
except socket.error:
|
||||
return jsonify(type='danger', msg=str('socket error'))
|
||||
worker_response = recv_socket_data(worker_socket)
|
||||
matched = False
|
||||
for line in worker_response.split("\n"):
|
||||
if '$2$' in line:
|
||||
matched = True
|
||||
hash = line.strip()
|
||||
hash_out = re.search('\$2\$.+$', hash).group(0)
|
||||
f = open("/access.inc", "w")
|
||||
f.write('enable_password = "' + re.sub('[^0-9a-zA-Z\$]+', '', hash.rstrip()) + '";\n')
|
||||
f.write('enable_password = "' + re.sub('[^0-9a-zA-Z\$]+', '', hash_out.rstrip()) + '";\n')
|
||||
f.close()
|
||||
container.restart()
|
||||
if matched:
|
||||
return jsonify(type='success', msg='command completed successfully')
|
||||
else:
|
||||
return jsonify(type='danger', msg='command did not complete, exit code was ' + int(hash.exit_code))
|
||||
return jsonify(type='danger', msg='command did not complete')
|
||||
except Exception as e:
|
||||
return jsonify(type='danger', msg=str(e))
|
||||
elif request.json['cmd'] == 'mailman_password' and request.json['email'] and request.json['passwd']:
|
||||
|
@ -141,7 +197,58 @@ class GracefulKiller:
|
|||
self.kill_now = True
|
||||
|
||||
def startFlaskAPI():
|
||||
app.run(debug=False, host='0.0.0.0', port=8080, threaded=True)
|
||||
create_self_signed_cert()
|
||||
try:
|
||||
ctx = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
|
||||
ctx.check_hostname = False
|
||||
ctx.load_cert_chain(certfile='/cert.pem', keyfile='/key.pem')
|
||||
except:
|
||||
print "Cannot initialize TLS, retrying in 5s..."
|
||||
time.sleep(5)
|
||||
app.run(debug=False, host='0.0.0.0', port=443, threaded=True, ssl_context=ctx)
|
||||
|
||||
def recv_socket_data(c_socket, timeout=10):
|
||||
c_socket.setblocking(0)
|
||||
total_data=[];
|
||||
data='';
|
||||
begin=time.time()
|
||||
while True:
|
||||
if total_data and time.time()-begin > timeout:
|
||||
break
|
||||
elif time.time()-begin > timeout*2:
|
||||
break
|
||||
try:
|
||||
data = c_socket.recv(8192)
|
||||
if data:
|
||||
total_data.append(data)
|
||||
#change the beginning time for measurement
|
||||
begin=time.time()
|
||||
else:
|
||||
#sleep for sometime to indicate a gap
|
||||
time.sleep(0.1)
|
||||
break
|
||||
except:
|
||||
pass
|
||||
return ''.join(total_data)
|
||||
|
||||
def create_self_signed_cert():
|
||||
pkey = crypto.PKey()
|
||||
pkey.generate_key(crypto.TYPE_RSA, 2048)
|
||||
cert = crypto.X509()
|
||||
cert.get_subject().O = "mailcow"
|
||||
cert.get_subject().CN = "dockerapi"
|
||||
cert.set_serial_number(int(uuid.uuid4()))
|
||||
cert.gmtime_adj_notBefore(0)
|
||||
cert.gmtime_adj_notAfter(10*365*24*60*60)
|
||||
cert.set_issuer(cert.get_subject())
|
||||
cert.set_pubkey(pkey)
|
||||
cert.sign(pkey, 'sha512')
|
||||
cert = crypto.dump_certificate(crypto.FILETYPE_PEM, cert)
|
||||
pkey = crypto.dump_privatekey(crypto.FILETYPE_PEM, pkey)
|
||||
with os.fdopen(os.open('/cert.pem', os.O_WRONLY | os.O_CREAT, 0o644), 'w') as handle:
|
||||
handle.write(cert)
|
||||
with os.fdopen(os.open('/key.pem', os.O_WRONLY | os.O_CREAT, 0o600), 'w') as handle:
|
||||
handle.write(pkey)
|
||||
|
||||
api.add_resource(containers_get, '/containers/json')
|
||||
api.add_resource(container_get, '/containers/<string:container_id>/json')
|
||||
|
|
|
@ -14,6 +14,7 @@ RUN apt-get update && apt-get -y --no-install-recommends install \
|
|||
cpanminus \
|
||||
curl \
|
||||
default-libmysqlclient-dev \
|
||||
dnsutils \
|
||||
libjson-webtoken-perl \
|
||||
libcgi-pm-perl \
|
||||
libcrypt-openssl-rsa-perl \
|
||||
|
@ -90,8 +91,9 @@ RUN curl https://www.dovecot.org/releases/2.3/dovecot-$DOVECOT_VERSION.tar.gz |
|
|||
RUN cpanm Data::Uniqid Mail::IMAPClient String::Util
|
||||
RUN echo '* * * * * root /usr/local/bin/imapsync_cron.pl' > /etc/cron.d/imapsync
|
||||
RUN echo '30 3 * * * vmail /usr/local/bin/doveadm quota recalc -A' > /etc/cron.d/dovecot-sync
|
||||
RUN echo '* * * * * root /usr/local/bin/trim_logs.sh >> /dev/stdout 2>&1' > /etc/cron.d/trim_logs
|
||||
|
||||
RUN echo '* * * * * vmail /usr/local/bin/trim_logs.sh >> /dev/stdout 2>&1' > /etc/cron.d/trim_logs
|
||||
RUN echo '25 * * * * vmail /usr/local/bin/maildir_gc.sh >> /dev/stdout 2>&1' > /etc/cron.d/maildir_gc
|
||||
RUN echo '30 1 * * * root /usr/local/bin/sa-rules.sh >> /dev/stdout 2>&1' > /etc/cron.d/sa-rules
|
||||
COPY trim_logs.sh /usr/local/bin/trim_logs.sh
|
||||
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
|
||||
COPY imapsync /usr/local/bin/imapsync
|
||||
|
@ -101,6 +103,8 @@ COPY report-spam.sieve /usr/local/lib/dovecot/sieve/report-spam.sieve
|
|||
COPY report-ham.sieve /usr/local/lib/dovecot/sieve/report-ham.sieve
|
||||
COPY rspamd-pipe-ham /usr/local/lib/dovecot/sieve/rspamd-pipe-ham
|
||||
COPY rspamd-pipe-spam /usr/local/lib/dovecot/sieve/rspamd-pipe-spam
|
||||
COPY sa-rules.sh /usr/local/bin/sa-rules.sh
|
||||
COPY maildir_gc.sh /usr/local/bin/maildir_gc.sh
|
||||
COPY docker-entrypoint.sh /
|
||||
COPY supervisord.conf /etc/supervisor/supervisord.conf
|
||||
|
||||
|
@ -109,7 +113,9 @@ RUN chmod +x /usr/local/lib/dovecot/sieve/rspamd-pipe-ham \
|
|||
/usr/local/bin/imapsync_cron.pl \
|
||||
/usr/local/bin/postlogin.sh \
|
||||
/usr/local/bin/imapsync \
|
||||
/usr/local/bin/trim_logs.sh
|
||||
/usr/local/bin/trim_logs.sh \
|
||||
/usr/local/bin/sa-rules.sh \
|
||||
/usr/local/bin/maildir_gc.sh
|
||||
|
||||
RUN groupadd -g 5000 vmail \
|
||||
&& groupadd -g 401 dovecot \
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
set -e
|
||||
|
||||
# Wait for MySQL to warm-up
|
||||
while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do
|
||||
while ! mysqladmin ping --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do
|
||||
echo "Waiting for database to come up..."
|
||||
sleep 2
|
||||
done
|
||||
|
@ -15,6 +15,7 @@ sed -i "s/LOG_LINES/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh
|
|||
|
||||
# Create missing directories
|
||||
[[ ! -d /usr/local/etc/dovecot/sql/ ]] && mkdir -p /usr/local/etc/dovecot/sql/
|
||||
[[ ! -d /var/vmail/_garbage ]] && mkdir -p /var/vmail/_garbage
|
||||
[[ ! -d /var/vmail/sieve ]] && mkdir -p /var/vmail/sieve
|
||||
[[ ! -d /etc/sogo ]] && mkdir -p /etc/sogo
|
||||
|
||||
|
@ -23,7 +24,7 @@ DBPASS=$(echo ${DBPASS} | sed 's/"/\\"/g')
|
|||
|
||||
# Create quota dict for Dovecot
|
||||
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-quota.conf
|
||||
connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
map {
|
||||
pattern = priv/quota/storage
|
||||
table = quota2
|
||||
|
@ -40,7 +41,7 @@ EOF
|
|||
|
||||
# Create dict used for sieve pre and postfilters
|
||||
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf
|
||||
connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
map {
|
||||
pattern = priv/sieve/name/\$script_name
|
||||
table = sieve_before
|
||||
|
@ -62,7 +63,7 @@ map {
|
|||
EOF
|
||||
|
||||
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf
|
||||
connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
map {
|
||||
pattern = priv/sieve/name/\$script_name
|
||||
table = sieve_after
|
||||
|
@ -87,7 +88,7 @@ EOF
|
|||
# Create userdb dict for Dovecot
|
||||
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-userdb.conf
|
||||
driver = mysql
|
||||
connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
user_query = SELECT CONCAT('maildir:/var/vmail/',maildir) AS mail, 5000 AS uid, 5000 AS gid, concat('*:bytes=', quota) AS quota_rule FROM mailbox WHERE username = '%u' AND active = '1'
|
||||
iterate_query = SELECT username FROM mailbox WHERE active='1';
|
||||
EOF
|
||||
|
@ -95,7 +96,7 @@ EOF
|
|||
# Create pass dict for Dovecot
|
||||
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-passdb.conf
|
||||
driver = mysql
|
||||
connect = "host=mysql dbname=${DBNAME} user=${DBUSER} password=${DBPASS}"
|
||||
connect = "host=/var/run/mysqld/mysqld.sock dbname=${DBNAME} user=${DBUSER} password=${DBPASS} ssl_verify_server_cert=no ssl_ca=/etc/ssl/certs/ca-certificates.crt"
|
||||
default_pass_scheme = SSHA256
|
||||
password_query = SELECT password FROM mailbox WHERE username = '%u' AND domain IN (SELECT domain FROM domain WHERE domain='%d' AND active='1') AND JSON_EXTRACT(attributes, '$.force_pw_update') NOT LIKE '%%1%%'
|
||||
EOF
|
||||
|
@ -106,12 +107,14 @@ cat /usr/local/etc/dovecot/sieve_after > /var/vmail/sieve/global.sieve
|
|||
# Check permissions of vmail directory.
|
||||
# Do not do this every start-up, it may take a very long time. So we use a stat check here.
|
||||
if [[ $(stat -c %U /var/vmail/) != "vmail" ]] ; then chown -R vmail:vmail /var/vmail ; fi
|
||||
if [[ $(stat -c %U /var/vmail/_garbage) != "vmail" ]] ; then chown -R vmail:vmail /var/vmail/_garbage ; fi
|
||||
|
||||
# Create random master for SOGo sieve features
|
||||
RAND_USER=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 16 | head -n 1)
|
||||
RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 24 | head -n 1)
|
||||
echo ${RAND_USER}:$(doveadm pw -s SHA1 -p ${RAND_PASS}) > /usr/local/etc/dovecot/dovecot-master.passwd
|
||||
echo ${RAND_USER}:${RAND_PASS} > /etc/sogo/sieve.creds
|
||||
|
||||
echo ${RAND_USER}@mailcow.local:$(doveadm pw -s SHA1 -p ${RAND_PASS}) > /usr/local/etc/dovecot/dovecot-master.passwd
|
||||
echo ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/sieve.creds
|
||||
|
||||
# 401 is user dovecot
|
||||
if [[ ! -f /mail_crypt/ecprivkey.pem || ! -f /mail_crypt/ecpubkey.pem ]]; then
|
||||
|
@ -138,7 +141,10 @@ touch /etc/crontab /etc/cron.*/*
|
|||
|
||||
# Clean stopped imapsync jobs
|
||||
rm -f /tmp/imapsync_busy.lock
|
||||
IMAPSYNC_TABLE=$(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs)
|
||||
[[ ! -z ${IMAPSYNC_TABLE} ]] && mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'"
|
||||
IMAPSYNC_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs)
|
||||
[[ ! -z ${IMAPSYNC_TABLE} ]] && mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'"
|
||||
|
||||
# Collect SA rules once now
|
||||
/usr/local/bin/sa-rules.sh
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -0,0 +1,2 @@
|
|||
#/bin/bash
|
||||
[ -d /var/vmail/_garbage/ ] && /usr/bin/find /var/vmail/_garbage/ -mindepth 1 -maxdepth 1 -type d -cmin +${MAILDIR_GC_TIME} -exec rm -r {} \;
|
|
@ -1,4 +1,3 @@
|
|||
#!/bin/sh
|
||||
|
||||
export MASTER_USER=$USER
|
||||
exec "$@"
|
||||
|
|
|
@ -3,7 +3,7 @@ FILE=/tmp/mail$$
|
|||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -3,7 +3,7 @@ FILE=/tmp/mail$$
|
|||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -0,0 +1,25 @@
|
|||
#!/bin/bash
|
||||
[[ ! -d /tmp/sa-rules-heinlein ]] && mkdir -p /tmp/sa-rules-heinlein
|
||||
if [[ ! -f /etc/rspamd/custom/sa-rules-heinlein ]]; then
|
||||
HASH_SA_RULES=0
|
||||
else
|
||||
HASH_SA_RULES=$(cat /etc/rspamd/custom/sa-rules-heinlein | md5sum | cut -d' ' -f1)
|
||||
fi
|
||||
|
||||
curl --connect-timeout 15 --max-time 30 http://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"').tar.gz --output /tmp/sa-rules.tar.gz
|
||||
if [[ -f /tmp/sa-rules.tar.gz ]]; then
|
||||
tar xfvz /tmp/sa-rules.tar.gz -C /tmp/sa-rules-heinlein
|
||||
# create complete list of rules in a single file
|
||||
cat /tmp/sa-rules-heinlein/*cf > /etc/rspamd/custom/sa-rules-heinlein
|
||||
# Only restart rspamd-mailcow when rules changed
|
||||
if [[ $(cat /etc/rspamd/custom/sa-rules-heinlein | md5sum | cut -d' ' -f1) != ${HASH_SA_RULES} ]]; then
|
||||
CONTAINER_NAME=rspamd-mailcow
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | \
|
||||
jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | \
|
||||
jq -rc "select( .name | tostring | contains(\"${CONTAINER_NAME}\")) | .id")
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
curl --silent --insecure -XPOST --connect-timeout 15 --max-time 120 https://dockerapi/containers/${CONTAINER_ID}/restart
|
||||
fi
|
||||
fi
|
||||
fi
|
||||
rm -rf /tmp/sa-rules-heinlein /tmp/sa-rules.tar.gz
|
|
@ -1,8 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
redis-cli -h redis LTRIM ACME_LOG 0 LOG_LINES
|
||||
redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 LOG_LINES
|
||||
redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 LOG_LINES
|
||||
redis-cli -h redis LTRIM SOGO_LOG 0 LOG_LINES
|
||||
redis-cli -h redis LTRIM NETFILTER_LOG 0 LOG_LINES
|
||||
redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM ACME_LOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM SOGO_LOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM NETFILTER_LOG 0 LOG_LINES
|
||||
/usr/bin/redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 LOG_LINES
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
FROM php:7.2-fpm-alpine3.7
|
||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||
|
||||
ENV APCU_PECL 5.1.11
|
||||
ENV APCU_PECL 5.1.12
|
||||
ENV IMAGICK_PECL 3.4.3
|
||||
ENV MAILPARSE_PECL 3.0.2
|
||||
ENV MEMCACHED_PECL 3.0.4
|
||||
ENV REDIS_PECL 4.0.2
|
||||
ENV REDIS_PECL 4.1.1
|
||||
|
||||
RUN apk add -U --no-cache autoconf \
|
||||
bash \
|
||||
|
|
|
@ -4,11 +4,13 @@ set -e
|
|||
function array_by_comma { local IFS=","; echo "$*"; }
|
||||
|
||||
# Wait for containers
|
||||
while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do
|
||||
while ! mysqladmin ping --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do
|
||||
echo "Waiting for SQL..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do
|
||||
echo "Waiting for Redis..."
|
||||
sleep 2
|
||||
done
|
||||
|
||||
|
@ -18,11 +20,11 @@ redis-cli -h redis-mailcow DEL DOMAIN_MAP
|
|||
while read line
|
||||
do
|
||||
DOMAIN_ARR+=("$line")
|
||||
done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs)
|
||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain" -Bs)
|
||||
while read line
|
||||
do
|
||||
DOMAIN_ARR+=("$line")
|
||||
done < <(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs)
|
||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT alias_domain FROM alias_domain" -Bs)
|
||||
|
||||
if [[ ! -z ${DOMAIN_ARR} ]]; then
|
||||
for domain in "${DOMAIN_ARR[@]}"; do
|
||||
|
@ -48,7 +50,7 @@ if [[ ${API_ALLOW_FROM} != "invalid" ]] && \
|
|||
done
|
||||
VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]})
|
||||
if [[ ! -z ${VALIDATED_IPS} ]]; then
|
||||
mysql --host mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
INSERT INTO api (username, api_key, active, allow_from)
|
||||
SELECT username, "${API_KEY}", '1', "${VALIDATED_IPS}" FROM admin WHERE superadmin='1' AND active='1'
|
||||
ON DUPLICATE KEY UPDATE active = '1', allow_from = "${VALIDATED_IPS}", api_key = "${API_KEY}";
|
||||
|
|
|
@ -14,7 +14,7 @@ newaliases;
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_relay_recipient_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT DISTINCT
|
||||
CASE WHEN '%d' IN (
|
||||
|
@ -29,10 +29,18 @@ query = SELECT DISTINCT
|
|||
END AS result;
|
||||
EOF
|
||||
|
||||
cat <<EOF > /opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT CONCAT(policy, ' ', parameters) AS tls_policy FROM tls_policy_override WHERE active = '1' AND dest = '%s'
|
||||
EOF
|
||||
|
||||
cat <<EOF > /opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT IF(EXISTS(
|
||||
SELECT 'TLS_ACTIVE' FROM alias
|
||||
|
@ -49,7 +57,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT GROUP_CONCAT(transport SEPARATOR '') AS transport_maps
|
||||
FROM (
|
||||
|
@ -80,7 +88,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM relayhosts
|
||||
WHERE id IN (
|
||||
|
@ -96,7 +104,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_catchall_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT goto FROM alias, alias_domain
|
||||
WHERE alias_domain.alias_domain = '%d'
|
||||
|
@ -107,7 +115,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT username FROM mailbox, alias_domain
|
||||
WHERE alias_domain.alias_domain = '%d'
|
||||
|
@ -119,7 +127,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT goto FROM alias
|
||||
WHERE address='%s'
|
||||
|
@ -129,7 +137,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT bcc_dest FROM bcc_maps
|
||||
WHERE local_dest='%s'
|
||||
|
@ -140,7 +148,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT bcc_dest FROM bcc_maps
|
||||
WHERE local_dest='%s'
|
||||
|
@ -151,7 +159,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT new_dest FROM recipient_maps
|
||||
WHERE old_dest='%s'
|
||||
|
@ -161,7 +169,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT alias_domain from alias_domain WHERE alias_domain='%s' AND active='1'
|
||||
UNION
|
||||
|
@ -174,7 +182,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
|
||||
EOF
|
||||
|
@ -182,7 +190,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '1' AND active = '1'
|
||||
EOF
|
||||
|
@ -190,7 +198,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_sender_acl.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
# First select queries domain and alias_domain to determine if domains are active.
|
||||
query = SELECT goto FROM alias
|
||||
|
@ -231,7 +239,7 @@ EOF
|
|||
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf
|
||||
user = ${DBUSER}
|
||||
password = ${DBPASS}
|
||||
hosts = mysql
|
||||
hosts = unix:/var/run/mysqld/mysqld.sock
|
||||
dbname = ${DBNAME}
|
||||
query = SELECT goto FROM spamalias
|
||||
WHERE address='%s'
|
||||
|
|
|
@ -3,7 +3,7 @@ FILE=/tmp/mail$$
|
|||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnham
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 13" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -3,7 +3,7 @@ FILE=/tmp/mail$$
|
|||
cat > $FILE
|
||||
trap "/bin/rm -f $FILE" 0 1 2 3 13 15
|
||||
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/fuzzyadd
|
||||
cat ${FILE} | /usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/learnspam
|
||||
cat ${FILE} | /usr/bin/curl -H "Flag: 11" -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/fuzzyadd
|
||||
|
||||
exit 0
|
||||
|
|
|
@ -20,7 +20,7 @@ RUN apt-get update && apt-get install -y \
|
|||
&& mkdir -p /run/rspamd \
|
||||
&& chown _rspamd:_rspamd /run/rspamd
|
||||
|
||||
COPY settings.conf /etc/rspamd/modules.d/settings.conf
|
||||
COPY settings.conf /etc/rspamd/settings.conf
|
||||
COPY docker-entrypoint.sh /docker-entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/docker-entrypoint.sh"]
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
#!/bin/bash
|
||||
|
||||
chown -R _rspamd:_rspamd /var/lib/rspamd
|
||||
chown -R _rspamd:_rspamd /var/lib/rspamd /etc/rspamd/local.d /etc/rspamd/override.d /etc/rspamd/custom
|
||||
chmod 755 /var/lib/rspamd
|
||||
[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Placeholder' > /etc/rspamd/override.d/worker-controller-password.inc
|
||||
chown _rspamd:_rspamd /etc/rspamd/override.d/worker-controller-password.inc
|
||||
[[ ! -f /etc/rspamd/custom/sa-rules-heinlein ]] && echo '# to be auto-filled by dovecot-mailcow' > /etc/rspamd/custom/sa-rules-heinlein
|
||||
|
||||
exec "$@"
|
||||
|
|
|
@ -1,152 +0,0 @@
|
|||
local exports = {}
|
||||
local lpeg = require 'lpeg'
|
||||
|
||||
local split_grammar = {}
|
||||
local function rspamd_str_split(s, sep)
|
||||
local gr = split_grammar[sep]
|
||||
|
||||
if not gr then
|
||||
local _sep = lpeg.P(sep)
|
||||
local elem = lpeg.C((1 - _sep)^0)
|
||||
local p = lpeg.Ct(elem * (_sep * elem)^0)
|
||||
gr = p
|
||||
split_grammar[sep] = gr
|
||||
end
|
||||
|
||||
return gr:match(s)
|
||||
end
|
||||
|
||||
exports.rspamd_str_split = rspamd_str_split
|
||||
|
||||
local space = lpeg.S' \t\n\v\f\r'
|
||||
local nospace = 1 - space
|
||||
local ptrim = space^0 * lpeg.C((space^0 * nospace^1)^0)
|
||||
local match = lpeg.match
|
||||
exports.rspamd_str_trim = function(s)
|
||||
return match(ptrim, s)
|
||||
end
|
||||
|
||||
-- Robert Jay Gould http://lua-users.org/wiki/SimpleRound
|
||||
exports.round = function(num, numDecimalPlaces)
|
||||
local mult = 10^(numDecimalPlaces or 0)
|
||||
return math.floor(num * mult) / mult
|
||||
end
|
||||
|
||||
exports.template = function(tmpl, keys)
|
||||
local var_lit = lpeg.P { lpeg.R("az") + lpeg.R("AZ") + lpeg.R("09") + "_" }
|
||||
local var = lpeg.P { (lpeg.P("$") / "") * ((var_lit^1) / keys) }
|
||||
local var_braced = lpeg.P { (lpeg.P("${") / "") * ((var_lit^1) / keys) * (lpeg.P("}") / "") }
|
||||
|
||||
local template_grammar = lpeg.Cs((var + var_braced + 1)^0)
|
||||
|
||||
return lpeg.match(template_grammar, tmpl)
|
||||
end
|
||||
|
||||
exports.remove_email_aliases = function(email_addr)
|
||||
local function check_gmail_user(addr)
|
||||
-- Remove all points
|
||||
local no_dots_user = string.gsub(addr.user, '%.', '')
|
||||
local cap, pluses = string.match(no_dots_user, '^([^%+][^%+]*)(%+.*)$')
|
||||
if cap then
|
||||
return cap, rspamd_str_split(pluses, '+'), nil
|
||||
elseif no_dots_user ~= addr.user then
|
||||
return no_dots_user,{},nil
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function check_address(addr)
|
||||
if addr.user then
|
||||
local cap, pluses = string.match(addr.user, '^([^%+][^%+]*)(%+.*)$')
|
||||
if cap then
|
||||
return cap, rspamd_str_split(pluses, '+'), nil
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function set_addr(addr, new_user, new_domain)
|
||||
if new_user then
|
||||
addr.user = new_user
|
||||
end
|
||||
if new_domain then
|
||||
addr.domain = new_domain
|
||||
end
|
||||
|
||||
if addr.domain then
|
||||
addr.addr = string.format('%s@%s', addr.user, addr.domain)
|
||||
else
|
||||
addr.addr = string.format('%s@', addr.user)
|
||||
end
|
||||
|
||||
if addr.name and #addr.name > 0 then
|
||||
addr.raw = string.format('"%s" <%s>', addr.name, addr.addr)
|
||||
else
|
||||
addr.raw = string.format('<%s>', addr.addr)
|
||||
end
|
||||
end
|
||||
|
||||
local function check_gmail(addr)
|
||||
local nu, tags, nd = check_gmail_user(addr)
|
||||
|
||||
if nu then
|
||||
return nu, tags, nd
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function check_googlemail(addr)
|
||||
local nd = 'gmail.com'
|
||||
local nu, tags = check_gmail_user(addr)
|
||||
|
||||
if nu then
|
||||
return nu, tags, nd
|
||||
end
|
||||
|
||||
return nil, nil, nd
|
||||
end
|
||||
|
||||
local specific_domains = {
|
||||
['gmail.com'] = check_gmail,
|
||||
['googlemail.com'] = check_googlemail,
|
||||
}
|
||||
|
||||
if email_addr then
|
||||
if email_addr.domain and specific_domains[email_addr.domain] then
|
||||
local nu, tags, nd = specific_domains[email_addr.domain](email_addr)
|
||||
if nu or nd then
|
||||
set_addr(email_addr, nu, nd)
|
||||
|
||||
return nu, tags
|
||||
end
|
||||
else
|
||||
local nu, tags, nd = check_address(email_addr)
|
||||
if nu or nd then
|
||||
set_addr(email_addr, nu, nd)
|
||||
|
||||
return nu, tags
|
||||
end
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
end
|
||||
|
||||
exports.is_rspamc_or_controller = function(task)
|
||||
local ua = task:get_request_header('User-Agent') or ''
|
||||
local pwd = task:get_request_header('Password')
|
||||
local is_rspamc = false
|
||||
if tostring(ua) == 'rspamc' or pwd then is_rspamc = true end
|
||||
|
||||
return is_rspamc
|
||||
end
|
||||
|
||||
local unpack_function = table.unpack or unpack
|
||||
exports.unpack = function(t)
|
||||
return unpack_function(t)
|
||||
end
|
||||
|
||||
return exports
|
|
@ -1,674 +0,0 @@
|
|||
--[[
|
||||
Copyright (c) 2011-2017, Vsevolod Stakhov <vsevolod@highsecure.ru>
|
||||
Copyright (c) 2016-2017, Andrew Lewis <nerf@judo.za.org>
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
You may obtain a copy of the License at
|
||||
|
||||
http://www.apache.org/licenses/LICENSE-2.0
|
||||
|
||||
Unless required by applicable law or agreed to in writing, software
|
||||
distributed under the License is distributed on an "AS IS" BASIS,
|
||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
See the License for the specific language governing permissions and
|
||||
limitations under the License.
|
||||
]]--
|
||||
|
||||
if confighelp then
|
||||
return
|
||||
end
|
||||
|
||||
-- A plugin that implements ratelimits using redis
|
||||
|
||||
local E = {}
|
||||
local N = 'ratelimit'
|
||||
local redis_params
|
||||
-- Senders that are considered as bounce
|
||||
local settings = {
|
||||
bounce_senders = { 'postmaster', 'mailer-daemon', '', 'null', 'fetchmail-daemon', 'mdaemon' },
|
||||
-- Do not check ratelimits for these recipients
|
||||
whitelisted_rcpts = { 'postmaster', 'mailer-daemon' },
|
||||
prefix = 'RL',
|
||||
ham_factor_rate = 1.01,
|
||||
spam_factor_rate = 0.99,
|
||||
ham_factor_burst = 1.02,
|
||||
spam_factor_burst = 0.98,
|
||||
max_rate_mult = 5,
|
||||
max_bucket_mult = 10,
|
||||
expire = 60 * 60 * 24 * 2, -- 2 days by default
|
||||
limits = {},
|
||||
allow_local = false,
|
||||
}
|
||||
|
||||
-- Checks bucket, updating it if needed
|
||||
-- KEYS[1] - prefix to update, e.g. RL_<triplet>_<seconds>
|
||||
-- KEYS[2] - current time in milliseconds
|
||||
-- KEYS[3] - bucket leak rate (messages per millisecond)
|
||||
-- KEYS[4] - bucket burst
|
||||
-- KEYS[5] - expire for a bucket
|
||||
-- return 1 if message should be ratelimited and 0 if not
|
||||
-- Redis keys used:
|
||||
-- l - last hit
|
||||
-- b - current burst
|
||||
-- dr - current dynamic rate multiplier (*10000)
|
||||
-- db - current dynamic burst multiplier (*10000)
|
||||
local bucket_check_script = [[
|
||||
local last = redis.call('HGET', KEYS[1], 'l')
|
||||
local now = tonumber(KEYS[2])
|
||||
local dynr, dynb = 0, 0
|
||||
if not last then
|
||||
-- New bucket
|
||||
redis.call('HSET', KEYS[1], 'l', KEYS[2])
|
||||
redis.call('HSET', KEYS[1], 'b', '0')
|
||||
redis.call('HSET', KEYS[1], 'dr', '10000')
|
||||
redis.call('HSET', KEYS[1], 'db', '10000')
|
||||
redis.call('EXPIRE', KEYS[1], KEYS[5])
|
||||
return {0, 0, 1, 1}
|
||||
end
|
||||
|
||||
last = tonumber(last)
|
||||
local burst = tonumber(redis.call('HGET', KEYS[1], 'b'))
|
||||
-- Perform leak
|
||||
if burst > 0 then
|
||||
if last < tonumber(KEYS[2]) then
|
||||
local rate = tonumber(KEYS[3])
|
||||
dynr = tonumber(redis.call('HGET', KEYS[1], 'dr')) / 10000.0
|
||||
rate = rate * dynr
|
||||
local leaked = ((now - last) * rate)
|
||||
burst = burst - leaked
|
||||
redis.call('HINCRBYFLOAT', KEYS[1], 'b', -(leaked))
|
||||
end
|
||||
else
|
||||
burst = 0
|
||||
redis.call('HSET', KEYS[1], 'b', '0')
|
||||
end
|
||||
|
||||
dynb = tonumber(redis.call('HGET', KEYS[1], 'db')) / 10000.0
|
||||
|
||||
if (burst + 1) * dynb > tonumber(KEYS[4]) then
|
||||
return {1, tostring(burst), tostring(dynr), tostring(dynb)}
|
||||
end
|
||||
|
||||
return {0, tostring(burst), tostring(dynr), tostring(dynb)}
|
||||
]]
|
||||
local bucket_check_id
|
||||
|
||||
|
||||
-- Updates a bucket
|
||||
-- KEYS[1] - prefix to update, e.g. RL_<triplet>_<seconds>
|
||||
-- KEYS[2] - current time in milliseconds
|
||||
-- KEYS[3] - dynamic rate multiplier
|
||||
-- KEYS[4] - dynamic burst multiplier
|
||||
-- KEYS[5] - max dyn rate (min: 1/x)
|
||||
-- KEYS[6] - max burst rate (min: 1/x)
|
||||
-- KEYS[7] - expire for a bucket
|
||||
-- Redis keys used:
|
||||
-- l - last hit
|
||||
-- b - current burst
|
||||
-- dr - current dynamic rate multiplier
|
||||
-- db - current dynamic burst multiplier
|
||||
local bucket_update_script = [[
|
||||
local last = redis.call('HGET', KEYS[1], 'l')
|
||||
local now = tonumber(KEYS[2])
|
||||
if not last then
|
||||
-- New bucket
|
||||
redis.call('HSET', KEYS[1], 'l', KEYS[2])
|
||||
redis.call('HSET', KEYS[1], 'b', '1')
|
||||
redis.call('HSET', KEYS[1], 'dr', '10000')
|
||||
redis.call('HSET', KEYS[1], 'db', '10000')
|
||||
redis.call('EXPIRE', KEYS[1], KEYS[7])
|
||||
return {1, 1, 1}
|
||||
end
|
||||
|
||||
local burst = tonumber(redis.call('HGET', KEYS[1], 'b'))
|
||||
local db = tonumber(redis.call('HGET', KEYS[1], 'db')) / 10000
|
||||
local dr = tonumber(redis.call('HGET', KEYS[1], 'dr')) / 10000
|
||||
|
||||
if dr < tonumber(KEYS[5]) and dr > 1.0 / tonumber(KEYS[5]) then
|
||||
dr = dr * tonumber(KEYS[3])
|
||||
redis.call('HSET', KEYS[1], 'dr', tostring(math.floor(dr * 10000)))
|
||||
end
|
||||
|
||||
if db < tonumber(KEYS[6]) and db > 1.0 / tonumber(KEYS[6]) then
|
||||
db = db * tonumber(KEYS[4])
|
||||
redis.call('HSET', KEYS[1], 'db', tostring(math.floor(db * 10000)))
|
||||
end
|
||||
|
||||
redis.call('HINCRBYFLOAT', KEYS[1], 'b', 1)
|
||||
redis.call('HSET', KEYS[1], 'l', KEYS[2])
|
||||
redis.call('EXPIRE', KEYS[1], KEYS[7])
|
||||
|
||||
return {tostring(burst), tostring(dr), tostring(db)}
|
||||
]]
|
||||
local bucket_update_id
|
||||
|
||||
-- message_func(task, limit_type, prefix, bucket)
|
||||
local message_func = function(_, limit_type, _, _)
|
||||
return string.format('Ratelimit "%s" exceeded', limit_type)
|
||||
end
|
||||
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
local rspamd_util = require "rspamd_util"
|
||||
local rspamd_lua_utils = require "lua_util"
|
||||
local lua_redis = require "lua_redis"
|
||||
local fun = require "fun"
|
||||
local lua_maps = require "lua_maps"
|
||||
local lua_util = require "lua_util"
|
||||
local rspamd_hash = require "rspamd_cryptobox_hash"
|
||||
|
||||
|
||||
local function load_scripts(cfg, ev_base)
|
||||
bucket_check_id = lua_redis.add_redis_script(bucket_check_script, redis_params)
|
||||
bucket_update_id = lua_redis.add_redis_script(bucket_update_script, redis_params)
|
||||
end
|
||||
|
||||
local limit_parser
|
||||
local function parse_string_limit(lim, no_error)
|
||||
local function parse_time_suffix(s)
|
||||
if s == 's' then
|
||||
return 1
|
||||
elseif s == 'm' then
|
||||
return 60
|
||||
elseif s == 'h' then
|
||||
return 3600
|
||||
elseif s == 'd' then
|
||||
return 86400
|
||||
end
|
||||
end
|
||||
local function parse_num_suffix(s)
|
||||
if s == '' then
|
||||
return 1
|
||||
elseif s == 'k' then
|
||||
return 1000
|
||||
elseif s == 'm' then
|
||||
return 1000000
|
||||
elseif s == 'g' then
|
||||
return 1000000000
|
||||
end
|
||||
end
|
||||
local lpeg = require "lpeg"
|
||||
|
||||
if not limit_parser then
|
||||
local digit = lpeg.R("09")
|
||||
limit_parser = {}
|
||||
limit_parser.integer =
|
||||
(lpeg.S("+-") ^ -1) *
|
||||
(digit ^ 1)
|
||||
limit_parser.fractional =
|
||||
(lpeg.P(".") ) *
|
||||
(digit ^ 1)
|
||||
limit_parser.number =
|
||||
(limit_parser.integer *
|
||||
(limit_parser.fractional ^ -1)) +
|
||||
(lpeg.S("+-") * limit_parser.fractional)
|
||||
limit_parser.time = lpeg.Cf(lpeg.Cc(1) *
|
||||
(limit_parser.number / tonumber) *
|
||||
((lpeg.S("smhd") / parse_time_suffix) ^ -1),
|
||||
function (acc, val) return acc * val end)
|
||||
limit_parser.suffixed_number = lpeg.Cf(lpeg.Cc(1) *
|
||||
(limit_parser.number / tonumber) *
|
||||
((lpeg.S("kmg") / parse_num_suffix) ^ -1),
|
||||
function (acc, val) return acc * val end)
|
||||
limit_parser.limit = lpeg.Ct(limit_parser.suffixed_number *
|
||||
(lpeg.S(" ") ^ 0) * lpeg.S("/") * (lpeg.S(" ") ^ 0) *
|
||||
limit_parser.time)
|
||||
end
|
||||
local t = lpeg.match(limit_parser.limit, lim)
|
||||
|
||||
if t and t[1] and t[2] and t[2] ~= 0 then
|
||||
return t[2], t[1]
|
||||
end
|
||||
|
||||
if not no_error then
|
||||
rspamd_logger.errx(rspamd_config, 'bad limit: %s', lim)
|
||||
end
|
||||
|
||||
return nil
|
||||
end
|
||||
|
||||
local function parse_limit(name, data)
|
||||
local buckets = {}
|
||||
if type(data) == 'table' then
|
||||
-- 3 cases here:
|
||||
-- * old limit in format [burst, rate]
|
||||
-- * vector of strings in Andrew's string format
|
||||
-- * proper bucket table
|
||||
if #data == 2 and tonumber(data[1]) and tonumber(data[2]) then
|
||||
-- Old style ratelimit
|
||||
rspamd_logger.warnx(rspamd_config, 'old style ratelimit for %s', name)
|
||||
if tonumber(data[1]) > 0 and tonumber(data[2]) > 0 then
|
||||
table.insert(buckets, {
|
||||
burst = data[1],
|
||||
rate = data[2]
|
||||
})
|
||||
elseif data[1] ~= 0 then
|
||||
rspamd_logger.warnx(rspamd_config, 'invalid numbers for %s', name)
|
||||
else
|
||||
rspamd_logger.infox(rspamd_config, 'disable limit %s, burst is zero', name)
|
||||
end
|
||||
else
|
||||
-- Recursively map parse_limit and flatten the list
|
||||
fun.each(function(l)
|
||||
-- Flatten list
|
||||
for _,b in ipairs(l) do table.insert(buckets, b) end
|
||||
end, fun.map(function(d) return parse_limit(d, name) end, data))
|
||||
end
|
||||
elseif type(data) == 'string' then
|
||||
local rep_rate, burst = parse_string_limit(data)
|
||||
|
||||
if rep_rate and burst then
|
||||
table.insert(buckets, {
|
||||
burst = burst,
|
||||
rate = 1.0 / rep_rate -- reciprocal
|
||||
})
|
||||
end
|
||||
end
|
||||
|
||||
-- Filter valid
|
||||
return fun.totable(fun.filter(function(val)
|
||||
return type(val.burst) == 'number' and type(val.rate) == 'number'
|
||||
end, buckets))
|
||||
end
|
||||
|
||||
--- Check whether this addr is bounce
|
||||
local function check_bounce(from)
|
||||
return fun.any(function(b) return b == from end, settings.bounce_senders)
|
||||
end
|
||||
|
||||
local keywords = {
|
||||
['ip'] = {
|
||||
['get_value'] = function(task)
|
||||
local ip = task:get_ip()
|
||||
if ip and ip:is_valid() then return tostring(ip) end
|
||||
return nil
|
||||
end,
|
||||
},
|
||||
['rip'] = {
|
||||
['get_value'] = function(task)
|
||||
local ip = task:get_ip()
|
||||
if ip and ip:is_valid() and not ip:is_local() then return tostring(ip) end
|
||||
return nil
|
||||
end,
|
||||
},
|
||||
['from'] = {
|
||||
['get_value'] = function(task)
|
||||
local from = task:get_from(0)
|
||||
if ((from or E)[1] or E).addr then
|
||||
return string.lower(from[1]['addr'])
|
||||
end
|
||||
return nil
|
||||
end,
|
||||
},
|
||||
['bounce'] = {
|
||||
['get_value'] = function(task)
|
||||
local from = task:get_from(0)
|
||||
if not ((from or E)[1] or E).user then
|
||||
return '_'
|
||||
end
|
||||
if check_bounce(from[1]['user']) then return '_' else return nil end
|
||||
end,
|
||||
},
|
||||
['asn'] = {
|
||||
['get_value'] = function(task)
|
||||
local asn = task:get_mempool():get_variable('asn')
|
||||
if not asn then
|
||||
return nil
|
||||
else
|
||||
return asn
|
||||
end
|
||||
end,
|
||||
},
|
||||
['user'] = {
|
||||
['get_value'] = function(task)
|
||||
local auser = task:get_user()
|
||||
if not auser then
|
||||
return nil
|
||||
else
|
||||
return auser
|
||||
end
|
||||
end,
|
||||
},
|
||||
['to'] = {
|
||||
['get_value'] = function(task)
|
||||
return task:get_principal_recipient()
|
||||
end,
|
||||
},
|
||||
}
|
||||
|
||||
local function gen_rate_key(task, rtype, bucket)
|
||||
local key_t = {tostring(lua_util.round(100000.0 / bucket.burst))}
|
||||
local key_keywords = lua_util.str_split(rtype, '_')
|
||||
local have_user = false
|
||||
|
||||
for _, v in ipairs(key_keywords) do
|
||||
local ret
|
||||
|
||||
if keywords[v] and type(keywords[v]['get_value']) == 'function' then
|
||||
ret = keywords[v]['get_value'](task)
|
||||
end
|
||||
if not ret then return nil end
|
||||
if v == 'user' then have_user = true end
|
||||
if type(ret) ~= 'string' then ret = tostring(ret) end
|
||||
table.insert(key_t, ret)
|
||||
end
|
||||
|
||||
if have_user and not task:get_user() then
|
||||
return nil
|
||||
end
|
||||
|
||||
return table.concat(key_t, ":")
|
||||
end
|
||||
|
||||
local function make_prefix(redis_key, name, bucket)
|
||||
local hash_len = 24
|
||||
if hash_len > #redis_key then hash_len = #redis_key end
|
||||
local hash = settings.prefix ..
|
||||
string.sub(rspamd_hash.create(redis_key):base32(), 1, hash_len)
|
||||
-- Fill defaults
|
||||
if not bucket.spam_factor_rate then
|
||||
bucket.spam_factor_rate = settings.spam_factor_rate
|
||||
end
|
||||
if not bucket.ham_factor_rate then
|
||||
bucket.ham_factor_rate = settings.ham_factor_rate
|
||||
end
|
||||
if not bucket.spam_factor_burst then
|
||||
bucket.spam_factor_burst = settings.spam_factor_burst
|
||||
end
|
||||
if not bucket.ham_factor_burst then
|
||||
bucket.ham_factor_burst = settings.ham_factor_burst
|
||||
end
|
||||
|
||||
return {
|
||||
bucket = bucket,
|
||||
name = name,
|
||||
hash = hash
|
||||
}
|
||||
end
|
||||
|
||||
local function limit_to_prefixes(task, k, v, prefixes)
|
||||
local n = 0
|
||||
for _,bucket in ipairs(v) do
|
||||
local prefix = gen_rate_key(task, k, bucket)
|
||||
|
||||
if prefix then
|
||||
prefixes[prefix] = make_prefix(prefix, k, bucket)
|
||||
n = n + 1
|
||||
end
|
||||
end
|
||||
|
||||
return n
|
||||
end
|
||||
|
||||
local function ratelimit_cb(task)
|
||||
if not settings.allow_local and
|
||||
rspamd_lua_utils.is_rspamc_or_controller(task) then return end
|
||||
|
||||
-- Get initial task data
|
||||
local ip = task:get_from_ip()
|
||||
if ip and ip:is_valid() and settings.whitelisted_ip then
|
||||
if settings.whitelisted_ip:get_key(ip) then
|
||||
-- Do not check whitelisted ip
|
||||
rspamd_logger.infox(task, 'skip ratelimit for whitelisted IP')
|
||||
return
|
||||
end
|
||||
end
|
||||
-- Parse all rcpts
|
||||
local rcpts = task:get_recipients()
|
||||
local rcpts_user = {}
|
||||
if rcpts then
|
||||
fun.each(function(r)
|
||||
fun.each(function(type) table.insert(rcpts_user, r[type]) end, {'user', 'addr'})
|
||||
end, rcpts)
|
||||
|
||||
if fun.any(function(r) return settings.whitelisted_rcpts:get_key(r) end, rcpts_user) then
|
||||
rspamd_logger.infox(task, 'skip ratelimit for whitelisted recipient')
|
||||
return
|
||||
end
|
||||
end
|
||||
-- Get user (authuser)
|
||||
if settings.whitelisted_user then
|
||||
local auser = task:get_user()
|
||||
if settings.whitelisted_user:get_key(auser) then
|
||||
rspamd_logger.infox(task, 'skip ratelimit for whitelisted user')
|
||||
return
|
||||
end
|
||||
end
|
||||
-- Now create all ratelimit prefixes
|
||||
local prefixes = {}
|
||||
local nprefixes = 0
|
||||
|
||||
for k,v in pairs(settings.limits) do
|
||||
nprefixes = nprefixes + limit_to_prefixes(task, k, v, prefixes)
|
||||
end
|
||||
|
||||
for k, hdl in pairs(settings.custom_keywords or E) do
|
||||
local ret, redis_key, bd = pcall(hdl, task)
|
||||
|
||||
if ret then
|
||||
local bucket = parse_limit(k, bd)
|
||||
if bucket[1] then
|
||||
prefixes[redis_key] = make_prefix(redis_key, k, bucket[1])
|
||||
end
|
||||
nprefixes = nprefixes + 1
|
||||
else
|
||||
rspamd_logger.errx(task, 'cannot call handler for %s: %s',
|
||||
k, redis_key)
|
||||
end
|
||||
end
|
||||
|
||||
local function gen_check_cb(prefix, bucket, lim_name)
|
||||
return function(err, data)
|
||||
if err then
|
||||
rspamd_logger.errx('cannot check limit %s: %s %s', prefix, err, data)
|
||||
elseif type(data) == 'table' and data[1] and data[1] == 1 then
|
||||
-- set symbol only and do NOT soft reject
|
||||
if settings.symbol then
|
||||
task:insert_result(settings.symbol, 0.0, lim_name .. "(" .. prefix .. ")")
|
||||
rspamd_logger.infox(task,
|
||||
'set_symbol_only: ratelimit "%s(%s)" exceeded, (%s / %s): %s (%s:%s dyn)',
|
||||
lim_name, prefix,
|
||||
bucket.burst, bucket.rate,
|
||||
data[2], data[3], data[4])
|
||||
return
|
||||
-- set INFO symbol and soft reject
|
||||
elseif settings.info_symbol then
|
||||
task:insert_result(settings.info_symbol, 1.0,
|
||||
lim_name .. "(" .. prefix .. ")")
|
||||
end
|
||||
rspamd_logger.infox(task,
|
||||
'ratelimit "%s(%s)" exceeded, (%s / %s): %s (%s:%s dyn)',
|
||||
lim_name, prefix,
|
||||
bucket.burst, bucket.rate,
|
||||
data[2], data[3], data[4])
|
||||
task:set_pre_result('soft reject',
|
||||
message_func(task, lim_name, prefix, bucket))
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- Don't do anything if pre-result has been already set
|
||||
if task:has_pre_result() then return end
|
||||
|
||||
if nprefixes > 0 then
|
||||
-- Save prefixes to the cache to allow update
|
||||
task:cache_set('ratelimit_prefixes', prefixes)
|
||||
local now = rspamd_util.get_time()
|
||||
now = lua_util.round(now * 1000.0) -- Get milliseconds
|
||||
-- Now call check script for all defined prefixes
|
||||
|
||||
for pr,value in pairs(prefixes) do
|
||||
local bucket = value.bucket
|
||||
local rate = (bucket.rate) / 1000.0 -- Leak rate in messages/ms
|
||||
rspamd_logger.debugm(N, task, "check limit %s:%s -> %s (%s/%s)",
|
||||
value.name, pr, value.hash, bucket.burst, bucket.rate)
|
||||
lua_redis.exec_redis_script(bucket_check_id,
|
||||
{key = value.hash, task = task, is_write = true},
|
||||
gen_check_cb(pr, bucket, value.name),
|
||||
{value.hash, tostring(now), tostring(rate), tostring(bucket.burst),
|
||||
tostring(settings.expire)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local function ratelimit_update_cb(task)
|
||||
local prefixes = task:cache_get('ratelimit_prefixes')
|
||||
|
||||
if prefixes then
|
||||
if task:has_pre_result() then
|
||||
-- Already rate limited/greylisted, do nothing
|
||||
rspamd_logger.debugm(N, task, 'pre-action has been set, do not update')
|
||||
return
|
||||
end
|
||||
|
||||
local is_spam = not (task:get_metric_action() == 'no action')
|
||||
|
||||
-- Update each bucket
|
||||
for k, v in pairs(prefixes) do
|
||||
local bucket = v.bucket
|
||||
local function update_bucket_cb(err, data)
|
||||
if err then
|
||||
rspamd_logger.errx(task, 'cannot update rate bucket %s: %s',
|
||||
k, err)
|
||||
else
|
||||
rspamd_logger.debugm(N, task,
|
||||
"updated limit %s:%s -> %s (%s/%s), burst: %s, dyn_rate: %s, dyn_burst: %s",
|
||||
v.name, k, v.hash,
|
||||
bucket.burst, bucket.rate,
|
||||
data[1], data[2], data[3])
|
||||
end
|
||||
end
|
||||
local now = rspamd_util.get_time()
|
||||
now = lua_util.round(now * 1000.0) -- Get milliseconds
|
||||
local mult_burst = bucket.ham_factor_burst or 1.0
|
||||
local mult_rate = bucket.ham_factor_burst or 1.0
|
||||
|
||||
if is_spam then
|
||||
mult_burst = bucket.spam_factor_burst or 1.0
|
||||
mult_rate = bucket.spam_factor_rate or 1.0
|
||||
end
|
||||
|
||||
lua_redis.exec_redis_script(bucket_update_id,
|
||||
{key = v.hash, task = task, is_write = true},
|
||||
update_bucket_cb,
|
||||
{v.hash, tostring(now), tostring(mult_rate), tostring(mult_burst),
|
||||
tostring(settings.max_rate_mult), tostring(settings.max_bucket_mult),
|
||||
tostring(settings.expire)})
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
local opts = rspamd_config:get_all_opt(N)
|
||||
if opts then
|
||||
|
||||
settings = lua_util.override_defaults(settings, opts)
|
||||
|
||||
if opts['limit'] then
|
||||
rspamd_logger.errx(rspamd_config, 'Legacy ratelimit config format no longer supported')
|
||||
end
|
||||
|
||||
if opts['rates'] and type(opts['rates']) == 'table' then
|
||||
-- new way of setting limits
|
||||
fun.each(function(t, lim)
|
||||
local buckets = parse_limit(t, lim)
|
||||
|
||||
if buckets and #buckets > 0 then
|
||||
settings.limits[t] = buckets
|
||||
end
|
||||
end, opts['rates'])
|
||||
end
|
||||
|
||||
local enabled_limits = fun.totable(fun.map(function(t)
|
||||
return t
|
||||
end, settings.limits))
|
||||
rspamd_logger.infox(rspamd_config,
|
||||
'enabled rate buckets: [%1]', table.concat(enabled_limits, ','))
|
||||
|
||||
-- Ret, ret, ret: stupid legacy stuff:
|
||||
-- If we have a string with commas then load it as as static map
|
||||
-- otherwise, apply normal logic of Rspamd maps
|
||||
|
||||
local wrcpts = opts['whitelisted_rcpts']
|
||||
if type(wrcpts) == 'string' then
|
||||
if string.find(wrcpts, ',') then
|
||||
settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(
|
||||
lua_util.rspamd_str_split(wrcpts, ','), 'set', 'Ratelimit whitelisted rcpts')
|
||||
else
|
||||
settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(wrcpts, 'set',
|
||||
'Ratelimit whitelisted rcpts')
|
||||
end
|
||||
elseif type(opts['whitelisted_rcpts']) == 'table' then
|
||||
settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(wrcpts, 'set',
|
||||
'Ratelimit whitelisted rcpts')
|
||||
else
|
||||
-- Stupid default...
|
||||
settings.whitelisted_rcpts = lua_maps.rspamd_map_add_from_ucl(
|
||||
settings.whitelisted_rcpts, 'set', 'Ratelimit whitelisted rcpts')
|
||||
end
|
||||
|
||||
if opts['whitelisted_ip'] then
|
||||
settings.whitelisted_ip = lua_maps.rspamd_map_add('ratelimit', 'whitelisted_ip', 'radix',
|
||||
'Ratelimit whitelist ip map')
|
||||
end
|
||||
|
||||
if opts['whitelisted_user'] then
|
||||
settings.whitelisted_user = lua_maps.rspamd_map_add('ratelimit', 'whitelisted_user', 'set',
|
||||
'Ratelimit whitelist user map')
|
||||
end
|
||||
|
||||
settings.custom_keywords = {}
|
||||
if opts['custom_keywords'] then
|
||||
local ret, res_or_err = pcall(loadfile(opts['custom_keywords']))
|
||||
|
||||
if ret then
|
||||
opts['custom_keywords'] = {}
|
||||
if type(res_or_err) == 'table' then
|
||||
for k,hdl in pairs(res_or_err) do
|
||||
settings['custom_keywords'][k] = hdl
|
||||
end
|
||||
elseif type(res_or_err) == 'function' then
|
||||
settings['custom_keywords']['custom'] = res_or_err
|
||||
end
|
||||
else
|
||||
rspamd_logger.errx(rspamd_config, 'cannot execute %s: %s',
|
||||
opts['custom_keywords'], res_or_err)
|
||||
settings['custom_keywords'] = {}
|
||||
end
|
||||
end
|
||||
|
||||
if opts['message_func'] then
|
||||
message_func = assert(load(opts['message_func']))()
|
||||
end
|
||||
|
||||
redis_params = lua_redis.parse_redis_server('ratelimit')
|
||||
|
||||
if not redis_params then
|
||||
rspamd_logger.infox(rspamd_config, 'no servers are specified, disabling module')
|
||||
lua_util.disable_module(N, "redis")
|
||||
else
|
||||
local s = {
|
||||
type = 'prefilter,nostat',
|
||||
name = 'RATELIMIT_CHECK',
|
||||
priority = 7,
|
||||
callback = ratelimit_cb,
|
||||
flags = 'empty',
|
||||
}
|
||||
|
||||
if settings.symbol then
|
||||
s.name = settings.symbol
|
||||
elseif settings.info_symbol then
|
||||
s.name = settings.info_symbol
|
||||
end
|
||||
|
||||
rspamd_config:register_symbol(s)
|
||||
rspamd_config:register_symbol {
|
||||
type = 'idempotent',
|
||||
name = 'RATELIMIT_UPDATE',
|
||||
callback = ratelimit_update_cb,
|
||||
}
|
||||
end
|
||||
end
|
||||
|
||||
rspamd_config:add_on_load(function(cfg, ev_base, worker)
|
||||
load_scripts(cfg, ev_base)
|
||||
end)
|
|
@ -49,4 +49,6 @@ COPY sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg
|
|||
COPY acl.diff /acl.diff
|
||||
CMD exec /usr/bin/supervisord -c /etc/supervisor/supervisord.conf
|
||||
|
||||
VOLUME /usr/lib/GNUstep/SOGo/
|
||||
|
||||
RUN rm -rf /tmp/* /var/tmp/*
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
#!/bin/bash
|
||||
|
||||
# Wait for MySQL to warm-up
|
||||
while ! mysqladmin ping --host mysql -u${DBUSER} -p${DBPASS} --silent; do
|
||||
while ! mysqladmin ping --socket=/var/run/mysqld/mysqld.sock -u${DBUSER} -p${DBPASS} --silent; do
|
||||
echo "Waiting for database to come up..."
|
||||
sleep 2
|
||||
done
|
||||
|
@ -15,10 +15,10 @@ done
|
|||
|
||||
# Recreate view
|
||||
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
|
||||
|
||||
while [[ ${VIEW_OK} != 'OK' ]]; do
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, home, kind, multiple_bookings) AS
|
||||
SELECT mailbox.username, mailbox.domain, mailbox.username, if(json_extract(attributes, '$.force_pw_update') LIKE '%0%', password, 'invalid'), mailbox.name, mailbox.username, IFNULL(GROUP_CONCAT(ga.aliases SEPARATOR ' '), ''), IFNULL(gda.ad_alias, ''), CONCAT('/var/vmail/', maildir), mailbox.kind, mailbox.multiple_bookings FROM mailbox
|
||||
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
||||
|
@ -26,7 +26,7 @@ LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.usern
|
|||
WHERE mailbox.active = '1'
|
||||
GROUP BY mailbox.username;
|
||||
EOF
|
||||
if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'sogo_view'") ]]; then
|
||||
VIEW_OK=OK
|
||||
else
|
||||
echo "Will retry to setup SOGo view in 3s"
|
||||
|
@ -37,11 +37,11 @@ done
|
|||
# Wait for static view table if missing after update and update content
|
||||
|
||||
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do
|
||||
if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = '_sogo_static_view'") ]]; then
|
||||
STATIC_VIEW_OK=OK
|
||||
echo "Updating _sogo_static_view content..."
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view SELECT * from sogo_view"
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')"
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "REPLACE INTO _sogo_static_view SELECT * from sogo_view"
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')"
|
||||
else
|
||||
echo "Waiting for database initialization..."
|
||||
sleep 3
|
||||
|
@ -50,10 +50,10 @@ done
|
|||
|
||||
# Recreate password update trigger
|
||||
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP TRIGGER IF EXISTS sogo_update_password"
|
||||
|
||||
while [[ ${TRIGGER_OK} != 'OK' ]]; do
|
||||
mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
|
||||
DELIMITER -
|
||||
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
|
||||
FOR EACH ROW
|
||||
|
@ -63,7 +63,7 @@ END;
|
|||
-
|
||||
DELIMITER ;
|
||||
EOF
|
||||
if [[ ! -z $(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then
|
||||
if [[ ! -z $(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -B -e "SELECT 'OK' FROM INFORMATION_SCHEMA.TRIGGERS WHERE TRIGGER_NAME = 'sogo_update_password'") ]]; then
|
||||
TRIGGER_OK=OK
|
||||
else
|
||||
echo "Will retry to setup SOGo password update trigger in 3s"
|
||||
|
@ -81,19 +81,19 @@ cat <<EOF > /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
|||
<plist version="0.9">
|
||||
<dict>
|
||||
<key>OCSAclURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_acl</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_acl</string>
|
||||
<key>OCSCacheFolderURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_cache_folder</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_cache_folder</string>
|
||||
<key>OCSEMailAlarmsFolderURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_alarms_folder</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_alarms_folder</string>
|
||||
<key>OCSFolderInfoURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_folder_info</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_folder_info</string>
|
||||
<key>OCSSessionsFolderURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_sessions_folder</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_sessions_folder</string>
|
||||
<key>OCSStoreURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_store</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_store</string>
|
||||
<key>SOGoProfileURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/sogo_user_profile</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/sogo_user_profile</string>
|
||||
<key>SOGoTimeZone</key>
|
||||
<string>${TZ}</string>
|
||||
<key>domains</key>
|
||||
|
@ -138,11 +138,11 @@ while read line
|
|||
<key>prependPasswordScheme</key>
|
||||
<string>YES</string>
|
||||
<key>viewURL</key>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@mysql:3306/${DBNAME}/_sogo_static_view</string>
|
||||
<string>mysql://${DBUSER}:${DBPASS}@%2Fvar%2Frun%2Fmysqld%2Fmysqld.sock/${DBNAME}/_sogo_static_view</string>
|
||||
</dict>
|
||||
</array>
|
||||
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist
|
||||
done < <(mysql --host mysql -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain;" -B -N)
|
||||
done < <(mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SELECT domain FROM domain;" -B -N)
|
||||
|
||||
# Generate footer
|
||||
echo ' </dict>
|
||||
|
|
|
@ -16,13 +16,6 @@ command=/usr/sbin/cron -f
|
|||
autorestart=true
|
||||
priority=2
|
||||
|
||||
[program:sogo-webres]
|
||||
command=/usr/bin/python -u -m SimpleHTTPServer 9192
|
||||
directory=/usr/lib/GNUstep/SOGo/
|
||||
user=sogo
|
||||
autorestart=true
|
||||
priority=4
|
||||
|
||||
[program:bootstrap-sogo]
|
||||
command=/bootstrap-sogo.sh
|
||||
stdout_logfile=/dev/stdout
|
||||
|
|
|
@ -10,6 +10,7 @@ RUN apk add --update --no-cache \
|
|||
drill \
|
||||
&& curl -o /etc/unbound/root.hints https://www.internic.net/domain/named.cache \
|
||||
&& chown root:unbound /etc/unbound \
|
||||
&& adduser unbound tty \
|
||||
&& chmod 775 /etc/unbound
|
||||
|
||||
EXPOSE 53/udp 53/tcp
|
||||
|
|
|
@ -1,8 +1,11 @@
|
|||
#!/bin/bash
|
||||
|
||||
echo "Setting console permissions..."
|
||||
chown root:tty /dev/console
|
||||
chmod g+rw /dev/console
|
||||
echo "Receiving anchor key..."
|
||||
/usr/sbin/unbound-anchor -a /etc/unbound/trusted-key.key
|
||||
echo "Receiving root hints..."
|
||||
curl -#o /etc/unbound/root.hints https://www.internic.net/domain/named.cache
|
||||
|
||||
/usr/sbin/unbound-control-setup
|
||||
exec "$@"
|
||||
|
|
|
@ -59,36 +59,41 @@ function mail_error() {
|
|||
log_msg "Sent notification email to ${1}"
|
||||
}
|
||||
|
||||
|
||||
get_container_ip() {
|
||||
# ${1} is container
|
||||
CONTAINER_ID=()
|
||||
CONTAINER_IPS=()
|
||||
CONTAINER_IP=
|
||||
LOOP_C=1
|
||||
until [[ ${CONTAINER_IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ ${LOOP_C} -gt 5 ]]; do
|
||||
sleep 0.5
|
||||
# get long container id for exact match
|
||||
CONTAINER_ID=($(curl --silent http://dockerapi:8080/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | .id"))
|
||||
CONTAINER_ID=($(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring == \"${1}\") | .id"))
|
||||
# returned id can have multiple elements (if scaled), shuffle for random test
|
||||
CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf))
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
for matched_container in "${CONTAINER_ID[@]}"; do
|
||||
CONTAINER_IP=$(curl --silent http://dockerapi:8080/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress')
|
||||
CONTAINER_IPS=($(curl --silent --insecure https://dockerapi/containers/${matched_container}/json | jq -r '.NetworkSettings.Networks[].IPAddress'))
|
||||
for ip_match in "${CONTAINER_IPS[@]}"; do
|
||||
# grep will do nothing if one of these vars is empty
|
||||
[[ -z ${CONTAINER_IP} ]] && continue
|
||||
[[ -z ${ip_match} ]] && continue
|
||||
[[ -z ${IPV4_NETWORK} ]] && continue
|
||||
# only return ips that are part of our network
|
||||
if ! grep -q ${IPV4_NETWORK} <(echo ${CONTAINER_IP}); then
|
||||
CONTAINER_IP=
|
||||
if ! grep -q ${IPV4_NETWORK} <(echo ${ip_match}); then
|
||||
continue
|
||||
else
|
||||
CONTAINER_IP=${ip_match}
|
||||
break
|
||||
fi
|
||||
done
|
||||
[[ ! -z ${CONTAINER_IP} ]] && break
|
||||
done
|
||||
fi
|
||||
LOOP_C=$((LOOP_C + 1))
|
||||
done
|
||||
[[ ${LOOP_C} -gt 5 ]] && echo 240.0.0.0 || echo ${CONTAINER_IP}
|
||||
}
|
||||
|
||||
# Check functions
|
||||
nginx_checks() {
|
||||
err_count=0
|
||||
diff_c=0
|
||||
|
@ -118,8 +123,8 @@ mysql_checks() {
|
|||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||
host_ip=$(get_container_ip mysql-mailcow)
|
||||
err_c_cur=${err_count}
|
||||
/usr/lib/nagios/plugins/check_mysql -H ${host_ip} -P 3306 -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
/usr/lib/nagios/plugins/check_mysql_query -H ${host_ip} -P 3306 -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} -q "SELECT COUNT(*) FROM information_schema.tables" 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
/usr/lib/nagios/plugins/check_mysql -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
/usr/lib/nagios/plugins/check_mysql_query -s /var/run/mysqld/mysqld.sock -u ${DBUSER} -p ${DBPASS} -d ${DBNAME} -q "SELECT COUNT(*) FROM information_schema.tables" 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
||||
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||
progress "MySQL/MariaDB" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
|
||||
|
@ -138,7 +143,6 @@ sogo_checks() {
|
|||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||
host_ip=$(get_container_ip sogo-mailcow)
|
||||
err_c_cur=${err_count}
|
||||
/usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /WebServerResources/css/theme-default.css -p 9192 -R md-default-theme 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
/usr/lib/nagios/plugins/check_http -4 -H ${host_ip} -u /SOGo.index/ -p 20000 -R "SOGo\.MainUI" 1>&2; err_count=$(( ${err_count} + $? ))
|
||||
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
|
||||
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
|
||||
|
@ -222,7 +226,7 @@ rspamd_checks() {
|
|||
while [ ${err_count} -lt ${THRESHOLD} ]; do
|
||||
host_ip=$(get_container_ip rspamd-mailcow)
|
||||
err_c_cur=${err_count}
|
||||
SCORE=$(/usr/bin/curl -s --data-binary @- --unix-socket /rspamd-sock/rspamd.sock http://rspamd/scan -d '
|
||||
SCORE=$(/usr/bin/curl -s --data-binary @- --unix-socket /var/lib/rspamd/rspamd.sock http://rspamd/scan -d '
|
||||
To: null@localhost
|
||||
From: watchdog@localhost
|
||||
|
||||
|
@ -338,12 +342,12 @@ done
|
|||
# Monitor dockerapi
|
||||
(
|
||||
while true; do
|
||||
while nc -z dockerapi 8080; do
|
||||
while nc -z dockerapi 443; do
|
||||
sleep 3
|
||||
done
|
||||
log_msg "Cannot find dockerapi-mailcow, waiting to recover..."
|
||||
kill -STOP ${BACKGROUND_TASKS[*]}
|
||||
until nc -z dockerapi 8080; do
|
||||
until nc -z dockerapi 443; do
|
||||
sleep 3
|
||||
done
|
||||
kill -CONT ${BACKGROUND_TASKS[*]}
|
||||
|
@ -358,10 +362,10 @@ while true; do
|
|||
if [[ ${com_pipe_answer} =~ .+-mailcow ]]; then
|
||||
kill -STOP ${BACKGROUND_TASKS[*]}
|
||||
sleep 3
|
||||
CONTAINER_ID=$(curl --silent http://dockerapi:8080/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | .id")
|
||||
CONTAINER_ID=$(curl --silent --insecure https://dockerapi/containers/json | jq -r ".[] | {name: .Config.Labels[\"com.docker.compose.service\"], id: .Id}" | jq -rc "select( .name | tostring | contains(\"${com_pipe_answer}\")) | .id")
|
||||
if [[ ! -z ${CONTAINER_ID} ]]; then
|
||||
log_msg "Sending restart command to ${CONTAINER_ID}..."
|
||||
curl --silent -XPOST http://dockerapi:8080/containers/${CONTAINER_ID}/restart
|
||||
curl --silent --insecure -XPOST https://dockerapi/containers/${CONTAINER_ID}/restart
|
||||
fi
|
||||
log_msg "Wait for restarted container to settle and continue watching..."
|
||||
sleep 30s
|
||||
|
|
|
@ -0,0 +1,192 @@
|
|||
#!/bin/bash
|
||||
set -eo pipefail
|
||||
shopt -s nullglob
|
||||
|
||||
openssl req -x509 -sha256 -newkey rsa:2048 -keyout /var/lib/mysql/sql.key -out /var/lib/mysql/sql.crt -days 3650 -nodes -subj '/CN=mysql'
|
||||
|
||||
# if command starts with an option, prepend mysqld
|
||||
if [ "${1:0:1}" = '-' ]; then
|
||||
set -- mysqld "$@"
|
||||
fi
|
||||
|
||||
# skip setup if they want an option that stops mysqld
|
||||
wantHelp=
|
||||
for arg; do
|
||||
case "$arg" in
|
||||
-'?'|--help|--print-defaults|-V|--version)
|
||||
wantHelp=1
|
||||
break
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# usage: file_env VAR [DEFAULT]
|
||||
# ie: file_env 'XYZ_DB_PASSWORD' 'example'
|
||||
# (will allow for "$XYZ_DB_PASSWORD_FILE" to fill in the value of
|
||||
# "$XYZ_DB_PASSWORD" from a file, especially for Docker's secrets feature)
|
||||
file_env() {
|
||||
local var="$1"
|
||||
local fileVar="${var}_FILE"
|
||||
local def="${2:-}"
|
||||
if [ "${!var:-}" ] && [ "${!fileVar:-}" ]; then
|
||||
echo >&2 "error: both $var and $fileVar are set (but are exclusive)"
|
||||
exit 1
|
||||
fi
|
||||
local val="$def"
|
||||
if [ "${!var:-}" ]; then
|
||||
val="${!var}"
|
||||
elif [ "${!fileVar:-}" ]; then
|
||||
val="$(< "${!fileVar}")"
|
||||
fi
|
||||
export "$var"="$val"
|
||||
unset "$fileVar"
|
||||
}
|
||||
|
||||
_check_config() {
|
||||
toRun=( "$@" --verbose --help --log-bin-index="$(mktemp -u)" )
|
||||
if ! errors="$("${toRun[@]}" 2>&1 >/dev/null)"; then
|
||||
cat >&2 <<-EOM
|
||||
|
||||
ERROR: mysqld failed while attempting to check config
|
||||
command was: "${toRun[*]}"
|
||||
|
||||
$errors
|
||||
EOM
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# Fetch value from server config
|
||||
# We use mysqld --verbose --help instead of my_print_defaults because the
|
||||
# latter only show values present in config files, and not server defaults
|
||||
_get_config() {
|
||||
local conf="$1"; shift
|
||||
"$@" --verbose --help --log-bin-index="$(mktemp -u)" 2>/dev/null | awk '$1 == "'"$conf"'" { print $2; exit }'
|
||||
}
|
||||
|
||||
# allow the container to be started with `--user`
|
||||
if [ "$1" = 'mysqld' -a -z "$wantHelp" -a "$(id -u)" = '0' ]; then
|
||||
_check_config "$@"
|
||||
DATADIR="$(_get_config 'datadir' "$@")"
|
||||
mkdir -p "$DATADIR"
|
||||
chown -R mysql:mysql "$DATADIR"
|
||||
exec gosu mysql "$BASH_SOURCE" "$@"
|
||||
fi
|
||||
|
||||
if [ "$1" = 'mysqld' -a -z "$wantHelp" ]; then
|
||||
# still need to check config, container may have started with --user
|
||||
_check_config "$@"
|
||||
# Get config
|
||||
DATADIR="$(_get_config 'datadir' "$@")"
|
||||
|
||||
if [ ! -d "$DATADIR/mysql" ]; then
|
||||
file_env 'MYSQL_ROOT_PASSWORD'
|
||||
if [ -z "$MYSQL_ROOT_PASSWORD" -a -z "$MYSQL_ALLOW_EMPTY_PASSWORD" -a -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
|
||||
echo >&2 'error: database is uninitialized and password option is not specified '
|
||||
echo >&2 ' You need to specify one of MYSQL_ROOT_PASSWORD, MYSQL_ALLOW_EMPTY_PASSWORD and MYSQL_RANDOM_ROOT_PASSWORD'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
mkdir -p "$DATADIR"
|
||||
|
||||
echo 'Initializing database'
|
||||
# "Other options are passed to mysqld." (so we pass all "mysqld" arguments directly here)
|
||||
mysql_install_db --datadir="$DATADIR" --rpm "${@:2}"
|
||||
echo 'Database initialized'
|
||||
|
||||
SOCKET="$(_get_config 'socket' "$@")"
|
||||
"$@" --skip-networking --socket="${SOCKET}" &
|
||||
pid="$!"
|
||||
|
||||
mysql=( mysql --protocol=socket -uroot -hlocalhost --socket="${SOCKET}" )
|
||||
|
||||
for i in {30..0}; do
|
||||
if echo 'SELECT 1' | "${mysql[@]}" &> /dev/null; then
|
||||
break
|
||||
fi
|
||||
echo 'MySQL init process in progress...'
|
||||
sleep 1
|
||||
done
|
||||
if [ "$i" = 0 ]; then
|
||||
echo >&2 'MySQL init process failed.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if [ -z "$MYSQL_INITDB_SKIP_TZINFO" ]; then
|
||||
# sed is for https://bugs.mysql.com/bug.php?id=20545
|
||||
mysql_tzinfo_to_sql /usr/share/zoneinfo | sed 's/Local time zone must be set--see zic manual page/FCTY/' | "${mysql[@]}" mysql
|
||||
fi
|
||||
|
||||
if [ ! -z "$MYSQL_RANDOM_ROOT_PASSWORD" ]; then
|
||||
export MYSQL_ROOT_PASSWORD="$(pwgen -1 32)"
|
||||
echo "GENERATED ROOT PASSWORD: $MYSQL_ROOT_PASSWORD"
|
||||
fi
|
||||
|
||||
rootCreate=
|
||||
# default root to listen for connections from anywhere
|
||||
file_env 'MYSQL_ROOT_HOST' '%'
|
||||
if [ ! -z "$MYSQL_ROOT_HOST" -a "$MYSQL_ROOT_HOST" != 'localhost' ]; then
|
||||
# no, we don't care if read finds a terminating character in this heredoc
|
||||
# https://unix.stackexchange.com/questions/265149/why-is-set-o-errexit-breaking-this-read-heredoc-expression/265151#265151
|
||||
read -r -d '' rootCreate <<-EOSQL || true
|
||||
CREATE USER 'root'@'${MYSQL_ROOT_HOST}' IDENTIFIED BY '${MYSQL_ROOT_PASSWORD}' ;
|
||||
GRANT ALL ON *.* TO 'root'@'${MYSQL_ROOT_HOST}' WITH GRANT OPTION ;
|
||||
EOSQL
|
||||
fi
|
||||
|
||||
"${mysql[@]}" <<-EOSQL
|
||||
-- What's done in this file shouldn't be replicated
|
||||
-- or products like mysql-fabric won't work
|
||||
SET @@SESSION.SQL_LOG_BIN=0;
|
||||
|
||||
DELETE FROM mysql.user WHERE user NOT IN ('mysql.sys', 'mysqlxsys', 'root') OR host NOT IN ('localhost') ;
|
||||
SET PASSWORD FOR 'root'@'localhost'=PASSWORD('${MYSQL_ROOT_PASSWORD}') ;
|
||||
GRANT ALL ON *.* TO 'root'@'localhost' WITH GRANT OPTION ;
|
||||
${rootCreate}
|
||||
DROP DATABASE IF EXISTS test ;
|
||||
FLUSH PRIVILEGES ;
|
||||
EOSQL
|
||||
|
||||
if [ ! -z "$MYSQL_ROOT_PASSWORD" ]; then
|
||||
mysql+=( -p"${MYSQL_ROOT_PASSWORD}" )
|
||||
fi
|
||||
|
||||
file_env 'MYSQL_DATABASE'
|
||||
if [ "$MYSQL_DATABASE" ]; then
|
||||
echo "CREATE DATABASE IF NOT EXISTS \`$MYSQL_DATABASE\` ;" | "${mysql[@]}"
|
||||
mysql+=( "$MYSQL_DATABASE" )
|
||||
fi
|
||||
|
||||
file_env 'MYSQL_USER'
|
||||
file_env 'MYSQL_PASSWORD'
|
||||
if [ "$MYSQL_USER" -a "$MYSQL_PASSWORD" ]; then
|
||||
echo "CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD' ;" | "${mysql[@]}"
|
||||
|
||||
if [ "$MYSQL_DATABASE" ]; then
|
||||
echo "GRANT ALL ON \`$MYSQL_DATABASE\`.* TO '$MYSQL_USER'@'%' ;" | "${mysql[@]}"
|
||||
fi
|
||||
fi
|
||||
|
||||
echo
|
||||
for f in /docker-entrypoint-initdb.d/*; do
|
||||
case "$f" in
|
||||
*.sh) echo "$0: running $f"; . "$f" ;;
|
||||
*.sql) echo "$0: running $f"; "${mysql[@]}" < "$f"; echo ;;
|
||||
*.sql.gz) echo "$0: running $f"; gunzip -c "$f" | "${mysql[@]}"; echo ;;
|
||||
*) echo "$0: ignoring $f" ;;
|
||||
esac
|
||||
echo
|
||||
done
|
||||
|
||||
if ! kill -s TERM "$pid" || ! wait "$pid"; then
|
||||
echo >&2 'MySQL init process failed.'
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo
|
||||
echo 'MySQL init process done. Ready for start up.'
|
||||
echo
|
||||
fi
|
||||
fi
|
||||
|
||||
exec "$@"
|
|
@ -14,7 +14,7 @@ disable_plaintext_auth = yes
|
|||
login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k"
|
||||
mail_home = /var/vmail/%d/%n
|
||||
mail_location = maildir:~/
|
||||
mail_plugins = quota acl zlib listescape #mail_crypt
|
||||
mail_plugins = quota acl zlib listescape mail_crypt mail_crypt_acl
|
||||
|
||||
# Dovecot 2.2
|
||||
#ssl_protocols = !SSLv3
|
||||
|
@ -175,7 +175,7 @@ namespace {
|
|||
type = shared
|
||||
separator = /
|
||||
prefix = Shared/%%u/
|
||||
location = maildir:%%h/:CONTROL=~/Shared/%%u:INDEXPVT=~/Shared/%%u
|
||||
location = maildir:%%h/:INDEX=~/Shared/%%u;CONTROL=~/Shared/%%u
|
||||
subscriptions = no
|
||||
list = children
|
||||
}
|
||||
|
@ -223,7 +223,7 @@ service pop3-login {
|
|||
}
|
||||
service imap {
|
||||
executable = imap imap-postlogin
|
||||
user = dovenull
|
||||
user = vmail
|
||||
vsz_limit = 256 M
|
||||
}
|
||||
service managesieve {
|
||||
|
@ -244,11 +244,11 @@ userdb {
|
|||
}
|
||||
protocol imap {
|
||||
imap_metadata = yes
|
||||
mail_plugins = quota imap_quota imap_acl acl zlib imap_zlib imap_sieve listescape #mail_crypt
|
||||
mail_plugins = quota imap_quota imap_acl acl zlib imap_zlib imap_sieve listescape mail_crypt mail_crypt_acl
|
||||
}
|
||||
mail_attribute_dict = file:%h/dovecot-attributes
|
||||
protocol lmtp {
|
||||
mail_plugins = quota sieve acl zlib listescape #mail_crypt
|
||||
mail_plugins = quota sieve acl zlib listescape mail_crypt mail_crypt_acl
|
||||
auth_socket_path = /usr/local/var/run/dovecot/auth-master
|
||||
}
|
||||
protocol sieve {
|
||||
|
@ -288,9 +288,12 @@ plugin {
|
|||
sieve_before = dict:proxy::sieve_before;name=active;bindir=/var/vmail/sieve_before_bindir
|
||||
sieve_after = dict:proxy::sieve_after;name=active;bindir=/var/vmail/sieve_after_bindir
|
||||
sieve_after2 = /var/vmail/sieve/global.sieve
|
||||
#mail_crypt_global_private_key = </mail_crypt/ecprivkey.pem
|
||||
#mail_crypt_global_public_key = </mail_crypt/ecpubkey.pem
|
||||
#mail_crypt_save_version = 2
|
||||
|
||||
# -- Global keys
|
||||
mail_crypt_global_private_key = </mail_crypt/ecprivkey.pem
|
||||
mail_crypt_global_public_key = </mail_crypt/ecpubkey.pem
|
||||
mail_crypt_save_version = 2
|
||||
|
||||
# Enable compression while saving, lz4 Dovecot v2.2.11+
|
||||
zlib_save = lz4
|
||||
}
|
||||
|
|
|
@ -50,6 +50,18 @@ server {
|
|||
absolute_redirect off;
|
||||
root /web;
|
||||
|
||||
location / {
|
||||
try_files $uri $uri/ @strip-ext;
|
||||
}
|
||||
|
||||
location /edit {
|
||||
rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
|
||||
}
|
||||
|
||||
location @strip-ext {
|
||||
rewrite ^(.*)$ $1.php last;
|
||||
}
|
||||
|
||||
location ~ ^/api/v1/(.*)$ {
|
||||
try_files $uri $uri/ /json_api.php?query=$1;
|
||||
}
|
||||
|
@ -120,12 +132,12 @@ server {
|
|||
|
||||
location ^~ /Microsoft-Server-ActiveSync {
|
||||
include /etc/nginx/conf.d/sogo_eas.active;
|
||||
proxy_connect_timeout 1000;
|
||||
proxy_connect_timeout 4000;
|
||||
proxy_next_upstream timeout error;
|
||||
proxy_send_timeout 1000;
|
||||
proxy_read_timeout 1000;
|
||||
proxy_send_timeout 4000;
|
||||
proxy_read_timeout 4000;
|
||||
proxy_buffer_size 8k;
|
||||
proxy_buffers 4 32k;
|
||||
proxy_buffers 16 64k;
|
||||
proxy_temp_file_write_size 64k;
|
||||
proxy_busy_buffers_size 64k;
|
||||
proxy_set_header X-Real-IP $remote_addr;
|
||||
|
@ -156,44 +168,19 @@ server {
|
|||
}
|
||||
|
||||
location /SOGo.woa/WebServerResources/ {
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
#alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
expires $expires;
|
||||
allow all;
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /.woa/WebServerResources/ {
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
#alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
expires $expires;
|
||||
allow all;
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location /SOGo/WebServerResources/ {
|
||||
proxy_pass http://sogo:9192/WebServerResources/;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
#alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
allow all;
|
||||
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
|
||||
}
|
||||
|
||||
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
|
||||
proxy_pass http://sogo:9192/$1.SOGo/Resources/$2;
|
||||
proxy_set_header Host $http_host;
|
||||
proxy_cache sogo;
|
||||
proxy_cache_valid 200 1d;
|
||||
proxy_cache_use_stale error timeout invalid_header updating http_500 http_502 http_503 http_504;
|
||||
#alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
||||
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
|
||||
}
|
||||
|
||||
include /etc/nginx/conf.d/site.*.custom;
|
||||
|
|
|
@ -26,7 +26,7 @@ listen = [::]:9002
|
|||
access.log = /proc/self/fd/2
|
||||
clear_env = no
|
||||
catch_workers_output = yes
|
||||
php_admin_value[memory_limit] = 256M
|
||||
php_admin_value[memory_limit] = 512M
|
||||
php_admin_value[max_execution_time] = 1200
|
||||
php_admin_value[max_input_time] = 1200
|
||||
|
||||
|
|
|
@ -20,7 +20,7 @@ broken_sasl_auth_clients = yes
|
|||
disable_vrfy_command = yes
|
||||
maximal_backoff_time = 1800s
|
||||
maximal_queue_lifetime = 1d
|
||||
message_size_limit = 26214400
|
||||
message_size_limit = 104857600
|
||||
milter_default_action = accept
|
||||
milter_protocol = 6
|
||||
minimal_backoff_time = 300s
|
||||
|
@ -41,6 +41,7 @@ postscreen_greet_wait = 3s
|
|||
postscreen_non_smtp_command_enable = no
|
||||
postscreen_pipelining_enable = no
|
||||
proxy_read_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_virtual_sender_acl.cf,
|
||||
proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf,
|
||||
proxy:mysql:/opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf,
|
||||
proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf,
|
||||
proxy:mysql:/opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf,
|
||||
|
@ -127,3 +128,4 @@ smtp_sasl_auth_enable = yes
|
|||
smtp_sasl_password_maps = proxy:mysql:/opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf
|
||||
smtp_sasl_security_options =
|
||||
smtp_sasl_mechanism_filter = plain, login
|
||||
smtp_tls_policy_maps=proxy:mysql:/opt/postfix/conf/sql/mysql_tls_policy_override_maps.cf
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
# High spam networks, disabled by default
|
||||
# ASN:SCORE DESC
|
||||
# Remove comment to enable score
|
||||
#201942:5 #Soltia Consulting SL - ipinfo.io
|
||||
#16276:5 #OVH
|
||||
#12876:5 #ONLINE S.A.S
|
||||
#31034:5
|
||||
#12874:5
|
||||
#30823:5
|
||||
#197071:5
|
||||
#16276:2 #OVH
|
||||
#12876:2 #ONLINE S.A.S
|
||||
#31034:5 #ARUBA-ASN, IT
|
||||
#12874:5 #FASTWEB, IT
|
||||
#30823:3 #PKV spam
|
||||
#42831:5 #UK Dedicated Servers Ltd
|
||||
#29119:5 #Aire Networks del Mediterraneo S.L.U.
|
||||
#13335:5 #Cloudflare
|
||||
|
@ -17,7 +18,7 @@
|
|||
#14061:4 #Digitalocean
|
||||
#55293:4 #A2 Hosting
|
||||
#63018:4 #US Dedicated
|
||||
#197518:2
|
||||
#197518:2 #RACKMARKT
|
||||
#44493:2
|
||||
#46606:2
|
||||
#49505:2
|
||||
|
@ -25,3 +26,5 @@
|
|||
#197695:2
|
||||
#198068:2
|
||||
#43146:2
|
||||
#49100:4
|
||||
#39364:4
|
||||
|
|
|
@ -9,7 +9,8 @@ require_once "vars.inc.php";
|
|||
|
||||
ini_set('error_reporting', 0);
|
||||
|
||||
$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
|
||||
//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
|
||||
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
|
|
|
@ -25,13 +25,6 @@ WHITELISTED_FWD_HOST {
|
|||
symbols_set = ["WHITELISTED_FWD_HOST"];
|
||||
}
|
||||
|
||||
KEEP_SPAM {
|
||||
type = "ip";
|
||||
map = "redis://KEEP_SPAM";
|
||||
action = "accept";
|
||||
symbols_set = ["KEEP_SPAM"];
|
||||
}
|
||||
|
||||
LOCAL_BL_ASN {
|
||||
require_symbols = "!MAILCOW_WHITE";
|
||||
type = "asn";
|
||||
|
@ -40,11 +33,3 @@ LOCAL_BL_ASN {
|
|||
description = "Sender's ASN is on the local blacklist";
|
||||
symbols_set = ["LOCAL_BL_ASN"];
|
||||
}
|
||||
|
||||
#SPOOFED_SENDER {
|
||||
# type = "rcpt";
|
||||
# filter = "email:domain:tld";
|
||||
# map = "redis://DOMAIN_MAP";
|
||||
# require_symbols = "AUTH_NA | !RCVD_VIA_SMTP_AUTH";
|
||||
# symbols_set = ["SPOOFED_SENDER"];
|
||||
#}
|
||||
|
|
|
@ -7,6 +7,68 @@ rspamd_config.MAILCOW_AUTH = {
|
|||
end
|
||||
}
|
||||
|
||||
rspamd_config:register_symbol({
|
||||
name = 'KEEP_SPAM',
|
||||
type = 'prefilter',
|
||||
callback = function(task)
|
||||
local util = require("rspamd_util")
|
||||
local rspamd_logger = require "rspamd_logger"
|
||||
local rspamd_ip = require 'rspamd_ip'
|
||||
local uname = task:get_user()
|
||||
|
||||
if uname then
|
||||
return false
|
||||
end
|
||||
|
||||
local redis_params = rspamd_parse_redis_server('keep_spam')
|
||||
local ip = task:get_from_ip()
|
||||
|
||||
if not ip:is_valid() then
|
||||
return false
|
||||
end
|
||||
|
||||
local from_ip_string = tostring(ip)
|
||||
ip_check_table = {from_ip_string}
|
||||
|
||||
local maxbits = 128
|
||||
local minbits = 32
|
||||
if ip:get_version() == 4 then
|
||||
maxbits = 32
|
||||
minbits = 8
|
||||
end
|
||||
for i=maxbits,minbits,-1 do
|
||||
local nip = ip:apply_mask(i):to_string() .. "/" .. i
|
||||
table.insert(ip_check_table, nip)
|
||||
end
|
||||
local function keep_spam_cb(err, data)
|
||||
if err then
|
||||
rspamd_logger.infox(rspamd_config, "keep_spam query request for ip %s returned invalid or empty data (\"%s\") or error (\"%s\")", ip, data, err)
|
||||
return false
|
||||
else
|
||||
for k,v in pairs(data) do
|
||||
if (v and v ~= userdata and v == '1') then
|
||||
rspamd_logger.infox(rspamd_config, "found ip in keep_spam map, setting pre-result", v)
|
||||
task:set_pre_result('accept', 'IP matched with forward hosts')
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
table.insert(ip_check_table, 1, 'KEEP_SPAM')
|
||||
local redis_ret_user = rspamd_redis_make_request(task,
|
||||
redis_params, -- connect params
|
||||
'KEEP_SPAM', -- hash key
|
||||
false, -- is write
|
||||
keep_spam_cb, --callback
|
||||
'HMGET', -- command
|
||||
ip_check_table -- arguments
|
||||
)
|
||||
if not redis_ret_user then
|
||||
rspamd_logger.infox(rspamd_config, "cannot check keep_spam redis map")
|
||||
end
|
||||
end,
|
||||
priority = 19
|
||||
})
|
||||
|
||||
rspamd_config:register_symbol({
|
||||
name = 'TAG_MOO',
|
||||
type = 'postfilter',
|
||||
|
|
|
@ -6,7 +6,8 @@ require_once "vars.inc.php";
|
|||
// Do not show errors, we log to using error_log
|
||||
ini_set('error_reporting', 0);
|
||||
// Init database
|
||||
$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
|
||||
//$dsn = $database_type . ':host=' . $database_host . ';dbname=' . $database_name;
|
||||
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
bind_socket = "*:11334";
|
||||
count = 2;
|
||||
count = 1;
|
||||
secure_ip = "127.0.0.1";
|
||||
secure_ip = "::1";
|
||||
bind_socket = "/rspamd-sock/rspamd.sock mode=0666 owner=nobody";
|
||||
bind_socket = "/var/lib/rspamd/rspamd.sock mode=0666 owner=nobody";
|
||||
.include(try=true; priority=10) "$CONFDIR/override.d/worker-controller-password.inc"
|
||||
.include(try=true; priority=20) "$CONFDIR/override.d/worker-controller.custom.inc"
|
||||
|
|
|
@ -39,17 +39,17 @@
|
|||
|
||||
SxVMemLimit = 384;
|
||||
|
||||
SOGoMaximumPingInterval = 354;
|
||||
SOGoMaximumPingInterval = 3540;
|
||||
|
||||
SOGoInternalSyncInterval = 30;
|
||||
SOGoMaximumSyncInterval = 354;
|
||||
SOGoInternalSyncInterval = 45;
|
||||
SOGoMaximumSyncInterval = 3540;
|
||||
|
||||
// 100 seems to break some Android clients
|
||||
//SOGoMaximumSyncWindowSize = 100;
|
||||
//SOGoMaximumSyncWindowSize = 99;
|
||||
// This should do the trick for Outlook 2016
|
||||
SOGoMaximumSyncResponseSize = 2048;
|
||||
SOGoMaximumSyncResponseSize = 512;
|
||||
|
||||
WOWatchDogRequestTimeout = 10;
|
||||
WOWatchDogRequestTimeout = 20;
|
||||
WOListenQueueSize = 300;
|
||||
WONoDetach = YES;
|
||||
|
||||
|
|
|
@ -2,7 +2,7 @@ server:
|
|||
verbosity: 1
|
||||
interface: 0.0.0.0
|
||||
interface: ::0
|
||||
logfile: /dev/stdout
|
||||
logfile: /dev/console
|
||||
do-ip4: yes
|
||||
do-ip6: yes
|
||||
do-udp: yes
|
||||
|
@ -27,3 +27,12 @@ server:
|
|||
hide-version: yes
|
||||
max-udp-size: 4096
|
||||
msg-buffer-size: 65552
|
||||
|
||||
remote-control:
|
||||
control-enable: yes
|
||||
control-interface: 127.0.0.1
|
||||
control-port: 8953
|
||||
server-key-file: "/etc/unbound/unbound_server.key"
|
||||
server-cert-file: "/etc/unbound/unbound_server.pem"
|
||||
control-key-file: "/etc/unbound/unbound_control.key"
|
||||
control-cert-file: "/etc/unbound/unbound_control.pem"
|
||||
|
|
|
@ -22,29 +22,29 @@ $tfa_data = get_tfa();
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="text" class="form-control" name="admin_user" id="admin_user" value="<?=htmlspecialchars($admindetails['username']);?>" required>
|
||||
<input type="text" class="form-control" name="admin_user" value="<?=htmlspecialchars($admindetails['username']);?>" required>
|
||||
↳ <kbd>a-z A-Z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="admin_pass"><?=$lang['admin']['password'];?>:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" name="admin_pass" id="admin_pass" placeholder="<?=$lang['admin']['unchanged_if_empty'];?>">
|
||||
<input type="password" data-hibp="true" class="form-control" name="admin_pass" placeholder="<?=$lang['admin']['unchanged_if_empty'];?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="admin_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" name="admin_pass2" id="admin_pass2">
|
||||
<input type="password" class="form-control" name="admin_pass2">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<button class="btn btn-default" id="edit_selected" data-id="admin" data-item="admin" data-api-url='edit/self' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="admin" data-item="admin" data-api-url='edit/self' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
<legend><?=$lang['tfa']['tfa'];?></legend>
|
||||
<div class="row">
|
||||
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['tfa']['tfa'];?>:</div>
|
||||
<div class="col-sm-9 col-xs-7">
|
||||
|
@ -76,12 +76,10 @@ $tfa_data = get_tfa();
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="hidden panel panel-primary">
|
||||
<div class="panel-heading">API</div>
|
||||
<div class="panel-body">
|
||||
<legend data-target="#api" style="margin-top:40px;cursor:pointer" id="api_legend" unselectable="on" data-toggle="collapse">
|
||||
<span id="api_arrow" style="font-size:12px" class="rotate glyphicon glyphicon-menu-down"></span> API (experimental, work in progress)
|
||||
</legend>
|
||||
<div id="api" class="collapse">
|
||||
<form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="allow_from"><?=$lang['admin']['api_allow_from'];?>:</label>
|
||||
|
@ -113,6 +111,7 @@ $tfa_data = get_tfa();
|
|||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading"><?=$lang['admin']['domain_admins'];?></div>
|
||||
|
@ -125,12 +124,12 @@ $tfa_data = get_tfa();
|
|||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="domain_admins" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#"><?=$lang['tfa']['disable_tfa'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain_admins" data-api-url='edit/domain-admin' data-api-attr='{"disable_tfa":"1"}' href="#"><?=$lang['tfa']['disable_tfa'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="domain_admins" data-api-url='delete/domain-admin' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" data-id="add_domain_admin" data-toggle="modal" data-target="#addDomainAdminModal" href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add_domain_admin'];?></a>
|
||||
</div>
|
||||
|
@ -156,13 +155,13 @@ $tfa_data = get_tfa();
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="rspamd_ui_pass"><?=$lang['admin']['password'];?>:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" name="rspamd_ui_pass" id="rspamd_ui_pass" required>
|
||||
<input type="password" class="form-control" name="rspamd_ui_pass" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="rspamd_ui_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
|
||||
<div class="col-sm-9">
|
||||
<input type="password" class="form-control" name="rspamd_ui_pass2" id="rspamd_ui_pass2" required>
|
||||
<input type="password" class="form-control" name="rspamd_ui_pass2" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -202,7 +201,7 @@ $tfa_data = get_tfa();
|
|||
<div class="mass-actions-admin">
|
||||
<div class="btn-group btn-group-sm">
|
||||
<button type="button" id="toggle_multi_select_all" data-id="dkim" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
|
||||
<button type="button" id="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
|
||||
<button type="button" data-action="delete_selected" name="delete_selected" data-id="dkim" data-api-url="delete/dkim" class="btn btn-danger"><?=$lang['admin']['remove'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
@ -310,7 +309,7 @@ $tfa_data = get_tfa();
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<label for="domain">Selector</label>
|
||||
<input class="form-control input-sm" id="dkim_selector" name="dkim_selector" value="dkim" required>
|
||||
<input class="form-control input-sm" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select data-width="200px" data-style="btn btn-default btn-sm" class="form-control" id="key_size" name="key_size" title="<?=$lang['admin']['dkim_key_length'];?>" required>
|
||||
|
@ -318,7 +317,7 @@ $tfa_data = get_tfa();
|
|||
<option data-subtext="bits">2048</option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-default" id="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-sm btn-default" data-action="add_item" data-id="dkim" data-api-url='add/dkim' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
</form>
|
||||
|
||||
<legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" id="import_dkim_legend" unselectable="on" data-toggle="collapse">
|
||||
|
@ -328,17 +327,17 @@ $tfa_data = get_tfa();
|
|||
<form class="form" data-id="dkim_import" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="domain">Domain:</label>
|
||||
<input class="form-control input-sm" id="domain" name="domain" placeholder="example.org" required>
|
||||
<input class="form-control input-sm" name="domain" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="domain">Selector:</label>
|
||||
<input class="form-control input-sm" id="dkim_selector" name="dkim_selector" value="dkim" required>
|
||||
<input class="form-control input-sm" name="dkim_selector" value="dkim" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="private_key_file"><?=$lang['admin']['private_key'];?>:</label>
|
||||
<textarea class="form-control input-sm" rows="10" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA KEY-----"></textarea>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-default" id="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['import'];?></button>
|
||||
<button class="btn btn-sm btn-default" data-action="add_item" data-id="dkim_import" data-api-url='add/dkim_import' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['import'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -384,7 +383,7 @@ $tfa_data = get_tfa();
|
|||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<button class="btn btn-sm btn-default" id="add_item" data-id="dkim_duplicate" data-api-url='add/dkim_duplicate' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-duplicate"></span> <?=$lang['admin']['duplicate'];?></button>
|
||||
<button class="btn btn-sm btn-default" data-action="add_item" data-id="dkim_duplicate" data-api-url='add/dkim_duplicate' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-duplicate"></span> <?=$lang['admin']['duplicate'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
|
||||
|
@ -404,10 +403,10 @@ $tfa_data = get_tfa();
|
|||
<button type="button" id="toggle_multi_select_all" data-id="fwdhosts" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
|
||||
<li><a id="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
|
||||
<li><a data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"0"}' href="#">Enable spam filter</a></li>
|
||||
<li><a data-action="edit_selected" data-id="fwdhosts" data-api-url='edit/fwdhost' data-api-attr='{"keep_spam":"1"}' href="#">Disable spam filter</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#"><?=$lang['admin']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="fwdhosts" data-api-url='delete/fwdhost' href="#"><?=$lang['admin']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -416,7 +415,7 @@ $tfa_data = get_tfa();
|
|||
<form class="form" data-id="fwdhost" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="hostname"><?=$lang['admin']['host'];?></label>
|
||||
<input class="form-control" id="hostname" name="hostname" placeholder="example.org" required>
|
||||
<input class="form-control" name="hostname" placeholder="example.org" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="<?=$lang['user']['spamfilter'];?>" required>
|
||||
|
@ -424,7 +423,7 @@ $tfa_data = get_tfa();
|
|||
<option value="0"><?=$lang['admin']['inactive'];?></option>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-default" id="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="fwdhost" data-api-url='add/fwdhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -439,41 +438,41 @@ $tfa_data = get_tfa();
|
|||
<form class="form" data-id="f2b" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="ban_time"><?=$lang['admin']['f2b_ban_time'];?>:</label>
|
||||
<input type="number" class="form-control" id="ban_time" name="ban_time" value="<?=$f2b_data['ban_time'];?>" required>
|
||||
<input type="number" class="form-control" name="ban_time" value="<?=$f2b_data['ban_time'];?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="max_attempts"><?=$lang['admin']['f2b_max_attempts'];?>:</label>
|
||||
<input type="number" class="form-control" id="max_attempts" name="max_attempts" value="<?=$f2b_data['max_attempts'];?>" required>
|
||||
<input type="number" class="form-control" name="max_attempts" value="<?=$f2b_data['max_attempts'];?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="retry_window"><?=$lang['admin']['f2b_retry_window'];?>:</label>
|
||||
<input type="number" class="form-control" id="retry_window" name="retry_window" value="<?=$f2b_data['retry_window'];?>" required>
|
||||
<input type="number" class="form-control" name="retry_window" value="<?=$f2b_data['retry_window'];?>" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="netban_ipv4"><?=$lang['admin']['f2b_netban_ipv4'];?>:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<input type="number" class="form-control" id="netban_ipv4" name="netban_ipv4" value="<?=$f2b_data['netban_ipv4'];?>" required>
|
||||
<input type="number" class="form-control" name="netban_ipv4" value="<?=$f2b_data['netban_ipv4'];?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="netban_ipv6"><?=$lang['admin']['f2b_netban_ipv6'];?>:</label>
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon">/</span>
|
||||
<input type="number" class="form-control" id="netban_ipv6" name="netban_ipv6" value="<?=$f2b_data['netban_ipv6'];?>" required>
|
||||
<input type="number" class="form-control" name="netban_ipv6" value="<?=$f2b_data['netban_ipv6'];?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<p class="help-block"><?=$lang['admin']['f2b_list_info'];?></p>
|
||||
<div class="form-group">
|
||||
<label for="whitelist"><?=$lang['admin']['f2b_whitelist'];?>:</label>
|
||||
<textarea class="form-control" id="whitelist" name="whitelist" rows="5"><?=$f2b_data['whitelist'];?></textarea>
|
||||
<textarea class="form-control" name="whitelist" rows="5"><?=$f2b_data['whitelist'];?></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="blacklist"><?=$lang['admin']['f2b_blacklist'];?>:</label>
|
||||
<textarea class="form-control" id="blacklist" name="blacklist" rows="5"><?=$f2b_data['blacklist'];?></textarea>
|
||||
<textarea class="form-control" name="blacklist" rows="5"><?=$f2b_data['blacklist'];?></textarea>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<button class="btn btn-default" id="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<a href="#" role="button" class="btn btn-default" data-toggle="modal" data-container="netfilter-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_netfilter']; ?></a>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -491,9 +490,9 @@ $tfa_data = get_tfa();
|
|||
<?php
|
||||
if ($active_bans['queued_for_unban'] == 0):
|
||||
?>
|
||||
<a id="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"unban"}' href="#">[<?=$lang['admin']['queue_unban'];?>]</a>
|
||||
<a id="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"whitelist"}' href="#">[whitelist]</a>
|
||||
<a id="edit_selected" data-item="<?=$active_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist]</a>
|
||||
<a data-action="edit_selected" data-item="<?=$active_bans['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_bans['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_bans['network'];?>" data-id="f2b-quick" data-api-url='edit/fail2ban' data-api-attr='{"action":"blacklist"}' href="#">[blacklist]</a>
|
||||
<?php
|
||||
else:
|
||||
?>
|
||||
|
@ -528,10 +527,10 @@ $tfa_data = get_tfa();
|
|||
<button type="button" id="toggle_multi_select_all" data-id="rlyhosts" class="btn btn-default"><?=$lang['mailbox']['toggle_all'];?></button>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="rlyhosts" data-api-url='edit/relayhost' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="rlyhosts" data-api-url='delete/relayhost' href="#"><?=$lang['admin']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="rlyhosts" data-api-url='delete/relayhost' href="#"><?=$lang['admin']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -540,17 +539,17 @@ $tfa_data = get_tfa();
|
|||
<form class="form" data-id="rlyhost" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="hostname"><?=$lang['admin']['host'];?></label>
|
||||
<input class="form-control" id="hostname" name="hostname" required>
|
||||
<input class="form-control" name="hostname" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hostname"><?=$lang['admin']['username'];?></label>
|
||||
<input class="form-control" id="username" name="username">
|
||||
<input class="form-control" name="username">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="hostname"><?=$lang['admin']['password'];?></label>
|
||||
<input class="form-control" id="password" name="password">
|
||||
<input class="form-control" name="password">
|
||||
</div>
|
||||
<button class="btn btn-default" id="add_item" data-id="rlyhost" data-api-url='add/relayhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="rlyhost" data-api-url='add/relayhost' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -565,19 +564,19 @@ $tfa_data = get_tfa();
|
|||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="retention_size"><?=$lang['admin']['quarantine_retention_size'];?></label>
|
||||
<input type="number" class="form-control" id="retention_size" name="retention_size" value="<?=$q_data['retention_size'];?>" placeholder="0" required>
|
||||
<input type="number" class="form-control" name="retention_size" value="<?=$q_data['retention_size'];?>" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<div class="form-group">
|
||||
<label for="max_size"><?=$lang['admin']['quarantine_max_size'];?></label>
|
||||
<input type="number" class="form-control" id="max_size" name="max_size" value="<?=$q_data['max_size'];?>" placeholder="0" required>
|
||||
<input type="number" class="form-control" name="max_size" value="<?=$q_data['max_size'];?>" placeholder="0" required>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="exclude_domains"><?=$lang['admin']['quarantine_exclude_domains'];?></label><br />
|
||||
<select data-width="100%" id="exclude_domains" name="exclude_domains" class="selectpicker" title="<?=$lang['tfa']['select'];?>" multiple>
|
||||
<select data-width="100%" name="exclude_domains" class="selectpicker" title="<?=$lang['tfa']['select'];?>" multiple>
|
||||
<?php
|
||||
foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain):
|
||||
?>
|
||||
|
@ -587,7 +586,7 @@ $tfa_data = get_tfa();
|
|||
?>
|
||||
</select>
|
||||
</div>
|
||||
<button class="btn btn-default" id="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -649,19 +648,19 @@ $tfa_data = get_tfa();
|
|||
<input type="hidden" name="active" value="0">
|
||||
<div class="form-group">
|
||||
<label for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label>
|
||||
<input type="text" class="form-control" id="desc" name="desc" value="<?=$rsetting_details['desc'];?>">
|
||||
<input type="text" class="form-control" name="desc" value="<?=$rsetting_details['desc'];?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
|
||||
<textarea class="form-control" id="content" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
|
||||
<textarea class="form-control" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label>
|
||||
<input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?>
|
||||
</label>
|
||||
</div>
|
||||
<button class="btn btn-default" id="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-danger" id="delete_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#"><?=$lang['admin']['remove'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-danger" data-action="delete_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#"><?=$lang['admin']['remove'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
<?php
|
||||
|
@ -744,7 +743,7 @@ $tfa_data = get_tfa();
|
|||
?>
|
||||
</table>
|
||||
<p><div class="btn-group">
|
||||
<button class="btn btn-sm btn-default" id="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-sm btn-default" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
|
||||
</div></p>
|
||||
</form>
|
||||
|
@ -755,21 +754,21 @@ $tfa_data = get_tfa();
|
|||
<form class="form" data-id="uitexts" role="form" method="post">
|
||||
<div class="form-group">
|
||||
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label>
|
||||
<input type="text" class="form-control" id="title_name" name="title_name" placeholder="mailcow UI" value="<?=$ui_texts['title_name'];?>">
|
||||
<input type="text" class="form-control" name="title_name" placeholder="mailcow UI" value="<?=$ui_texts['title_name'];?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="main_name"><?=$lang['admin']['main_name'];?>:</label>
|
||||
<input type="text" class="form-control" id="main_name" name="main_name" placeholder="mailcow UI" value="<?=$ui_texts['main_name'];?>">
|
||||
<input type="text" class="form-control" name="main_name" placeholder="mailcow UI" value="<?=$ui_texts['main_name'];?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="apps_name"><?=$lang['admin']['apps_name'];?>:</label>
|
||||
<input type="text" class="form-control" id="apps_name" name="apps_name" placeholder="mailcow Apps" value="<?=$ui_texts['apps_name'];?>">
|
||||
<input type="text" class="form-control" name="apps_name" placeholder="mailcow Apps" value="<?=$ui_texts['apps_name'];?>">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label>
|
||||
<textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
|
||||
</div>
|
||||
<button class="btn btn-default" id="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -791,8 +790,8 @@ echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
|
|||
echo "var log_pagination_size = '". $LOG_PAGINATION_SIZE . "';\n";
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/admin.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/admin.js"></script>
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
} else {
|
||||
|
|
|
@ -27,7 +27,8 @@ if (strpos($data, 'autodiscover/outlook/responseschema') !== false) {
|
|||
}
|
||||
}
|
||||
|
||||
$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name;
|
||||
//$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name;
|
||||
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
|
|
|
@ -65,12 +65,6 @@ body.modal-open {
|
|||
font-size:9pt;
|
||||
background:transparent;
|
||||
}
|
||||
.bootstrap-select {
|
||||
width: auto!important;
|
||||
}
|
||||
.table-condensed .input-sm {
|
||||
width: 100%!important;
|
||||
}
|
||||
.full-width-select {
|
||||
width: 100%!important;
|
||||
}
|
||||
|
|
|
@ -5,9 +5,6 @@ table.footable>tbody>tr.footable-empty>td {
|
|||
.pagination a {
|
||||
text-decoration: none !important;
|
||||
}
|
||||
.panel panel-default {
|
||||
overflow: visible !important;
|
||||
}
|
||||
.btn-group {
|
||||
width: max-content;
|
||||
}
|
||||
|
|
|
@ -148,3 +148,13 @@ nav .glyphicon {
|
|||
color: #5a5a5a;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.haveibeenpwned {
|
||||
cursor: pointer;
|
||||
-webkit-user-select: none;
|
||||
-moz-user-select: none;
|
||||
-ms-user-select: none;
|
||||
user-select: none;
|
||||
}
|
||||
.full-width-select {
|
||||
width: 100%!important;
|
||||
}
|
|
@ -288,8 +288,8 @@ echo "var log_pagination_size = '". $LOG_PAGINATION_SIZE . "';\n";
|
|||
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/debug.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/debug.js"></script>
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
}
|
||||
|
|
|
@ -39,13 +39,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="col-sm-10">
|
||||
<textarea id="textarea_alias_goto" class="form-control" autocapitalize="none" autocorrect="off" rows="10" id="goto" name="goto" required><?= (!preg_match('/^(null|ham|spam)@localhost$/i', $result['goto'])) ? htmlspecialchars($result['goto']) : null; ?></textarea>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox"id="goto_null" type="checkbox" value="1" name="goto_null" <?= ($result['goto'] == "null@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_null'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_null" <?= ($result['goto'] == "null@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_null'];?></label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox" id="goto_spam" type="checkbox" value="1" name="goto_spam" <?= ($result['goto'] == "spam@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_spam'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_spam" <?= ($result['goto'] == "spam@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_spam'];?></label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox" id="goto_ham" type="checkbox" value="1" name="goto_ham" <?= ($result['goto'] == "ham@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_ham'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_ham" <?= ($result['goto'] == "ham@localhost") ? "checked" : null; ?>> <?=$lang['add']['goto_ham'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -58,7 +58,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editalias" data-item="<?=htmlspecialchars($alias);?>" data-api-url='edit/alias' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editalias" data-item="<?=htmlspecialchars($alias);?>" data-api-url='edit/alias' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -92,7 +92,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domains"><?=$lang['edit']['domains'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="domains" name="domains" multiple required>
|
||||
<select data-live-search="true" class="full-width-select" name="domains" multiple required>
|
||||
<?php
|
||||
foreach ($result['selected_domains'] as $domain):
|
||||
?>
|
||||
|
@ -111,13 +111,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="">
|
||||
<input type="password" data-hibp="true" class="form-control" name="password" placeholder="">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password2" id="password2">
|
||||
<input type="password" class="form-control" name="password2">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -136,7 +136,31 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editdomainadmin" data-item="<?=$domain_admin;?>" data-api-url='edit/domain-admin' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editdomainadmin" data-item="<?=$domain_admin;?>" data-api-url='edit/domain-admin' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form data-id="daacl" class="form-inline well" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="help-block">ACL</p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-group">
|
||||
<select id="da_acl" name="da_acl" size="10" multiple>
|
||||
<?php
|
||||
$da_acls = acl('get', 'domainadmin', $domain_admin);
|
||||
foreach ($da_acls as $acl => $val):
|
||||
?>
|
||||
<option value="<?=$acl;?>" <?=($val == 1) ? 'selected' : null;?>><?=$lang['acl'][$acl];?></option>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="daacl" data-item="<?=htmlspecialchars($domain_admin);?>" data-api-url='edit/da-acl' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -165,7 +189,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="description"><?=$lang['edit']['description'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="description" value="<?=htmlspecialchars($result['description']);?>">
|
||||
<input type="text" class="form-control" name="description" value="<?=htmlspecialchars($result['description']);?>">
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
|
@ -174,31 +198,31 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="aliases"><?=$lang['edit']['max_aliases'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="aliases" id="aliases" value="<?=intval($result['max_num_aliases_for_domain']);?>">
|
||||
<input type="number" class="form-control" name="aliases" value="<?=intval($result['max_num_aliases_for_domain']);?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['edit']['max_mailboxes'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mailboxes" id="mailboxes" value="<?=intval($result['max_num_mboxes_for_domain']);?>">
|
||||
<input type="number" class="form-control" name="mailboxes" value="<?=intval($result['max_num_mboxes_for_domain']);?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxquota"><?=$lang['edit']['max_quota'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxquota" id="maxquota" value="<?=intval($result['max_quota_for_mbox'] / 1048576);?>">
|
||||
<input type="number" class="form-control" name="maxquota" value="<?=intval($result['max_quota_for_mbox'] / 1048576);?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="quota"><?=$lang['edit']['domain_quota'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="quota" id="quota" value="<?=intval($result['max_quota_for_domain'] / 1048576);?>">
|
||||
<input type="number" class="form-control" name="quota" value="<?=intval($result['max_quota_for_domain'] / 1048576);?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="quota">Relayhost</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" name="relayhost" id="relayhost" class="form-control">
|
||||
<select data-live-search="true" name="relayhost" class="form-control">
|
||||
<?php
|
||||
foreach ($rlyhosts as $rlyhost) {
|
||||
?>
|
||||
|
@ -233,7 +257,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editdomain" data-item="<?=$domain;?>" data-api-url='edit/domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editdomain" data-item="<?=$domain;?>" data-api-url='edit/domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -256,17 +280,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<form data-id="domratelimit" class="form-inline well" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Ratelimit</label>
|
||||
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
<input name="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" autocomplete="off" class="form-control" placeholder="disabled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="rl_frame" id="rl_frame" class="form-control">
|
||||
<select name="rl_frame" class="form-control">
|
||||
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
|
||||
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
|
||||
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" id="edit_selected" data-id="domratelimit" data-item="<?=$domain;?>" data-api-url='edit/rl-domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
<button data-acl="<?=$_SESSION['acl']['ratelimit'];?>" class="btn btn-default" data-action="edit_selected" data-id="domratelimit" data-item="<?=$domain;?>" data-api-url='edit/rl-domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</form>
|
||||
<hr>
|
||||
|
@ -278,17 +302,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<table class="table table-striped table-condensed" id="wl_policy_domain_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_wl_domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_wl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<a class="btn btn-sm btn-danger" data-action="delete_selected" data-id="policy_wl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" data-id="add_wl_policy_domain">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
|
||||
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_wl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"wl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_wl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"wl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -300,17 +324,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<table class="table table-striped table-condensed" id="bl_policy_domain_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_bl_domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_bl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<a class="btn btn-sm btn-danger" data-action="delete_selected" data-id="policy_bl_domain" data-api-url='delete/domain-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" data-id="add_bl_policy_domain">
|
||||
<div class="input-group">
|
||||
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
|
||||
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<input type="text" class="form-control" name="object_from" placeholder="*@example.org" required>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_bl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"bl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_bl_policy_domain" data-api-url='add/domain-policy' data-api-attr='{"domain":"<?= $domain; ?>","object_list":"bl"}' href="#"><?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -338,7 +362,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="target_domain"><?=$lang['edit']['target_domain'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="target_domain" id="target_domain" value="<?=htmlspecialchars($result['target_domain']);?>">
|
||||
<input type="text" class="form-control" name="target_domain" value="<?=htmlspecialchars($result['target_domain']);?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -350,7 +374,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editaliasdomain" data-item="<?=$alias_domain;?>" data-api-url='edit/alias-domain' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editaliasdomain" data-item="<?=$alias_domain;?>" data-api-url='edit/alias-domain' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -358,17 +382,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<form data-id="domratelimit" class="form-inline well" method="post">
|
||||
<div class="form-group">
|
||||
<label class="control-label">Ratelimit</label>
|
||||
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
<input name="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" autocomplete="off" class="form-control" placeholder="disabled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="rl_frame" id="rl_frame" class="form-control">
|
||||
<select name="rl_frame" class="form-control">
|
||||
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
|
||||
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
|
||||
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" id="edit_selected" data-id="domratelimit" data-item="<?=$alias_domain;?>" data-api-url='edit/rl-domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="domratelimit" data-item="<?=$alias_domain;?>" data-api-url='edit/rl-domain' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
|
@ -406,7 +430,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="name"><?=$lang['edit']['full_name'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" id="name" value="<?=htmlspecialchars($result['name'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<input type="text" class="form-control" name="name" value="<?=htmlspecialchars($result['name'], ENT_QUOTES, 'UTF-8');?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -414,13 +438,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<br /><span id="quotaBadge" class="badge">max. <?=intval($result['max_new_quota'] / 1048576)?> MiB</span>
|
||||
</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" name="quota" id="quota" id="destroyable" style="width:100%" min="1" max="<?=intval($result['max_new_quota'] / 1048576);?>" value="<?=intval($result['quota']) / 1048576;?>" class="form-control">
|
||||
<input type="number" name="quota" style="width:100%" min="1" max="<?=intval($result['max_new_quota'] / 1048576);?>" value="<?=intval($result['quota']) / 1048576;?>" class="form-control">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="sender_acl"><?=$lang['edit']['sender_acl'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" data-width="100%" style="width:100%" id="sender_acl" name="sender_acl" size="10" multiple>
|
||||
<select data-live-search="true" data-width="100%" style="width:100%" id="editSelectSenderACL" name="sender_acl" size="10" multiple>
|
||||
<?php
|
||||
$sender_acl_handles = mailbox('get', 'sender_acl_handles', $mailbox);
|
||||
|
||||
|
@ -474,13 +498,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="<?=$lang['edit']['unchanged_if_empty'];?>">
|
||||
<input type="password" data-hibp="true" class="form-control" name="password" placeholder="<?=$lang['edit']['unchanged_if_empty'];?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password2" id="password2">
|
||||
<input type="password" class="form-control" name="password2">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -500,7 +524,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editmailbox" data-item="<?=htmlspecialchars($result['username']);?>" data-api-url='edit/mailbox' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editmailbox" data-item="<?=htmlspecialchars($result['username']);?>" data-api-url='edit/mailbox' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -512,17 +536,41 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-group">
|
||||
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
<input name="rl_value" type="number" autocomplete="off" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<select name="rl_frame" id="rl_frame" class="form-control">
|
||||
<select name="rl_frame" class="form-control">
|
||||
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
|
||||
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
|
||||
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" id="edit_selected" data-id="mboxratelimit" data-item="<?=htmlspecialchars($mailbox);?>" data-api-url='edit/rl-mbox' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="mboxratelimit" data-item="<?=htmlspecialchars($mailbox);?>" data-api-url='edit/rl-mbox' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<form data-id="useracl" class="form-inline well" method="post">
|
||||
<div class="row">
|
||||
<div class="col-sm-1">
|
||||
<p class="help-block">ACL</p>
|
||||
</div>
|
||||
<div class="col-sm-10">
|
||||
<div class="form-group">
|
||||
<select id="user_acl" name="user_acl" size="10" multiple>
|
||||
<?php
|
||||
$user_acls = acl('get', 'user', $mailbox);
|
||||
foreach ($user_acls as $acl => $val):
|
||||
?>
|
||||
<option value="<?=$acl;?>" <?=($val == 1) ? 'selected' : null;?>><?=$lang['acl'][$acl];?></option>
|
||||
<?php
|
||||
endforeach;
|
||||
?>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="useracl" data-item="<?=htmlspecialchars($mailbox);?>" data-api-url='edit/user-acl' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -541,19 +589,19 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="hostname"><?=$lang['add']['hostname'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="hostname" id="hostname" value="<?=htmlspecialchars($result['hostname'], ENT_QUOTES, 'UTF-8');?>" required>
|
||||
<input type="text" class="form-control" name="hostname" value="<?=htmlspecialchars($result['hostname'], ENT_QUOTES, 'UTF-8');?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" id="username" value="<?=htmlspecialchars($result['username'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<input type="text" class="form-control" name="username" value="<?=htmlspecialchars($result['username'], ENT_QUOTES, 'UTF-8');?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password" id="password" value="<?=htmlspecialchars($result['password'], ENT_QUOTES, 'UTF-8');?>">
|
||||
<input type="password" data-hibp="true" class="form-control" name="password" value="<?=htmlspecialchars($result['password'], ENT_QUOTES, 'UTF-8');?>">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -565,7 +613,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editrelayhost" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/relayhost' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editrelayhost" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/relayhost' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -588,13 +636,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="description" value="<?=htmlspecialchars($result['description'], ENT_QUOTES, 'UTF-8');?>" required>
|
||||
<input type="text" class="form-control" name="description" value="<?=htmlspecialchars($result['description'], ENT_QUOTES, 'UTF-8');?>" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domain"><?=$lang['edit']['kind'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="kind" id="kind" title="<?=$lang['edit']['select'];?>" required>
|
||||
<select name="kind" title="<?=$lang['edit']['select'];?>" required>
|
||||
<option value="location" <?=($result['kind'] == "location") ? "selected" : null;?>>Location</option>
|
||||
<option value="group" <?=($result['kind'] == "group") ? "selected" : null;?>>Group</option>
|
||||
<option value="thing" <?=($result['kind'] == "thing") ? "selected" : null;?>>Thing</option>
|
||||
|
@ -604,7 +652,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="multiple_bookings_select"><?=$lang['add']['multiple_bookings'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="multiple_bookings_select" id="multiple_bookings_select" title="<?=$lang['add']['select'];?>" required>
|
||||
<select name="multiple_bookings_select" id="editSelectMultipleBookings" title="<?=$lang['add']['select'];?>" required>
|
||||
<option value="0" <?=($result['multiple_bookings'] == 0) ? "selected" : null;?>><?=$lang['mailbox']['booking_0'];?></option>
|
||||
<option value="-1" <?=($result['multiple_bookings'] == -1) ? "selected" : null;?>><?=$lang['mailbox']['booking_lt0'];?></option>
|
||||
<option value="custom" <?=($result['multiple_bookings'] >= 1) ? "selected" : null;?>><?=$lang['mailbox']['booking_custom'];?></option>
|
||||
|
@ -625,7 +673,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editresource" data-item="<?=htmlspecialchars($result['name']);?>" data-api-url='edit/resource' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editresource" data-item="<?=htmlspecialchars($result['name']);?>" data-api-url='edit/resource' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -671,7 +719,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editbcc" data-item="<?=$bcc;?>" data-api-url='edit/bcc' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editbcc" data-item="<?=$bcc;?>" data-api-url='edit/bcc' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -683,7 +731,9 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
<?php
|
||||
}
|
||||
}
|
||||
elseif (isset($_GET['recipient_map']) && !empty($_GET["recipient_map"])) {
|
||||
elseif (isset($_GET['recipient_map']) &&
|
||||
!empty($_GET["recipient_map"]) &&
|
||||
$_SESSION['mailcow_cc_role'] == "admin") {
|
||||
$map = intval($_GET["recipient_map"]);
|
||||
$result = recipient_map('details', $map);
|
||||
if (substr($result['recipient_map_old'], 0, 1) == '@') {
|
||||
|
@ -718,7 +768,68 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="edit_recipient_map" data-item="<?=$map;?>" data-api-url='edit/recipient_map' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="edit_recipient_map" data-item="<?=$map;?>" data-api-url='edit/recipient_map' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
}
|
||||
else {
|
||||
?>
|
||||
<div class="alert alert-info" role="alert"><?=$lang['info']['no_action'];?></div>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
elseif (isset($_GET['tls_policy_map']) &&
|
||||
!empty($_GET["tls_policy_map"]) &&
|
||||
$_SESSION['mailcow_cc_role'] == "admin") {
|
||||
$map = intval($_GET["tls_policy_map"]);
|
||||
$result = tls_policy_maps('details', $map);
|
||||
if (!empty($result)) {
|
||||
?>
|
||||
<h4><?=$lang['mailbox']['tls_policy_maps']?>: <?=$result['dest'];?></h4>
|
||||
<br />
|
||||
<form class="form-horizontal" data-id="edit_tls_policy_maps" role="form" method="post">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="dest"><?=$lang['mailbox']['tls_map_dest'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input value="<?=$result['dest'];?>" type="text" class="form-control" name="dest" id="dest">
|
||||
<small><?=$lang['mailbox']['tls_map_dest_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="policy"><?=$lang['mailbox']['tls_map_policy'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" name="policy" required>
|
||||
<option value="none" <?=($result['policy'] != 'none') ?: 'selected';?>>none</option>
|
||||
<option value="may" <?=($result['policy'] != 'may') ?: 'selected';?>>may</option>
|
||||
<option value="encrypt" <?=($result['policy'] != 'encrypt') ?: 'selected';?>>encrypt</option>
|
||||
<option value="dane" <?=($result['policy'] != 'dane') ?: 'selected';?>>dane-only</option>
|
||||
<option value="dane-only" <?=($result['policy'] != 'dane-only') ?: 'selected';?>>dane-only</option>
|
||||
<option value="fingerprint" <?=($result['policy'] != 'fingerprint') ?: 'selected';?>>fingerprint</option>
|
||||
<option value="verify" <?=($result['policy'] != 'verify') ?: 'selected';?>>verify</option>
|
||||
<option value="secure" <?=($result['policy'] != 'secure') ?: 'selected';?>>secure</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="parameters"><?=$lang['mailbox']['tls_map_parameters'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input value="<?=$result['parameters'];?>" type="text" class="form-control" name="parameters" id="parameters">
|
||||
<small><?=$lang['mailbox']['tls_map_parameters_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="active" <?php if (isset($result['active_int']) && $result['active_int']=="1") { echo "checked"; }; ?>> <?=$lang['edit']['active'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="edit_tls_policy_maps" data-item="<?=$map;?>" data-api-url='edit/tls-policy-map' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -885,7 +996,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editsyncjob" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/syncjob' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editsyncjob" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/syncjob' data-api-attr='{}' href="#"><?=$lang['edit']['save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -936,7 +1047,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="edit_selected" data-id="editfilter" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/filter' data-api-attr='{}' href="#"><?=$lang['edit']['validate_save'];?></button>
|
||||
<button class="btn btn-success" data-action="edit_selected" data-id="editfilter" data-item="<?=htmlspecialchars($result['id']);?>" data-api-url='edit/filter' data-api-attr='{}' href="#"><?=$lang['edit']['validate_save'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -965,14 +1076,14 @@ else {
|
|||
<script type='text/javascript'>
|
||||
<?php
|
||||
$lang_user = json_encode($lang['user']);
|
||||
echo "var lang = ". $lang_user . ";\n";
|
||||
echo "var lang_user = ". $lang_user . ";\n";
|
||||
echo "var table_for_domain = '". ((isset($domain)) ? $domain : null) . "';\n";
|
||||
echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n";
|
||||
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/edit.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/edit.js"></script>
|
||||
<?php
|
||||
require_once("inc/footer.inc.php");
|
||||
?>
|
||||
|
|
|
@ -1,5 +1,5 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<!-- Generator: Adobe Illustrator 17.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
||||
|
||||
<svg
|
||||
xmlns:dc="http://purl.org/dc/elements/1.1/"
|
||||
|
@ -10,20 +10,21 @@
|
|||
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
|
||||
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
|
||||
version="1.1"
|
||||
id="Layer_1"
|
||||
id="layer1"
|
||||
x="0px"
|
||||
y="0px"
|
||||
width="374.82101"
|
||||
height="356.871"
|
||||
viewBox="0 0 374.821 356.871"
|
||||
enable-background="new 0 0 1600 1200"
|
||||
width="434.82101"
|
||||
height="376.871"
|
||||
viewBox="0 0 434.82101 376.871"
|
||||
enable-background="new 0 0 374.82 356.871"
|
||||
xml:space="preserve"
|
||||
inkscape:version="0.91 r13725"
|
||||
sodipodi:docname="cow_mailcow.svg"><metadata
|
||||
id="metadata144"><rdf:RDF><cc:Work
|
||||
id="metadata77"><rdf:RDF><cc:Work
|
||||
rdf:about=""><dc:format>image/svg+xml</dc:format><dc:type
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs142" /><sodipodi:namedview
|
||||
rdf:resource="http://purl.org/dc/dcmitype/StillImage" /><dc:title></dc:title><cc:license
|
||||
rdf:resource="" /></cc:Work></rdf:RDF></metadata><defs
|
||||
id="defs75" /><sodipodi:namedview
|
||||
pagecolor="#ffffff"
|
||||
bordercolor="#666666"
|
||||
borderopacity="1"
|
||||
|
@ -32,161 +33,150 @@
|
|||
guidetolerance="10"
|
||||
inkscape:pageopacity="0"
|
||||
inkscape:pageshadow="2"
|
||||
inkscape:window-width="1097"
|
||||
inkscape:window-height="1138"
|
||||
id="namedview140"
|
||||
inkscape:window-width="1721"
|
||||
inkscape:window-height="1177"
|
||||
id="namedview73"
|
||||
showgrid="false"
|
||||
inkscape:zoom="1.5733334"
|
||||
inkscape:cx="264.82839"
|
||||
inkscape:cy="340.43592"
|
||||
inkscape:window-x="814"
|
||||
inkscape:window-y="0"
|
||||
inkscape:window-maximized="0"
|
||||
inkscape:current-layer="g3"
|
||||
fit-margin-top="0"
|
||||
fit-margin-left="0"
|
||||
fit-margin-right="0"
|
||||
fit-margin-bottom="0" /><g
|
||||
inkscape:zoom="1.4142136"
|
||||
inkscape:cx="219.01206"
|
||||
inkscape:cy="236.74714"
|
||||
inkscape:window-x="-8"
|
||||
inkscape:window-y="-8"
|
||||
inkscape:window-maximized="1"
|
||||
inkscape:current-layer="layer1"
|
||||
fit-margin-top="10"
|
||||
fit-margin-left="50"
|
||||
fit-margin-bottom="10"
|
||||
fit-margin-right="10"
|
||||
showguides="true" /><g
|
||||
id="g3"
|
||||
transform="translate(-648.292,-401.988)"><g
|
||||
id="g5"><g
|
||||
id="g7"><g
|
||||
id="email"><path
|
||||
d="m 890.306,557.81 29.26,11.373 0,172.027 c 0,9.753 -7.895,17.649 -17.638,17.649 l -235.998,0 c -9.743,0 -17.638,-7.896 -17.638,-17.649 l 0,-172.026 29.259,-8.937"
|
||||
id="path10"
|
||||
transform="translate(50,10)"><g
|
||||
id="grey_5_"><path
|
||||
d="m 55.948,213.25 c 0.07331,-20.26146 -0.716379,-17.26061 -3.655806,-39.26743 2.227824,-22.4392 -7.627923,-38.85857 -7.669233,-58.34044 0,-4.715 -5.805961,-6.78013 -4.760961,-11.13713 -6.292,13.037 -9.833,27.707 -9.833,43.222 0,25.946 9.89,49.533 26.027,67.059 -0.048,-0.511 -0.082,-1.023 -0.108,-1.536 z"
|
||||
id="path6"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="M 758.871,656.221 649.49,747.45 c 2.507,6.648 8.901,11.409 16.44,11.409 l 235.998,0 c 7.536,0 13.933,-4.761 16.444,-11.409 l -107.402,-91.229 -52.099,0 z"
|
||||
id="path12"
|
||||
style="fill:#3d5263"
|
||||
sodipodi:nodetypes="ccccscc" /></g><g
|
||||
id="yellow"><path
|
||||
d="m 254.808,180.412 -0.567,0.455 c -10.49,39.88 -40.951,71.658 -80.048,83.996 l 10.952,9.206 53.296,44.799 31.601,26.563 c 0.783,-2.011 1.229,-4.19 1.231,-6.478 0,-0.007 10e-4,-0.013 10e-4,-0.02 l 0,-16.836 0,-10e-4 0,-28.141 0,-126.736 -16.466,13.193 z"
|
||||
id="path9"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fee70f;fill-opacity:0.89499996" /><g
|
||||
id="g14"><path
|
||||
d="m 810.391,656.686 107.981,90.764 c -0.331,0.881 -0.744,1.726 -1.205,2.536 l 0.028,0.035 c 1.501,-2.596 2.371,-5.594 2.371,-8.81 l 0,-172.004 -109.175,87.479 z"
|
||||
style="fill:#f9e82d" /><path
|
||||
d="m 23.027,185.52 -6.574,-5.225 -16.452,-13.076 0,90.407 0,81.307 c 0,2.295 0.447,4.481 1.233,6.499 l 58.39,-48.683 26.964,-22.481 12.38,-10.321 C 62.73,251.524 34.307,222.274 23.027,185.52 Z"
|
||||
id="path11"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f9e82d" /><path
|
||||
d="m 238.441,318.868 -53.296,-44.799 -10.952,-9.206 c -11.431,3.607 -23.597,5.558 -36.22,5.558 -13.653,0 -26.772,-2.28 -39.004,-6.474 l -12.38,10.321 -26.965,22.482 -58.39,48.683 c 2.605,6.69 9.094,11.438 16.706,11.438 l 235.394,0 c 7.613,0 14.103,-4.749 16.707,-11.44 l -31.6,-26.563 z"
|
||||
id="path13"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#edd514;fill-opacity:0.89499996" /></g><g
|
||||
id="grey_4_"><path
|
||||
enable-background="new "
|
||||
d="M 238.441,318.868 C 196.984,322.876 123.368,324.434 59.625,296.75 38.082,287.394 17.666,274.7 0.002,257.627 l 0,81.307 c 0,2.295 0.447,4.481 1.233,6.499 2.605,6.69 9.094,11.438 16.706,11.438 l 235.394,0 c 7.613,0 14.103,-4.749 16.707,-11.44 0.783,-2.011 1.229,-4.19 1.231,-6.478 l 0,-24.584 c 0,0 -12.58,2.541 -32.832,4.499 z"
|
||||
id="path16"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f9e82d;fill-opacity:1" /><path
|
||||
d="m 649.49,747.45 108.864,-90.764 -110.061,-87.479 0,172.003 c 0,3.216 0.876,6.214 2.367,8.81 l 0.039,-0.035 c -0.466,-0.809 -0.877,-1.654 -1.209,-2.535 z"
|
||||
style="opacity:0.1;fill:#3d5263" /><path
|
||||
enable-background="new "
|
||||
d="m 86.588,274.268 c 14.979,6.703 31.579,10.435 49.051,10.435 17.648,0 34.408,-3.803 49.505,-10.634 37.082,-16.777 64.125,-51.824 69.664,-93.657 l -0.567,0.455 c -10.49,39.88 -40.951,71.658 -80.048,83.996 -11.431,3.607 -23.597,5.558 -36.22,5.558 -13.653,0 -26.772,-2.28 -39.004,-6.474 C 62.731,251.524 34.308,222.274 23.028,185.52 l -6.574,-5.225 c 5.525,42.054 32.786,77.261 70.134,93.973 z"
|
||||
id="path18"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f9e82d;fill-opacity:1" /></g></g><path
|
||||
d="m 961.81,681.214 c 0,0 -15.232,16.783 -42.244,14.73 l 0,28.14 c 13.328,-5.185 47.061,-20.036 56.854,-40.809 l -14.61,-2.061 z"
|
||||
id="path20"
|
||||
style="opacity:0.1;fill:#3d5263" /></g><g
|
||||
id="white_1_"><path
|
||||
d="m 54.293,63.875 c -1.799,1.745 -3.541,3.548 -5.229,5.402 -0.042,0.046 -0.085,0.092 -0.127,0.139 -0.234,0.258 -0.473,0.51 -0.705,0.77 0.055,-0.055 0.111,-0.108 0.166,-0.163 21.76,-21.782 51.828,-35.259 85.046,-35.259 66.396,0 120.222,53.826 120.222,120.223 0,30.718 -11.526,58.74 -30.482,79.991 21.633,-21.737 35.006,-51.7 35.01,-84.791 0,-0.004 0,-0.009 0,-0.013 0,-21.143 -5.465,-41.007 -15.049,-58.269 -1.449,-2.608 -2.991,-5.157 -4.624,-7.643 -5.377,-8.187 -11.727,-15.676 -18.885,-22.307 -5.903,-5.467 -12.351,-10.354 -19.26,-14.558 -4.278,-2.604 -8.734,-4.944 -13.341,-7.006 -10.627,-4.756 -22.07,-8.016 -34.062,-9.509 -4.915,-0.612 -9.921,-0.931 -15.001,-0.931 -5.747,0 -11.398,0.409 -16.93,1.189 -12.291,1.733 -23.981,5.329 -34.784,10.487 -4.742,2.264 -9.313,4.83 -13.688,7.672 -6.561,4.266 -12.682,9.149 -18.277,14.576 z"
|
||||
id="path21"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 984.594,658.413 c 3.59,-9.156 7.701,-11 9.346,-11.346 -49.276,4.542 -32.99,38.693 -32.99,38.693 0,0 6.229,14.728 26.532,13.892 27.063,0.461 35.631,-50.166 35.631,-50.166 -6.654,11.655 -26.404,9.876 -38.519,8.927 z"
|
||||
id="path22"
|
||||
style="fill:#ffffff" /><path
|
||||
d="m 95.828,118.535 c 2.559,0 4.63,-2.071 4.63,-4.629 0,-2.553 -2.071,-4.626 -4.63,-4.626 -2.558,0 -4.634,2.074 -4.634,4.626 10e-4,2.557 2.076,4.629 4.634,4.629 z"
|
||||
id="path23"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 783.931,446.247 c -66.396,0 -120.223,53.827 -120.223,120.223 0,66.396 53.827,120.221 120.223,120.221 66.397,0 120.222,-53.825 120.222,-120.221 0,-66.395 -53.825,-120.223 -120.222,-120.223 z m -11.96,215.702 c -53.009,0 -95.982,-43.855 -95.982,-97.953 0,-54.098 42.973,-97.952 95.982,-97.952 53.007,0 95.98,43.855 95.98,97.952 -10e-4,54.098 -42.973,97.953 -95.98,97.953 z"
|
||||
id="path26"
|
||||
style="fill:#ffffff" /><path
|
||||
d="m 186.85,118.535 c 2.556,0 4.629,-2.071 4.629,-4.629 0,-2.553 -2.074,-4.626 -4.629,-4.626 -2.559,0 -4.631,2.074 -4.631,4.626 0,2.557 2.073,4.629 4.631,4.629 z"
|
||||
id="path25"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.1;fill:#3d5263" /><g
|
||||
id="g28"><g
|
||||
id="g30"><polyline
|
||||
points="691.144,492.5 673.257,540.276 686.55,605.582 712.496,631.852 "
|
||||
id="polyline32"
|
||||
style="fill:#3d5263" /><g
|
||||
id="g34"><g
|
||||
id="g36"><polyline
|
||||
points="658.248,450.81 673.501,487.076 693.836,496.903 724.04,458.731 "
|
||||
id="polyline38"
|
||||
style="fill:#fef3df" /><g
|
||||
id="g40"><path
|
||||
d="m 710.634,473.205 c 0,0 -22.482,-25.556 -49.793,-18.975 0,0 4.667,34.118 46.349,44.019 l 2.61,8.533 c 0,0 -65.612,-9.689 -59.339,-67.593 0,0 49.008,-19.884 72.598,15.106"
|
||||
id="path42"
|
||||
style="fill:#ffffff" /></g><g
|
||||
id="grey_3_"><g
|
||||
id="g28"><path
|
||||
d="m 223.701,234.394 c 18.648,-21.18 29.965,-48.971 29.965,-79.408 0,-66.396 -53.825,-120.223 -120.222,-120.223 -33.218,0 -63.286,13.477 -85.046,35.259 -4.591,5.125 -8.746,10.647 -12.413,16.507 -1.524,2.437 -2.963,4.931 -4.314,7.48 -7.067,13.341 -11.704,28.167 -13.301,43.893 -0.411,4.043 -0.622,8.146 -0.622,12.298 0,3.849 0.188,7.653 0.542,11.409 0.776,8.241 2.38,16.24 4.735,23.912 11.281,36.754 39.703,66.004 75.941,78.427 12.231,4.193 25.351,6.474 39.004,6.474 12.623,0 24.79,-1.95 36.22,-5.558 18.139,-5.725 34.412,-15.64 47.7,-28.603 0.536,-0.522 1.811,-1.867 1.811,-1.867 z m -5.788,-58.356 c -2.132,7.217 -5.052,14.085 -8.668,20.495 -16.571,29.372 -47.64,49.146 -83.233,49.146 -27.584,0 -52.447,-11.88 -69.956,-30.895 C 39.919,197.26 30.03,173.673 30.03,147.726 c 0,-15.515 3.54,-30.185 9.833,-43.222 15.648,-32.42 48.344,-54.73 86.15,-54.73 3.967,0 7.876,0.25 11.717,0.728 47.479,5.898 84.262,47.175 84.262,97.224 -0.002,9.846 -1.431,19.348 -4.079,28.312 z"
|
||||
id="path30"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><polyline
|
||||
points="909.697,450.81 894.447,487.076 874.114,496.903 843.907,458.731 "
|
||||
id="polyline44"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 857.314,473.205 c 0,0 22.48,-25.556 49.79,-18.975 0,0 -4.664,34.118 -46.347,44.019 l -2.613,8.533 c 0,0 65.611,-9.689 59.339,-67.593 0,0 -49.006,-19.884 -72.6,15.106"
|
||||
id="path46"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /></g></g><path
|
||||
d="m 726.619,647.067 55.945,0 16.40428,-204.81407 c -55.814,0 -112.41728,30.01707 -112.41728,77.85207 0,1.454 0.085,2.787 0.121,4.175 0.127,3.934 0.448,7.585 0.856,11.135 1.689,14.816 5.451,27.177 8.461,43.383 1.452,7.831 5.002,23.374 5.002,23.374 0.056,0.408 0.165,0.804 0.224,1.211 2.535,16.546 11.832,32.027 25.404,43.684 z"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765"
|
||||
sodipodi:nodetypes="cccscccccc" /><path
|
||||
d="m 781.992,433.489 0,213.577 55.944,0 c 13.572,-11.657 22.867,-27.138 25.406,-43.684 0.058,-0.407 0.163,-0.803 0.221,-1.211 0,0 3.549,-15.543 5.002,-23.374 3.011,-16.206 6.774,-28.567 8.464,-43.381 0.405,-3.552 0.724,-7.203 0.846,-11.137 0.042,-1.388 0.126,-2.721 0.126,-4.175 0,-47.834 -40.191,-86.615 -96.009,-86.615 z"
|
||||
id="path50"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><g
|
||||
id="g52"><g
|
||||
id="g54"><path
|
||||
d="m 860.944,613.502 c 0,28.321 -35.091,51.289 -78.383,51.289 -43.299,0 -78.388,-22.968 -78.388,-51.289 0,-28.325 35.089,-51.289 78.388,-51.289 43.292,0 78.383,22.964 78.383,51.289 z"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /></g></g><g
|
||||
id="g58"><g
|
||||
id="g60"><g
|
||||
id="g62"><path
|
||||
d="m 747.044,605.582 c 0,6.215 -5.04,11.256 -11.261,11.256 -6.21,0 -11.253,-5.041 -11.253,-11.256 0,-6.223 5.043,-11.257 11.253,-11.257 6.22,0 11.261,5.034 11.261,11.257 z"
|
||||
id="path64"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /></g></g><g
|
||||
id="g66"><g
|
||||
id="g68"><path
|
||||
d="m 840.856,605.582 c 0,6.215 -5.037,11.256 -11.257,11.256 -6.218,0 -11.259,-5.041 -11.259,-11.256 0,-6.223 5.041,-11.257 11.259,-11.257 6.22,0 11.257,5.034 11.257,11.257 z"
|
||||
id="path70"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /></g></g></g><g
|
||||
id="g72"><path
|
||||
d="m 875.228,525.835 c 0.354,-3.113 0.634,-6.311 0.743,-9.754 0.035,-1.218 0.109,-2.384 0.109,-3.661 0,-40.785 -33.369,-74.043 -80.237,-75.775 l -7.335,0.005 -0.006,0 c -0.007,0.018 -25.93541,90.33209 79.27959,142.17809 3.15658,-17.35082 5.65276,-38.01947 7.44641,-52.99309 z"
|
||||
id="path74"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#87654a"
|
||||
sodipodi:nodetypes="ccsccccc" /></g><g
|
||||
id="g76"><g
|
||||
id="g78"><g
|
||||
id="g80"><g
|
||||
id="g82"><path
|
||||
d="m 843.907,519.681 c 0,6.964 -5.65,12.611 -12.618,12.611 -6.963,0 -12.614,-5.646 -12.614,-12.611 0,-6.97 5.651,-12.614 12.614,-12.614 6.968,0 12.618,5.644 12.618,12.614 z"
|
||||
id="path84"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /></g></g></g><g
|
||||
id="g86"><g
|
||||
id="g88"><g
|
||||
id="g90"><path
|
||||
d="m 752.028,519.681 c 0,6.964 -5.649,12.611 -12.612,12.611 -6.969,0 -12.612,-5.646 -12.612,-12.611 0,-6.97 5.642,-12.614 12.612,-12.614 6.964,0 12.612,5.644 12.612,12.614 z"
|
||||
id="path92"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /></g></g></g><g
|
||||
id="g94"><g
|
||||
id="g96"><path
|
||||
d="m 748.75,515.894 c 0,2.558 -2.071,4.629 -4.63,4.629 -2.558,0 -4.633,-2.072 -4.633,-4.629 0,-2.552 2.076,-4.626 4.633,-4.626 2.559,0 4.63,2.073 4.63,4.626 z"
|
||||
id="path98"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /></g></g><g
|
||||
id="g100"><g
|
||||
id="g102"><path
|
||||
d="m 839.771,515.894 c 0,2.558 -2.073,4.629 -4.629,4.629 -2.558,0 -4.631,-2.072 -4.631,-4.629 0,-2.552 2.072,-4.626 4.631,-4.626 2.555,0 4.629,2.073 4.629,4.626 z"
|
||||
id="path104"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /></g></g></g></g><path
|
||||
d="m 734.557,443.625 c 0,0 -18.236,-25.199 0,-41.637 0,0 13.125,32.012 40.242,31.502"
|
||||
id="path106"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 834.496,443.625 c 0,0 18.236,-25.199 0,-41.637 0,0 -13.126,32.012 -40.242,31.502"
|
||||
id="path108"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 786.264,431.965 c -66.396,0 -120.223,53.827 -120.223,120.223 0,66.396 53.827,120.221 120.223,120.221 66.397,0 120.222,-53.825 120.222,-120.221 10e-4,-66.395 -53.825,-120.223 -120.222,-120.223 z m -11.96,215.702 c -53.009,0 -95.982,-43.855 -95.982,-97.953 0,-54.098 42.973,-97.952 95.982,-97.952 53.007,0 95.979,43.855 95.979,97.952 0,54.098 -42.972,97.953 -95.979,97.953 z"
|
||||
id="path110"
|
||||
style="fill:#f1f2f2" /></g><path
|
||||
d="m 49.064,69.277 c -0.042,0.046 -0.085,0.092 -0.127,0.139 0.042,-0.047 0.085,-0.093 0.127,-0.139 z"
|
||||
id="path32"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#f1f2f2" /></g><g
|
||||
id="g112"><path
|
||||
d="m 781.737,436.751 c 66.396,0 120.221,53.827 120.221,120.223 0,30.718 -11.526,58.74 -30.482,79.991 21.636,-21.74 35.01,-51.708 35.01,-84.803 0,-66.395 -53.825,-120.222 -120.222,-120.222 -35.678,0 -67.721,15.549 -89.739,40.233 21.772,-21.879 51.91,-35.422 85.212,-35.422 z"
|
||||
id="path114"
|
||||
id="darkbrown_1_"><path
|
||||
d="m 257.626,161.89 c -0.488,5.062 -1.29,10.032 -2.387,14.89 -0.31,1.371 -0.643,2.733 -0.999,4.086 l 0.567,-0.455 16.466,-13.193 0,-0.023 -13.647,-5.305 z"
|
||||
id="path35"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#ffffff" /></g></g><path
|
||||
d="m 919.566,695.944 c 0,0 7.562,0.712 13.317,-0.502 l 13.013,16.12 c 0,0 -17.639,9.525 -26.33,12.523 l 0,-28.141 z"
|
||||
id="path116"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 0.001,167.219 16.451,13.076 6.574,5.225 c -2.354,-7.672 -3.959,-15.671 -4.735,-23.912 l -2.85,0.871 L 0,167.196"
|
||||
id="path37"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.1;fill:#3d5263" /></g><path
|
||||
d="m 648.292,659.614 0,81.645 c 0,9.72 7.88,17.6 17.6,17.6 l 236.073,0 c 9.72,0 17.6,-7.88 17.6,-17.6 l 0,-24.902 c 10e-4,0 -175.814,35.524 -271.273,-56.743 z"
|
||||
id="path124"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 87.491,192.337 c -6.21,0 -11.254,5.034 -11.254,11.257 0,6.216 5.043,11.257 11.254,11.257 6.221,0 11.261,-5.041 11.261,-11.257 0,-6.223 -5.041,-11.257 -11.261,-11.257 z"
|
||||
id="path39"
|
||||
inkscape:connector-curvature="0"
|
||||
style="opacity:0.1;fill:#3d5263" /></g><g
|
||||
id="g126" /></g></svg>
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 181.307,192.337 c -6.218,0 -11.259,5.034 -11.259,11.257 0,6.216 5.041,11.257 11.259,11.257 6.22,0 11.257,-5.041 11.257,-11.257 0,-6.223 -5.037,-11.257 -11.257,-11.257 z"
|
||||
id="path41"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620" /><path
|
||||
d="m 182.997,102.25057 c -6.963,0 -15.44243,7.76632 -15.44243,14.73532 0,6.965 8.12588,17.2072 15.08888,17.2072 6.968,0 15.79898,-9.53609 15.79898,-16.50009 0.001,-6.97 -8.47743,-15.44243 -15.44543,-15.44243 z m 3.853,16.28443 c -2.558,0 -4.631,-2.072 -4.631,-4.629 0,-2.552 2.072,-4.626 4.631,-4.626 2.555,0 4.629,2.073 4.629,4.626 0,2.558 -2.073,4.629 -4.629,4.629 z"
|
||||
id="path43"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620"
|
||||
sodipodi:nodetypes="ssscssssss" /><path
|
||||
d="m 89.709786,102.60413 c -6.971,0 -14.379767,8.11987 -14.379767,15.08887 0,6.965 8.824981,16.14653 15.793981,16.14653 6.963,0 15.79298,-9.18253 15.79298,-16.14653 0.001,-6.97 -10.243194,-15.08887 -17.207194,-15.08887 z M 95.828,118.535 c -2.559,0 -4.634,-2.072 -4.634,-4.629 0,-2.552 2.076,-4.626 4.634,-4.626 2.559,0 4.63,2.073 4.63,4.626 0,2.558 -2.071,4.629 -4.63,4.629 z"
|
||||
id="path45"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#5a3620"
|
||||
sodipodi:nodetypes="ssscssssss" /></g><g
|
||||
id="cream"><path
|
||||
d="m 336.302,256.425 c 3.59,-9.155 7.701,-11 9.346,-11.346 -40.757,3.757 -36.661,27.769 -34.026,35.96 0.55,1.712 1.037,2.733 1.037,2.733 0,0 2.031,4.787 7.536,8.748 4.149,2.986 10.27,5.503 18.995,5.144 27.063,0.461 35.631,-50.166 35.631,-50.166 -6.654,11.655 -26.404,9.876 -38.519,8.927 z"
|
||||
id="path48"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 48.937,69.415 c 0.042,-0.046 0.085,-0.092 0.127,-0.139 1.688,-1.854 3.43,-3.657 5.229,-5.402 -8.915,-6.977 -24.344,-15.826 -41.744,-11.633 0,0 2.814,20.458 23.437,34.287 3.667,-5.86 7.822,-11.381 12.413,-16.507 -0.055,0.055 -0.111,0.108 -0.166,0.163 0.231,-0.258 0.47,-0.511 0.704,-0.769 z"
|
||||
id="path50"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 258.812,52.242 c -15.831,-3.815 -30.029,3.169 -39.176,9.714 7.158,6.63 13.508,14.12 18.885,22.307 17.763,-13.689 20.291,-32.021 20.291,-32.021 z"
|
||||
id="path52"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 134.269,160.225 c -43.299,0 -78.388,22.964 -78.388,51.289 0,0.582 0.038,1.157 0.067,1.735 0.026,0.514 0.06,1.025 0.108,1.535 17.508,19.015 42.371,30.895 69.956,30.895 35.594,0 66.662,-19.774 83.233,-49.146 -9.796,-21.016 -39.651,-36.308 -74.976,-36.308 z M 87.491,214.85 c -6.211,0 -11.254,-5.041 -11.254,-11.257 0,-6.223 5.044,-11.257 11.254,-11.257 6.22,0 11.261,5.034 11.261,11.257 0,6.216 -5.04,11.257 -11.261,11.257 z m 93.816,0 c -6.218,0 -11.259,-5.041 -11.259,-11.257 0,-6.223 5.041,-11.257 11.259,-11.257 6.22,0 11.257,5.034 11.257,11.257 0,6.216 -5.037,11.257 -11.257,11.257 z"
|
||||
id="path54"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="M 86.265,0 C 68.102,16.373 86.113,41.427 86.258,41.628 97.061,36.47 108.751,32.874 121.042,31.141 97.629,27.686 86.265,0 86.265,0 Z"
|
||||
id="path56"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /><path
|
||||
d="m 186.204,0 c 0,0 -10.863,26.476 -33.231,30.883 11.992,1.493 23.435,4.752 34.062,9.509 C 190.383,35.136 202.036,14.271 186.204,0 Z"
|
||||
id="path58"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#fef3df" /></g><g
|
||||
id="g60"><path
|
||||
d="m 217.913,176.038 c 2.647,-8.964 6.55187,-25.89162 6.55187,-35.73662 C 224.46487,90.252379 185.208,56.4 137.728,50.502 c -2.157,28.03 3.629,87.043 80.185,125.536 z m -47.53,-58.345 c 0,-6.97 5.651,-12.614 12.614,-12.614 6.968,0 12.617,5.645 12.617,12.614 0,6.964 -5.649,12.611 -12.617,12.611 -6.963,0 -12.614,-5.646 -12.614,-12.611 z"
|
||||
id="path62"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#87654a"
|
||||
sodipodi:nodetypes="csccsssss" /></g><g
|
||||
id="brown"><path
|
||||
d="m 312.658,283.772 c 0,0 -0.487,-1.021 -1.037,-2.733 -3.758,3.317 -13.036,10.236 -27.03,12.416 l 0,-10e-4 c -0.009,0.002 -0.019,0.003 -0.027,0.005 -4.044,0.628 -8.479,0.863 -13.29,0.497 l 0,28.141 c 2.059,-0.801 4.607,-1.834 7.477,-3.083 5.462,-2.377 12.093,-5.542 18.771,-9.395 0.027,-0.016 0.054,-0.031 0.081,-0.047 8.158,-4.713 16.37,-10.452 22.593,-17.052 -5.506,-3.961 -7.538,-8.748 -7.538,-8.748 z"
|
||||
id="path65"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 12.549,52.242 c 17.4,-4.193 32.83,4.656 41.744,11.633 C 59.888,58.449 66.009,53.565 72.57,49.301 48.272,18.498 2.169,37.201 2.169,37.201 -1.114,67.502 15.288,84.594 31.672,94.01 33.023,91.461 34.462,88.966 35.986,86.53 15.363,72.699 12.549,52.242 12.549,52.242 Z"
|
||||
id="path67"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 200.376,47.398 c 6.909,4.205 13.356,9.091 19.26,14.558 9.146,-6.545 23.345,-13.529 39.176,-9.714 0,0 -2.527,18.332 -20.291,32.021 1.633,2.485 3.175,5.034 4.624,7.643 15.141,-9.784 29.097,-26.539 26.046,-54.704 0,-10e-4 -44.152,-17.909 -68.815,10.196 z"
|
||||
id="path69"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765" /><path
|
||||
d="m 138.854,50.502 c -3.841,-0.478 -8.875,-0.728 -12.842,-0.728 -37.806,0 -70.502,22.31 -86.15,54.73 -1.045,4.357 -1.603,8.897 -1.603,13.612 0,1.454 0.085,2.787 0.121,4.175 0.127,3.935 0.448,7.585 0.855,11.135 4.291755,24.95762 7.959057,42.49186 13.464,66.758 0.056,0.407 0.164,0.804 0.224,1.211 0.617,4.028 1.642,7.992 3.025,11.854 -0.029,-0.578 -0.067,-1.153 -0.067,-1.735 0,-28.325 35.089,-51.289 78.388,-51.289 35.325,0 65.181,15.292 74.977,36.308 3.616,-6.409 6.536,-13.277 8.668,-20.495 C 179.98905,152.54886 163.9995,134.88987 153.25313,111.82124 142.50675,88.752624 137.775,64.517 138.854,50.502 Z m -47.73,79.802 c -6.97,0 -12.612,-5.646 -12.612,-12.611 0,-6.97 5.642,-12.614 12.612,-12.614 6.964,0 12.611,5.645 12.611,12.614 0.001,6.964 -5.648,12.611 -12.611,12.611 z"
|
||||
id="path71"
|
||||
inkscape:connector-curvature="0"
|
||||
style="fill:#b58765"
|
||||
sodipodi:nodetypes="cscscccccssccscssscs" /></g></g></svg>
|
Before Width: | Height: | Size: 12 KiB After Width: | Height: | Size: 14 KiB |
|
@ -12,10 +12,20 @@ logger();
|
|||
<script src="/js/formcache.min.js"></script>
|
||||
<script src="/js/google.charts.loader.js"></script>
|
||||
<script src="/js/numberedtextarea.min.js"></script>
|
||||
<script src="/js/sha1.min.js"></script>
|
||||
<script src="/js/u2f-api.js"></script>
|
||||
<script src="/js/api.js"></script>
|
||||
<script src="/js/mailcow.js"></script>
|
||||
<script>
|
||||
var loading_text = '<?= $lang['footer']['loading']; ?>'
|
||||
<?php
|
||||
$lang_footer = json_encode($lang['footer']);
|
||||
$lang_acl = json_encode($lang['acl']);
|
||||
$lang_tfa = json_encode($lang['tfa']);
|
||||
echo "var lang_footer = ". $lang_footer . ";\n";
|
||||
echo "var lang_acl = ". $lang_acl . ";\n";
|
||||
echo "var lang_tfa = ". $lang_tfa . ";\n";
|
||||
echo "var docker_timeout = ". $DOCKER_TIMEOUT * 1000 . ";\n";
|
||||
?>
|
||||
$(window).scroll(function() {
|
||||
sessionStorage.scrollTop = $(this).scrollTop();
|
||||
});
|
||||
|
@ -28,17 +38,8 @@ $(window).load(function() {
|
|||
$(".overlay").hide();
|
||||
});
|
||||
$(document).ready(function() {
|
||||
window.mailcow_alert_box = function(message, type) {
|
||||
msg = $('<span/>').text(message).text();
|
||||
if (type == 'danger') {
|
||||
auto_hide = 0;
|
||||
$('#' + localStorage.getItem("add_modal")).modal('show');
|
||||
localStorage.removeItem("add_modal");
|
||||
} else {
|
||||
auto_hide = 5000;
|
||||
}
|
||||
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
|
||||
}
|
||||
// TFA, CSRF, Alerts in footer.inc.php
|
||||
// Other general functions in mailcow.js
|
||||
<?php
|
||||
$alertbox_log_parser = alertbox_log_parser($_SESSION);
|
||||
if (is_array($alertbox_log_parser)) {
|
||||
|
@ -50,7 +51,6 @@ $(document).ready(function() {
|
|||
unset($_SESSION['return']);
|
||||
}
|
||||
?>
|
||||
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
|
||||
// Confirm TFA modal
|
||||
<?php if (isset($_SESSION['pending_tfa_method'])):?>
|
||||
$('#ConfirmTFAModal').modal({
|
||||
|
@ -59,7 +59,7 @@ $(document).ready(function() {
|
|||
});
|
||||
$('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
|
||||
$('#ConfirmTFAModal').on('shown.bs.modal', function(){
|
||||
$(this).find('#token').focus();
|
||||
$(this).find('input[name=token]').focus();
|
||||
// If U2F
|
||||
if(document.getElementById("u2f_auth_data") !== null) {
|
||||
$.ajax({
|
||||
|
@ -68,7 +68,7 @@ $(document).ready(function() {
|
|||
dataType: 'script',
|
||||
url: "/api/v1/get/u2f-authentication/<?= (isset($_SESSION['pending_mailcow_cc_username'])) ? rawurlencode($_SESSION['pending_mailcow_cc_username']) : null; ?>",
|
||||
complete: function(data){
|
||||
$('#u2f_status_auth').html('<?=$lang['tfa']['waiting_usb_auth'];?>');
|
||||
$('#u2f_status_auth').html(lang_tfa.waiting_usb_auth);
|
||||
data;
|
||||
setTimeout(function() {
|
||||
console.log("Ready to authenticate");
|
||||
|
@ -98,7 +98,6 @@ $(document).ready(function() {
|
|||
<?php endif; ?>
|
||||
|
||||
// Set TFA modals
|
||||
|
||||
$('#selectTFA').change(function () {
|
||||
if ($(this).val() == "yubi_otp") {
|
||||
$('#YubiOTPModal').modal('show');
|
||||
|
@ -121,7 +120,7 @@ $(document).ready(function() {
|
|||
data;
|
||||
setTimeout(function() {
|
||||
console.log("Ready to register");
|
||||
$('#u2f_status_reg').html('<?=$lang['tfa']['waiting_usb_register'];?>');
|
||||
$('#u2f_status_reg').html(lang_tfa.waiting_usb_register);
|
||||
u2f.register(appId, registerRequests, registeredKeys, function(deviceResponse) {
|
||||
var form = document.getElementById('u2f_reg_form');
|
||||
var reg = document.getElementById('u2f_register_data');
|
||||
|
@ -146,94 +145,8 @@ $(document).ready(function() {
|
|||
}
|
||||
});
|
||||
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
|
||||
// Remember last navigation pill
|
||||
(function () {
|
||||
'use strict';
|
||||
if ($('a[data-toggle="tab"]').length) {
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
if ($(this).data('dont-remember') == 1) {
|
||||
return true;
|
||||
}
|
||||
var id = $(this).parents('[role="tablist"]').attr('id');
|
||||
var key = 'lastTag';
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
localStorage.setItem(key, $(e.target).attr('href'));
|
||||
});
|
||||
$('[role="tablist"]').each(function (idx, elem) {
|
||||
var id = $(elem).attr('id');
|
||||
var key = 'lastTag';
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
var lastTab = localStorage.getItem(key);
|
||||
if (lastTab) {
|
||||
$('[href="' + lastTab + '"]').tab('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
// Disable submit after submitting form (not API driven buttons)
|
||||
$('form').submit(function() {
|
||||
if ($('form button[type="submit"]').data('submitted') == '1') {
|
||||
return false;
|
||||
} else {
|
||||
$(this).find('button[type="submit"]').first().text('<?= $lang['footer']['loading']; ?>');
|
||||
$('form button[type="submit"]').attr('data-submitted', '1');
|
||||
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
|
||||
$(document).on("keydown", disableF5);
|
||||
}
|
||||
});
|
||||
|
||||
// IE fix to hide scrollbars when table body is empty
|
||||
$('tbody').filter(function (index) {
|
||||
return $(this).children().length < 1;
|
||||
}).remove();
|
||||
|
||||
// Init Bootstrap Selectpicker
|
||||
$('select').selectpicker();
|
||||
|
||||
// Trigger container restart
|
||||
$('#RestartContainer').on('show.bs.modal', function(e) {
|
||||
var container = $(e.relatedTarget).data('container');
|
||||
$('#containerName').text(container);
|
||||
$('#triggerRestartContainer').click(function(){
|
||||
$(this).prop("disabled",true);
|
||||
$(this).html('<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ');
|
||||
$('#statusTriggerRestartContainer').html('<?= $lang['footer']['restarting_container']; ?>');
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: '/inc/ajax/container_ctrl.php',
|
||||
timeout: <?= $DOCKER_TIMEOUT * 1000; ?>,
|
||||
data: {
|
||||
'service': container,
|
||||
'action': 'restart'
|
||||
}
|
||||
})
|
||||
.always( function (data, status) {
|
||||
$('#statusTriggerRestartContainer').append(data);
|
||||
var htmlResponse = $.parseHTML(data)
|
||||
if ($(htmlResponse).find('span').hasClass('text-success')) {
|
||||
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-ok"></span> ');
|
||||
setTimeout(function(){
|
||||
$('#RestartContainer').modal('toggle');
|
||||
window.location = window.location.href.split("#")[0];
|
||||
}, 1200);
|
||||
} else {
|
||||
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-remove"></span> ');
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
|
||||
// CSRF
|
||||
$('<input type="hidden" value="<?= $_SESSION['CSRF']['TOKEN']; ?>">').attr('id', 'csrf_token').attr('name', 'csrf_token').appendTo('form');
|
||||
$('<input type="hidden" value="<?= $_SESSION['CSRF']['TOKEN']; ?>">').attr('name', 'csrf_token').appendTo('form');
|
||||
if (sessionStorage.scrollTop != "undefined") {
|
||||
$(window).scrollTop(sessionStorage.scrollTop);
|
||||
}
|
||||
|
|
|
@ -0,0 +1,216 @@
|
|||
<?php
|
||||
function acl($_action, $_scope = null, $_data = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
$_data_log = $_data;
|
||||
switch ($_action) {
|
||||
case 'edit':
|
||||
switch ($_scope) {
|
||||
case 'user':
|
||||
if (!is_array($_data['username'])) {
|
||||
$usernames = array();
|
||||
$usernames[] = $_data['username'];
|
||||
}
|
||||
else {
|
||||
$usernames = $_data['username'];
|
||||
}
|
||||
foreach ($usernames as $username) {
|
||||
// Cast to array for single selections
|
||||
$acls = (array)$_data['user_acl'];
|
||||
// Create associative array from index array
|
||||
// All set items are given 1 as value
|
||||
foreach ($acls as $acl_key => $acl_val) {
|
||||
$acl_post[$acl_val] = 1;
|
||||
}
|
||||
// Users cannot change their own ACL
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $username)
|
||||
|| ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin')) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Read all available acl options by calling acl(get)
|
||||
// Set all available acl options we cannot find in the post data to 0, else 1
|
||||
$is_now = acl('get', 'user', $username);
|
||||
if (!empty($is_now)) {
|
||||
foreach ($is_now as $acl_now_name => $acl_now_val) {
|
||||
$set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'Cannot determine current ACL'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
foreach ($set_acls as $set_acl_key => $set_acl_val) {
|
||||
$stmt = $pdo->prepare("UPDATE `user_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => array('acl_saved', $username)
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'domainadmin':
|
||||
if ($_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if (!is_array($_data['username'])) {
|
||||
$usernames = array();
|
||||
$usernames[] = $_data['username'];
|
||||
}
|
||||
else {
|
||||
$usernames = $_data['username'];
|
||||
}
|
||||
foreach ($usernames as $username) {
|
||||
// Cast to array for single selections
|
||||
$acls = (array)$_data['da_acl'];
|
||||
// Create associative array from index array
|
||||
// All set items are given 1 as value
|
||||
foreach ($acls as $acl_key => $acl_val) {
|
||||
$acl_post[$acl_val] = 1;
|
||||
}
|
||||
// Users cannot change their own ACL
|
||||
if ($_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
// Read all available acl options by calling acl(get)
|
||||
// Set all available acl options we cannot find in the post data to 0, else 1
|
||||
$is_now = acl('get', 'domainadmin', $username);
|
||||
if (!empty($is_now)) {
|
||||
foreach ($is_now as $acl_now_name => $acl_now_val) {
|
||||
$set_acls[$acl_now_name] = (isset($acl_post[$acl_now_name])) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'Cannot determine current ACL'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
foreach ($set_acls as $set_acl_key => $set_acl_val) {
|
||||
$stmt = $pdo->prepare("UPDATE `da_acl` SET " . $set_acl_key . " = " . intval($set_acl_val) . "
|
||||
WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => array('acl_saved', $username)
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'get':
|
||||
switch ($_scope) {
|
||||
case 'user':
|
||||
if (!hasMailboxObjectAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $_data)) {
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $_data));
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!empty($data)) {
|
||||
unset($data['username']);
|
||||
return $data;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 'domainadmin':
|
||||
if ($_SESSION['mailcow_cc_role'] != 'admin' && $_SESSION['mailcow_cc_role'] != 'domainadmin') {
|
||||
return false;
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'domainadmin' && $_SESSION['mailcow_cc_username'] != $_data) {
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $_data));
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
if (!empty($data)) {
|
||||
unset($data['username']);
|
||||
return $data;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case 'to_session':
|
||||
if (!isset($_SESSION['mailcow_cc_role'])) {
|
||||
return false;
|
||||
}
|
||||
unset($_SESSION['acl']);
|
||||
$username = strtolower(trim($_SESSION['mailcow_cc_username']));
|
||||
// Admins get access to all modules
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin' ||
|
||||
(isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'admin')) {
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
|
||||
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($acl_all)) {
|
||||
$acl['acl'][$row['Field']] = 1;
|
||||
}
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `da_acl` WHERE `Field` != 'username';");
|
||||
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($acl_all)) {
|
||||
$acl['acl'][$row['Field']] = 1;
|
||||
}
|
||||
}
|
||||
elseif ($_SESSION['mailcow_cc_role'] == 'domainadmin' ||
|
||||
(isset($_SESSION["dual-login"]["role"]) && $_SESSION["dual-login"]["role"] == 'domainadmin')) {
|
||||
// Read all exting user_acl modules and set to 1
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
|
||||
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($acl_all)) {
|
||||
$acl['acl'][$row['Field']] = 1;
|
||||
}
|
||||
// Read da_acl rules for current user, OVERWRITE overlapping modules
|
||||
// This prevents access to a users sync jobs, when a domain admins was not given access to sync jobs
|
||||
$stmt = $pdo->prepare("SELECT * FROM `da_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => (isset($_SESSION["dual-login"]["username"])) ? $_SESSION["dual-login"]["username"] : $username));
|
||||
$acl_user = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
foreach ($acl_user as $acl_user_key => $acl_user_val) {
|
||||
$acl['acl'][$acl_user_key] = $acl_user_val;
|
||||
}
|
||||
unset($acl['acl']['username']);
|
||||
}
|
||||
elseif ($_SESSION['mailcow_cc_role'] == 'user') {
|
||||
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
unset($acl['acl']['username']);
|
||||
}
|
||||
if (!empty($acl)) {
|
||||
$_SESSION = array_merge($_SESSION, $acl);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -87,7 +87,6 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `bcc_maps` (`local_dest`, `bcc_dest`, `domain`, `active`, `type`) VALUES
|
||||
(:local_dest, :bcc_dest, :domain, :active, :type)");
|
||||
$stmt->execute(array(
|
||||
|
@ -97,15 +96,6 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
':active' => $active,
|
||||
':type' => $type
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
|
@ -155,7 +145,6 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `id` FROM `bcc_maps`
|
||||
WHERE `local_dest` = :local_dest AND `type` = :type");
|
||||
$stmt->execute(array(':local_dest' => $local_dest, ':type' => $type));
|
||||
|
@ -177,15 +166,6 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
':type' => $type,
|
||||
':id' => $id
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
|
@ -233,12 +213,19 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
return $bccdata;
|
||||
break;
|
||||
case 'delete':
|
||||
if (!isset($_SESSION['acl']['bcc_maps']) || $_SESSION['acl']['bcc_maps'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `domain` FROM `bcc_maps` WHERE id = :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$domain = $stmt->fetch(PDO::FETCH_ASSOC)['domain'];
|
||||
|
@ -252,15 +239,7 @@ function bcc($_action, $_data = null, $attr = null) {
|
|||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `id`= :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
|
@ -309,17 +288,15 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
}
|
||||
$rmaps = recipient_map('get');
|
||||
foreach ($rmaps as $rmap) {
|
||||
$old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old'];
|
||||
}
|
||||
if (in_array($old_dest_sane, $old_dests_existing)) {
|
||||
if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest))
|
||||
'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `recipient_maps` (`old_dest`, `new_dest`, `active`) VALUES
|
||||
(:old_dest, :new_dest, :active)");
|
||||
$stmt->execute(array(
|
||||
|
@ -327,15 +304,6 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
':new_dest' => $new_dest,
|
||||
':active' => $active
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
|
@ -376,7 +344,6 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
$active = intval($_data['active']);
|
||||
if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -387,18 +354,16 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
}
|
||||
$rmaps = recipient_map('get');
|
||||
foreach ($rmaps as $rmap) {
|
||||
$old_dests_existing[] = recipient_map('details', $rmap)['recipient_map_old'];
|
||||
}
|
||||
if (in_array($old_dest_sane, $old_dests_existing) &&
|
||||
recipient_map('details', $id)['recipient_map_old'] != $old_dest_sane) {
|
||||
if ($rmap == $id) { continue; }
|
||||
if (recipient_map('details', $rmap)['recipient_map_old'] == $old_dest_sane) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('recipient_map_entry_exists', htmlspecialchars($old_dest_sane))
|
||||
);
|
||||
continue;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `recipient_maps` SET
|
||||
`old_dest` = :old_dest,
|
||||
`new_dest` = :new_dest,
|
||||
|
@ -410,15 +375,6 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
':active' => $active,
|
||||
':id' => $id
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
|
@ -463,24 +419,14 @@ function recipient_map($_action, $_data = null, $attr = null) {
|
|||
if (!is_numeric($id)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `recipient_maps` WHERE `id`= :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'msg' => array('recipient_map_entry_deleted', htmlspecialchars($old_dest))
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('recipient_map_entry_deleted', htmlspecialchars($id))
|
||||
);
|
||||
return true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -3,9 +3,12 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
global $DOCKER_TIMEOUT;
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: application/json' ));
|
||||
// We are using our mail certificates for dockerapi, the names will not match, the certs are trusted anyway
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, 0);
|
||||
curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, 0);
|
||||
switch($action) {
|
||||
case 'get_id':
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_POST, 0);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||
|
@ -38,7 +41,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
}
|
||||
return false;
|
||||
case 'containers':
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_POST, 0);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||
|
@ -74,7 +77,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
break;
|
||||
case 'info':
|
||||
if (empty($service_name)) {
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/json');
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/json');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_POST, 0);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||
|
@ -82,7 +85,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
else {
|
||||
$container_id = docker('get_id', $service_name);
|
||||
if (ctype_xdigit($container_id)) {
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/json');
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/' . $container_id . '/json');
|
||||
}
|
||||
else {
|
||||
// logger(array('return' => array(
|
||||
|
@ -144,7 +147,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
if (!empty($attr1)) {
|
||||
$container_id = docker('get_id', $service_name);
|
||||
if (ctype_xdigit($container_id) && ctype_alnum($attr1)) {
|
||||
curl_setopt($curl, CURLOPT_URL, 'http://dockerapi:8080/containers/' . $container_id . '/' . $attr1);
|
||||
curl_setopt($curl, CURLOPT_URL, 'https://dockerapi:443/containers/' . $container_id . '/' . $attr1);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
|
||||
if (!empty($attr2)) {
|
||||
|
@ -158,19 +161,19 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
|
|||
if ($response === false) {
|
||||
$err = curl_error($curl);
|
||||
curl_close($curl);
|
||||
logger(array('return' => array(array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
|
||||
'msg' => $err,
|
||||
))));
|
||||
// logger(array('return' => array(array(
|
||||
// 'type' => 'danger',
|
||||
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
|
||||
// 'msg' => $err,
|
||||
// ))));
|
||||
return $err;
|
||||
}
|
||||
else {
|
||||
curl_close($curl);
|
||||
logger(array('return' => array(array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
|
||||
))));
|
||||
// logger(array('return' => array(array(
|
||||
// 'type' => 'success',
|
||||
// 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
|
||||
// ))));
|
||||
if (empty($response)) {
|
||||
return true;
|
||||
}
|
||||
|
|
|
@ -90,7 +90,6 @@ function domain_admin($_action, $_data = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
|
||||
VALUES (:username, :domain, :created, :active)");
|
||||
$stmt->execute(array(
|
||||
|
@ -100,17 +99,6 @@ function domain_admin($_action, $_data = null) {
|
|||
':active' => $active
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
domain_admin('delete', $username);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `admin` (`username`, `password`, `superadmin`, `active`)
|
||||
VALUES (:username, :password_hashed, '0', :active)");
|
||||
$stmt->execute(array(
|
||||
|
@ -119,15 +107,6 @@ function domain_admin($_action, $_data = null) {
|
|||
':active' => $active
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -136,6 +115,10 @@ function domain_admin($_action, $_data = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `da_acl` (`username`) VALUES (:username)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
|
@ -179,15 +162,14 @@ function domain_admin($_action, $_data = null) {
|
|||
$password = $_data['password'];
|
||||
$password2 = $_data['password2'];
|
||||
if (!empty($domains)) {
|
||||
foreach ($domains as $i => &$domain) {
|
||||
foreach ($domains as $domain) {
|
||||
if (!is_valid_domain_name($domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('domain_invalid', htmlspecialchars($domain))
|
||||
);
|
||||
unset($domains[$i]);
|
||||
continue;
|
||||
continue 2;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -209,24 +191,12 @@ function domain_admin($_action, $_data = null) {
|
|||
continue;
|
||||
}
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!empty($domains)) {
|
||||
foreach ($domains as $domain) {
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
|
||||
VALUES (:username_new, :domain, :created, :active)");
|
||||
$stmt->execute(array(
|
||||
|
@ -236,17 +206,7 @@ function domain_admin($_action, $_data = null) {
|
|||
':active' => $active
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!empty($password) && !empty($password2)) {
|
||||
if (!preg_match('/' . $GLOBALS['PASSWD_REGEP'] . '/', $password)) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
@ -265,7 +225,6 @@ function domain_admin($_action, $_data = null) {
|
|||
continue;
|
||||
}
|
||||
$password_hashed = hash_password($password);
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active, `password` = :password_hashed WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':password_hashed' => $password_hashed,
|
||||
|
@ -282,17 +241,7 @@ function domain_admin($_action, $_data = null) {
|
|||
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
|
||||
}
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
else {
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `admin` SET `username` = :username_new, `active` = :active WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username_new' => $username_new,
|
||||
|
@ -308,15 +257,6 @@ function domain_admin($_action, $_data = null) {
|
|||
$stmt->execute(array(':username_new' => $username_new, ':username' => $username));
|
||||
}
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
|
@ -365,22 +305,12 @@ function domain_admin($_action, $_data = null) {
|
|||
return false;
|
||||
}
|
||||
$password_hashed = hash_password($password_new);
|
||||
try {
|
||||
$stmt = $pdo->prepare("UPDATE `admin` SET `password` = :password_hashed WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':password_hashed' => $password_hashed,
|
||||
':username' => $username
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
|
@ -407,7 +337,6 @@ function domain_admin($_action, $_data = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
try {
|
||||
$stmt = $pdo->prepare("DELETE FROM `domain_admins` WHERE `username` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
|
@ -416,15 +345,6 @@ function domain_admin($_action, $_data = null) {
|
|||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
));
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
|
|
|
@ -18,6 +18,17 @@ function last_login($user) {
|
|||
return false;
|
||||
}
|
||||
}
|
||||
function flush_memcached() {
|
||||
try {
|
||||
$m = new Memcached();
|
||||
$m->addServer('memcached', 11211);
|
||||
$m->flush();
|
||||
}
|
||||
catch ( Exception $e ) {
|
||||
// Dunno
|
||||
}
|
||||
}
|
||||
|
||||
function logger($_data = false) {
|
||||
/*
|
||||
logger() will be called as last function
|
||||
|
@ -64,6 +75,8 @@ function logger($_data = false) {
|
|||
$user = 'unauthenticated';
|
||||
$role = 'unauthenticated';
|
||||
}
|
||||
// We cannot log when logs is missing...
|
||||
try {
|
||||
$stmt = $pdo->prepare("INSERT INTO `logs` (`type`, `task`, `msg`, `call`, `user`, `role`, `remote`, `time`) VALUES
|
||||
(:type, :task, :msg, :call, :user, :role, :remote, UNIX_TIMESTAMP())");
|
||||
$stmt->execute(array(
|
||||
|
@ -76,6 +89,10 @@ function logger($_data = false) {
|
|||
':remote' => get_remote_ip()
|
||||
));
|
||||
}
|
||||
catch (Exception $e) {
|
||||
// Do nothing
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
|
@ -260,6 +277,12 @@ function verify_hash($hash, $password) {
|
|||
return true;
|
||||
}
|
||||
}
|
||||
elseif (preg_match('/^{MD5-CRYPT}/i', $hash)) {
|
||||
$hash = preg_replace('/^{MD5-CRYPT}/i', '', $hash);
|
||||
if (password_verify($password, $hash)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function check_login($user, $pass) {
|
||||
|
@ -373,54 +396,6 @@ function check_login($user, $pass) {
|
|||
sleep($_SESSION['ldelay']);
|
||||
return false;
|
||||
}
|
||||
function set_acl() {
|
||||
global $pdo;
|
||||
if (!isset($_SESSION['mailcow_cc_username'])) {
|
||||
return false;
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin' || $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
$stmt = $pdo->query("SHOW COLUMNS FROM `user_acl` WHERE `Field` != 'username';");
|
||||
$acl_all = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
while ($row = array_shift($acl_all)) {
|
||||
$acl['acl'][$row['Field']] = 1;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$username = strtolower(trim($_SESSION['mailcow_cc_username']));
|
||||
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$acl['acl'] = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
unset($acl['acl']['username']);
|
||||
}
|
||||
if (!empty($acl)) {
|
||||
$_SESSION = array_merge($_SESSION, $acl);
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'info',
|
||||
'log' => array(__FUNCTION__),
|
||||
'msg' => 'set_acl_failed'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function get_acl($username) {
|
||||
global $pdo;
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
return false;
|
||||
}
|
||||
$username = strtolower(trim($username));
|
||||
$stmt = $pdo->prepare("SELECT * FROM `user_acl` WHERE `username` = :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$acl = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
unset($acl['username']);
|
||||
if (!empty($acl)) {
|
||||
return $acl;
|
||||
}
|
||||
else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
function formatBytes($size, $precision = 2) {
|
||||
if(!is_numeric($size)) {
|
||||
return "0";
|
||||
|
@ -546,6 +521,7 @@ function update_sogo_static_view() {
|
|||
$stmt = $pdo->query("REPLACE INTO _sogo_static_view SELECT * from sogo_view");
|
||||
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
||||
}
|
||||
flush_memcached();
|
||||
}
|
||||
function edit_user_account($_data) {
|
||||
global $lang;
|
||||
|
@ -1266,7 +1242,7 @@ function get_admin_details() {
|
|||
return false;
|
||||
}
|
||||
$stmt = $pdo->query("SELECT `admin`.`username`, `api`.`active` AS `api_active`, `api`.`api_key`, `api`.`allow_from` FROM `admin`
|
||||
INNER JOIN `api` ON `admin`.`username` = `api`.`username`
|
||||
LEFT OUTER JOIN `api` ON `admin`.`username` = `api`.`username`
|
||||
WHERE `admin`.`superadmin`='1'
|
||||
AND `admin`.`active`='1'");
|
||||
$data = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
|
@ -1433,7 +1409,7 @@ function get_logs($container, $lines = false) {
|
|||
}
|
||||
if ($container == "rspamd-history") {
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/var/lib/rspamd/rspamd.sock');
|
||||
if (!is_numeric($lines)) {
|
||||
list ($from, $to) = explode('-', $lines);
|
||||
curl_setopt($curl, CURLOPT_URL,"http://rspamd/history?from=" . intval($from) . "&to=" . intval($to));
|
||||
|
|
|
@ -3,6 +3,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
global $pdo;
|
||||
global $redis;
|
||||
global $lang;
|
||||
global $MAILBOX_DEFAULT_ATTRIBUTES;
|
||||
$_data_log = $_data;
|
||||
!isset($_data_log['password']) ?: $_data_log['password'] = '*';
|
||||
!isset($_data_log['password2']) ?: $_data_log['password2'] = '*';
|
||||
|
@ -139,7 +140,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$stmt = $pdo->prepare("UPDATE `sieve_filters` SET `script_name` = 'inactive' WHERE `username` = :username AND `filter_type` = :filter_type");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
':filter_type' => $filter_type
|
||||
));
|
||||
}
|
||||
|
@ -637,7 +637,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
foreach ($alias_domains as $i => &$alias_domain) {
|
||||
foreach ($alias_domains as $i => $alias_domain) {
|
||||
$alias_domain = idn_to_ascii(strtolower(trim($alias_domain)));
|
||||
if (!is_valid_domain_name($alias_domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
@ -680,7 +680,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `alias_domain` (`alias_domain`, `target_domain`, `active`)
|
||||
VALUES (:alias_domain, :target_domain, :active)");
|
||||
$stmt->execute(array(
|
||||
|
@ -704,6 +703,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => array('aliasd_added', htmlspecialchars($alias_domain))
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'mailbox':
|
||||
$local_part = strtolower(trim($_data['local_part']));
|
||||
|
@ -735,6 +735,12 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$active = intval($_data['active']);
|
||||
$quota_b = ($quota_m * 1048576);
|
||||
$maildir = $domain . "/" . $local_part . "/";
|
||||
$mailbox_attrs = json_encode(
|
||||
array(
|
||||
'force_pw_update' => strval(intval($MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'])),
|
||||
'tls_enforce_in' => strval(intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in'])),
|
||||
'tls_enforce_out' => strval(intval($MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out'])))
|
||||
);
|
||||
if (!is_valid_domain_name($domain)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -868,7 +874,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `mailbox` (`username`, `password`, `name`, `maildir`, `quota`, `local_part`, `domain`, `attributes`, `active`)
|
||||
VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, '{\"force_pw_update\": \"0\", \"tls_enforce_in\": \"0\", \"tls_enforce_out\": \"0\"}', :active)");
|
||||
VALUES (:username, :password_hashed, :name, :maildir, :quota_b, :local_part, :domain, :mailbox_attrs, :active)");
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':password_hashed' => $password_hashed,
|
||||
|
@ -877,6 +883,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
':quota_b' => $quota_b,
|
||||
':local_part' => $local_part,
|
||||
':domain' => $domain,
|
||||
':mailbox_attrs' => $mailbox_attrs,
|
||||
':active' => $active
|
||||
));
|
||||
$stmt = $pdo->prepare("INSERT INTO `quota2` (`username`, `bytes`, `messages`)
|
||||
|
@ -1453,14 +1460,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
}
|
||||
break;
|
||||
case 'filter':
|
||||
$sieve = new Sieve\SieveParser();
|
||||
if (!is_array($_data['id'])) {
|
||||
$ids = array();
|
||||
$ids[] = $_data['id'];
|
||||
}
|
||||
else {
|
||||
$ids = $_data['id'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['filters']) || $_SESSION['acl']['filters'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -1469,6 +1468,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
$sieve = new Sieve\SieveParser();
|
||||
if (!is_array($_data['id'])) {
|
||||
$ids = array();
|
||||
$ids[] = $_data['id'];
|
||||
}
|
||||
else {
|
||||
$ids = $_data['id'];
|
||||
}
|
||||
foreach ($ids as $id) {
|
||||
$is_now = mailbox('get', 'filter_details', $id);
|
||||
if (!empty($is_now)) {
|
||||
|
@ -2777,6 +2784,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
`mailbox`.`active` AS `active_int`,
|
||||
CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
|
||||
`mailbox`.`domain`,
|
||||
`mailbox`.`maildir`,
|
||||
`mailbox`.`quota`,
|
||||
`quota2`.`bytes`,
|
||||
`attributes`,
|
||||
|
@ -2807,6 +2815,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$mailboxdata['active'] = $row['active'];
|
||||
$mailboxdata['active_int'] = $row['active_int'];
|
||||
$mailboxdata['domain'] = $row['domain'];
|
||||
$mailboxdata['maildir'] = $row['maildir'];
|
||||
$mailboxdata['quota'] = $row['quota'];
|
||||
$mailboxdata['attributes'] = json_decode($row['attributes'], true);
|
||||
$mailboxdata['quota_used'] = intval($row['bytes']);
|
||||
|
@ -3055,6 +3064,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
$exec_fields = array('cmd' => 'maildir_cleanup', 'maildir' => $domain);
|
||||
$maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
|
||||
if ($maildir_gc['type'] != 'success') {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'warning',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg']
|
||||
);
|
||||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => $domain,
|
||||
|
@ -3079,17 +3097,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$stmt->execute(array(
|
||||
':domain' => '%@'.$domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain");
|
||||
$stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` LIKE :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => '%@'.$domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain");
|
||||
$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` LIKE :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => '%@'.$domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
|
||||
$stmt->execute(array(
|
||||
':domain' => '%@'.$domain,
|
||||
':domain' => $domain,
|
||||
));
|
||||
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain");
|
||||
$stmt->execute(array(
|
||||
|
@ -3228,6 +3246,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
);
|
||||
continue;
|
||||
}
|
||||
$maildir = mailbox('get', 'mailbox_details', $username)['maildir'];
|
||||
$exec_fields = array('cmd' => 'maildir_cleanup', 'maildir' => $maildir);
|
||||
$maildir_gc = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
|
||||
if ($maildir_gc['type'] != 'success') {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'warning',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'Could not move maildir to garbage collector: ' . $maildir_gc['msg']
|
||||
);
|
||||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
|
||||
$stmt->execute(array(
|
||||
':username' => $username
|
||||
|
|
|
@ -6,6 +6,14 @@ function policy($_action, $_scope, $_data = null) {
|
|||
$_data_log = $_data;
|
||||
switch ($_action) {
|
||||
case 'add':
|
||||
if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
switch ($_scope) {
|
||||
case 'domain':
|
||||
$object = $_data['domain'];
|
||||
|
@ -90,14 +98,6 @@ function policy($_action, $_scope, $_data = null) {
|
|||
);
|
||||
return false;
|
||||
}
|
||||
if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($_data['object_list'] == "bl") {
|
||||
$object_list = "blacklist_from";
|
||||
}
|
||||
|
@ -151,6 +151,14 @@ function policy($_action, $_scope, $_data = null) {
|
|||
}
|
||||
break;
|
||||
case 'delete':
|
||||
if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
switch ($_scope) {
|
||||
case 'domain':
|
||||
(array)$prefids = $_data['prefid'];
|
||||
|
@ -215,14 +223,6 @@ function policy($_action, $_scope, $_data = null) {
|
|||
else {
|
||||
$prefids = $_data['prefid'];
|
||||
}
|
||||
if (!isset($_SESSION['acl']['spam_policy']) || $_SESSION['acl']['spam_policy'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
foreach ($prefids as $prefid) {
|
||||
if (!is_numeric($prefid)) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
|
@ -221,7 +221,7 @@ function quarantine($_action, $_data = null) {
|
|||
continue;
|
||||
}
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/var/lib/rspamd/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
|
||||
|
@ -243,7 +243,7 @@ function quarantine($_action, $_data = null) {
|
|||
}
|
||||
curl_close($curl);
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/var/lib/rspamd/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
|
||||
curl_setopt($curl, CURLOPT_POST, 1);
|
||||
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
|
||||
|
@ -255,11 +255,10 @@ function quarantine($_action, $_data = null) {
|
|||
$response = json_decode($response, true);
|
||||
if (isset($response['error'])) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'type' => 'warning',
|
||||
'log' => array(__FUNCTION__),
|
||||
'msg' => array('fuzzy_learn_error', $response['error'])
|
||||
);
|
||||
continue;
|
||||
}
|
||||
curl_close($curl);
|
||||
try {
|
||||
|
@ -279,7 +278,7 @@ function quarantine($_action, $_data = null) {
|
|||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__),
|
||||
'msg' => 'qlearn_spam'
|
||||
'msg' => array('qlearn_spam', $id)
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
@ -288,7 +287,7 @@ function quarantine($_action, $_data = null) {
|
|||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__),
|
||||
'msg' => array('spam_learn_error', 'curl error ' . curl_errno($curl))
|
||||
'msg' => array('spam_learn_error', 'Curl: ' . curl_strerror(curl_errno($curl)))
|
||||
);
|
||||
continue;
|
||||
}
|
||||
|
@ -301,12 +300,12 @@ function quarantine($_action, $_data = null) {
|
|||
continue;
|
||||
}
|
||||
else {
|
||||
curl_close($curl);
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__),
|
||||
'msg' => array('spam_learn_error', 'curl error ' . curl_errno($curl))
|
||||
'msg' => array('spam_learn_error', 'Curl: ' . curl_strerror(curl_errno($curl)))
|
||||
);
|
||||
curl_close($curl);
|
||||
continue;
|
||||
}
|
||||
curl_close($curl);
|
||||
|
|
|
@ -5,6 +5,14 @@ function ratelimit($_action, $_scope, $_data = null) {
|
|||
$_data_log = $_data;
|
||||
switch ($_action) {
|
||||
case 'edit':
|
||||
if (!isset($_SESSION['acl']['ratelimit']) || $_SESSION['acl']['ratelimit'] != "1" ) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
switch ($_scope) {
|
||||
case 'domain':
|
||||
if (!is_array($_data['object'])) {
|
||||
|
|
|
@ -0,0 +1,157 @@
|
|||
<?php
|
||||
function tls_policy_maps($_action, $_data = null, $attr = null) {
|
||||
global $pdo;
|
||||
global $lang;
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
return false;
|
||||
}
|
||||
switch ($_action) {
|
||||
case 'add':
|
||||
$dest = idn_to_ascii(trim($_data['dest']));
|
||||
$policy = strtolower(trim($_data['policy']));
|
||||
$parameters = (isset($_data['parameters']) && !empty($_data['parameters'])) ? $_data['parameters'] : '';
|
||||
if (!empty($parameters)) {
|
||||
foreach (explode(' ', $parameters) as $parameter) {
|
||||
if (!preg_match('/(.+)\=(.+)/i', $parameter)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => 'tls_policy_map_parameter_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$active = intval($_data['active']);
|
||||
$tls_policy_maps = tls_policy_maps('get');
|
||||
foreach ($tls_policy_maps as $tls_policy_map) {
|
||||
if (tls_policy_maps('details', $tls_policy_map)['dest'] == $dest) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('tls_policy_map_entry_exists', htmlspecialchars($dest))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("INSERT INTO `tls_policy_override` (`dest`, `policy`, `parameters`, `active`) VALUES
|
||||
(:dest, :policy, :parameters, :active)");
|
||||
$stmt->execute(array(
|
||||
':dest' => $dest,
|
||||
':policy' => $policy,
|
||||
':parameters' => $parameters,
|
||||
':active' => $active
|
||||
));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('tls_policy_map_entry_saved', htmlspecialchars($dest))
|
||||
);
|
||||
break;
|
||||
case 'edit':
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
$is_now = tls_policy_maps('details', $id);
|
||||
if (!empty($is_now)) {
|
||||
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active_int'];
|
||||
$dest = (!empty($_data['dest'])) ? $_data['dest'] : $is_now['dest'];
|
||||
$policy = (!empty($_data['policy'])) ? $_data['policy'] : $is_now['policy'];
|
||||
$parameters = (isset($_data['parameters'])) ? $_data['parameters'] : $is_now['parameters'];
|
||||
}
|
||||
else {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
continue;
|
||||
}
|
||||
if (!empty($parameters)) {
|
||||
foreach (explode(' ', $parameters) as $parameter) {
|
||||
if (!preg_match('/(.+)\=(.+)/i', $parameter)) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => 'tls_policy_map_parameter_invalid'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
$tls_policy_maps = tls_policy_maps('get');
|
||||
foreach ($tls_policy_maps as $tls_policy_map) {
|
||||
if ($tls_policy_map == $id) { continue; }
|
||||
if (tls_policy_maps('details', $tls_policy_map)['dest'] == $dest) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('recipient_map_entry_exists', htmlspecialchars($dest))
|
||||
);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
$stmt = $pdo->prepare("UPDATE `tls_policy_override` SET
|
||||
`dest` = :dest,
|
||||
`policy` = :policy,
|
||||
`parameters` = :parameters,
|
||||
`active` = :active
|
||||
WHERE `id`= :id");
|
||||
$stmt->execute(array(
|
||||
':dest' => $dest,
|
||||
':policy' => $policy,
|
||||
':parameters' => $parameters,
|
||||
':active' => $active,
|
||||
':id' => $id
|
||||
));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('tls_policy_map_entry_saved', htmlspecialchars($dest))
|
||||
);
|
||||
}
|
||||
break;
|
||||
case 'details':
|
||||
$mapdata = array();
|
||||
$id = intval($_data);
|
||||
$stmt = $pdo->prepare("SELECT `id`,
|
||||
`dest`,
|
||||
`policy`,
|
||||
`parameters`,
|
||||
`active` AS `active_int`,
|
||||
CASE `active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
|
||||
`created`,
|
||||
`modified` FROM `tls_policy_override`
|
||||
WHERE `id` = :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$mapdata = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
return $mapdata;
|
||||
break;
|
||||
case 'get':
|
||||
$mapdata = array();
|
||||
$all_items = array();
|
||||
$id = intval($_data);
|
||||
$stmt = $pdo->query("SELECT `id` FROM `tls_policy_override`");
|
||||
$all_items = $stmt->fetchAll(PDO::FETCH_ASSOC);
|
||||
foreach ($all_items as $i) {
|
||||
$mapdata[] = $i['id'];
|
||||
}
|
||||
$all_items = null;
|
||||
return $mapdata;
|
||||
break;
|
||||
case 'delete':
|
||||
$ids = (array)$_data['id'];
|
||||
foreach ($ids as $id) {
|
||||
if (!is_numeric($id)) {
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare("DELETE FROM `tls_policy_override` WHERE `id`= :id");
|
||||
$stmt->execute(array(':id' => $id));
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data, $_attr),
|
||||
'msg' => array('tls_policy_map_entry_deleted', htmlspecialchars($id))
|
||||
);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -27,12 +27,12 @@
|
|||
<link rel="stylesheet" href="/css/animate.min.css">
|
||||
<link rel="stylesheet" href="/css/numberedtextarea.min.css">
|
||||
<link rel="stylesheet" href="/css/jquery.jqplot.min.css">
|
||||
<?= (preg_match("/mailbox.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/mailbox.css">' : null; ?>
|
||||
<?= (preg_match("/admin.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/admin.css">' : null; ?>
|
||||
<?= (preg_match("/user.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/user.css">' : null; ?>
|
||||
<?= (preg_match("/edit.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/edit.css">' : null; ?>
|
||||
<?= (preg_match("/quarantine.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/quarantine.css">' : null; ?>
|
||||
<?= (preg_match("/debug.php/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/debug.css">' : null; ?>
|
||||
<?= (preg_match("/mailbox/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/mailbox.css">' : null; ?>
|
||||
<?= (preg_match("/admin/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/admin.css">' : null; ?>
|
||||
<?= (preg_match("/user/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/user.css">' : null; ?>
|
||||
<?= (preg_match("/edit/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/edit.css">' : null; ?>
|
||||
<?= (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/quarantine.css">' : null; ?>
|
||||
<?= (preg_match("/debug/i", $_SERVER['REQUEST_URI'])) ? '<link rel="stylesheet" href="/css/debug.css">' : null; ?>
|
||||
<link rel="shortcut icon" href="/favicon.png" type="image/png">
|
||||
<link rel="icon" href="/favicon.png" type="image/png">
|
||||
</head>
|
||||
|
@ -76,18 +76,18 @@
|
|||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
?>
|
||||
<li<?= (preg_match("/admin/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/admin.php"><?= $lang['header']['administration']; ?></a></li>
|
||||
<li<?= (preg_match("/debug/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/debug.php"><?= $lang['header']['debug']; ?></a></li>
|
||||
<li<?= (preg_match("/admin/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/admin"><?= $lang['header']['administration']; ?></a></li>
|
||||
<li<?= (preg_match("/debug/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/debug"><?= $lang['header']['debug']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin' || $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
?>
|
||||
<li<?= (preg_match("/mailbox/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/mailbox.php"><?= $lang['header']['mailboxes']; ?></a></li>
|
||||
<li<?= (preg_match("/mailbox/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/mailbox"><?= $lang['header']['mailboxes']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
?>
|
||||
<li<?= (preg_match("/user/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/user.php"><?= $lang['header']['user_settings']; ?></a></li>
|
||||
<li<?= (preg_match("/user/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/user"><?= $lang['header']['user_settings']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
}
|
||||
|
@ -97,7 +97,7 @@
|
|||
<?php
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
?>
|
||||
<li<?= (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantine.php"><span class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantine']; ?></a></li>
|
||||
<li<?= (preg_match("/quarantine/i", $_SERVER['REQUEST_URI'])) ? ' class="active"' : ''; ?>><a href="/quarantine"><span class="glyphicon glyphicon-briefcase"></span> <?= $lang['header']['quarantine']; ?></a></li>
|
||||
<?php
|
||||
}
|
||||
if ($_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
|
|
|
@ -3,7 +3,7 @@ function init_db_schema() {
|
|||
try {
|
||||
global $pdo;
|
||||
|
||||
$db_version = "19082018_1004";
|
||||
$db_version = "03102018_1502";
|
||||
|
||||
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
|
||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
||||
|
@ -192,6 +192,26 @@ function init_db_schema() {
|
|||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"tls_policy_override" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
"dest" => "VARCHAR(255) NOT NULL",
|
||||
"policy" => "ENUM('none', 'may', 'encrypt', 'dane', 'dane-only', 'fingerprint', 'verify', 'secure') NOT NULL",
|
||||
"parameters" => "VARCHAR(255) DEFAULT ''",
|
||||
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
|
||||
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
|
||||
"active" => "TINYINT(1) NOT NULL DEFAULT '1'"
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("id")
|
||||
),
|
||||
"unique" => array(
|
||||
"dest" => array("dest")
|
||||
),
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"quarantine" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
|
@ -280,10 +300,7 @@ function init_db_schema() {
|
|||
"delimiter_action" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"eas_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"filters" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"recipient_maps" => "TINYINT(1) NOT NULL DEFAULT '0'",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
|
@ -417,6 +434,32 @@ function init_db_schema() {
|
|||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"da_acl" => array(
|
||||
"cols" => array(
|
||||
"username" => "VARCHAR(255) NOT NULL",
|
||||
"syncjobs" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"quarantine" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"login_as" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"bcc_maps" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"filters" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"ratelimit" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
"spam_policy" => "TINYINT(1) NOT NULL DEFAULT '1'",
|
||||
),
|
||||
"keys" => array(
|
||||
"primary" => array(
|
||||
"" => array("username")
|
||||
),
|
||||
"fkey" => array(
|
||||
"fk_domain_admin_acl" => array(
|
||||
"col" => "username",
|
||||
"ref" => "domain_admins.username",
|
||||
"delete" => "CASCADE",
|
||||
"update" => "NO ACTION"
|
||||
)
|
||||
)
|
||||
),
|
||||
"attr" => "ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 ROW_FORMAT=DYNAMIC"
|
||||
),
|
||||
"imapsync" => array(
|
||||
"cols" => array(
|
||||
"id" => "INT NOT NULL AUTO_INCREMENT",
|
||||
|
@ -950,8 +993,9 @@ DELIMITER ;';
|
|||
'msg' => 'db_init_complete'
|
||||
);
|
||||
|
||||
// Fix user_acl
|
||||
// Fix ACL
|
||||
$stmt = $pdo->query("INSERT INTO `user_acl` (`username`) SELECT `username` FROM `mailbox` WHERE `kind` = '' AND NOT EXISTS (SELECT `username` FROM `user_acl`);");
|
||||
$stmt = $pdo->query("INSERT INTO `da_acl` (`username`) SELECT DISTINCT `username` FROM `domain_admins` WHERE `username` != 'admin' AND NOT EXISTS (SELECT `username` FROM `da_acl`);");
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
|
@ -35,7 +35,7 @@ $hrs = floor($mins / 60);
|
|||
$mins -= $hrs * 60;
|
||||
$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins);
|
||||
|
||||
$dsn = $database_type . ":host=" . $database_host . ";dbname=" . $database_name;
|
||||
$dsn = $database_type . ":unix_socket=" . $database_sock . ";dbname=" . $database_name;
|
||||
$opt = [
|
||||
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
|
||||
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
|
||||
|
@ -46,12 +46,22 @@ try {
|
|||
$pdo = new PDO($dsn, $database_user, $database_pass, $opt);
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
// Stop when SQL connection fails
|
||||
?>
|
||||
<center style='font-family: "Lucida Sans Unicode", "Lucida Grande", Verdana, Arial, Helvetica, 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
|
||||
exit;
|
||||
}
|
||||
// Stop when dockerapi is not available
|
||||
if (fsockopen("tcp://dockerapi", 443, $errno, $errstr) === false) {
|
||||
?>
|
||||
<center style='font-family:sans-serif;'>Connection to dockerapi container failed.<br /><br />The following error was reported:<br/><?=$errno;?> - <?=$errstr;?></center>
|
||||
<?php
|
||||
exit;
|
||||
}
|
||||
|
||||
function pdo_exception_handler($e) {
|
||||
print_r($e);
|
||||
if ($e instanceof PDOException) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
|
@ -124,6 +134,7 @@ if (isset($_GET['lang']) && in_array($_GET['lang'], $AVAILABLE_LANGUAGES)) {
|
|||
require_once $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.en.php';
|
||||
include $_SERVER['DOCUMENT_ROOT'] . '/lang/lang.'.$_SESSION['mailcow_locale'].'.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.acl.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.mailbox.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.customize.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.address_rewriting.inc.php';
|
||||
|
@ -135,12 +146,14 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fwdhost.inc.php';
|
|||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.ratelimit.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.relayhost.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.rsettings.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.tls_policy_maps.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.fail2ban.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/functions.docker.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/init_db.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.inc.php';
|
||||
init_db_schema();
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
set_acl();
|
||||
acl('to_session');
|
||||
}
|
||||
$UI_TEXTS = customize('get', 'ui_texts');
|
||||
|
||||
|
|
|
@ -40,7 +40,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
|
|||
}
|
||||
}
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == "admin") {
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['acl']['login_as'] == "1") {
|
||||
if (isset($_GET["duallogin"])) {
|
||||
$duallogin = html_entity_decode(rawurldecode($_GET["duallogin"]));
|
||||
if (filter_var($duallogin, FILTER_VALIDATE_EMAIL)) {
|
||||
|
|
|
@ -9,6 +9,7 @@ This file will be reset on upgrades.
|
|||
|
||||
// SQL database connection variables
|
||||
$database_type = 'mysql';
|
||||
$database_sock = '/var/run/mysqld/mysqld.sock';
|
||||
$database_host = 'mysql';
|
||||
$database_user = getenv('DBUSER');
|
||||
$database_pass = getenv('DBPASS');
|
||||
|
@ -122,3 +123,12 @@ $DOCKER_TIMEOUT = 60;
|
|||
|
||||
// Anonymize IPs logged via UI
|
||||
$ANONYMIZE_IPS = true;
|
||||
|
||||
// Force incoming TLS for new mailboxes by default
|
||||
$MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_in'] = false;
|
||||
|
||||
// Force outgoing TLS for new mailboxes by default
|
||||
$MAILBOX_DEFAULT_ATTRIBUTES['tls_enforce_out'] = false;
|
||||
|
||||
// Force password change on next login (only allows login to mailcow UI)
|
||||
$MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false;
|
||||
|
|
|
@ -2,15 +2,15 @@
|
|||
require_once 'inc/prerequisites.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin.php');
|
||||
header('Location: /admin');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'domainadmin') {
|
||||
header('Location: /mailbox.php');
|
||||
header('Location: /mailbox');
|
||||
exit();
|
||||
}
|
||||
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
|
||||
header('Location: /user.php');
|
||||
header('Location: /user');
|
||||
exit();
|
||||
}
|
||||
require_once 'inc/header.inc.php';
|
||||
|
@ -107,6 +107,6 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
</div>
|
||||
</div>
|
||||
</div><!-- /.container -->
|
||||
<script src="js/index.js"></script>
|
||||
<script src="/js/index.js"></script>
|
||||
<?php
|
||||
require_once 'inc/footer.inc.php';
|
||||
|
|
|
@ -13,15 +13,19 @@ jQuery(function($){
|
|||
e.preventDefault();
|
||||
$('#duplicate_dkim_arrow').toggleClass("animation");
|
||||
});
|
||||
$("#api_legend").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$('#api_arrow').toggleClass("animation");
|
||||
});
|
||||
$("#rspamd_preset_1").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_1);
|
||||
$("form[data-id=rsetting]").find("#content").val('priority = 10;\nauthenticated = yes;\napply "default" {\n symbols_enabled = ["DKIM_SIGNED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];\n}');
|
||||
$("form[data-id=rsetting]").find("#adminRspamdSettingsDesc").val(lang.rsettings_preset_1);
|
||||
$("form[data-id=rsetting]").find("#adminRspamdSettingsContent").val('priority = 10;\nauthenticated = yes;\napply "default" {\n symbols_enabled = ["DKIM_SIGNED", "RATELIMIT_UPDATE", "RATELIMIT_CHECK", "DYN_RL_CHECK", "HISTORY_SAVE", "MILTER_HEADERS", "ARC_SIGNED"];\n}');
|
||||
});
|
||||
$("#rspamd_preset_2").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
$("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_2);
|
||||
$("form[data-id=rsetting]").find("#content").val('priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;');
|
||||
$("form[data-id=rsetting]").find("#adminRspamdSettingsDesc").val(lang.rsettings_preset_2);
|
||||
$("form[data-id=rsetting]").find("#adminRspamdSettingsContent").val('priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;');
|
||||
});
|
||||
$("#dkim_missing_keys").on('click', function(e) {
|
||||
e.preventDefault();
|
||||
|
@ -117,15 +121,15 @@ jQuery(function($){
|
|||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-toggle="modal" id="miau" data-target="#testRelayhostModal" data-relayhost-id="' + encodeURI(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-stats"></span> Test</a>' +
|
||||
'<a href="/edit.php?relayhost=' + encodeURI(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-rlshost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/relayhost/' + encodeURI(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-rlshost" data-api-url="delete/relayhost" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item.id + '" />';
|
||||
});
|
||||
} else if (table == 'forwardinghoststable') {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" id="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-fwdhost" data-api-url="delete/fwdhost" data-item="' + encodeURI(item.host) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
if (item.keep_spam == "yes") {
|
||||
item.keep_spam = lang.no;
|
||||
|
@ -140,8 +144,8 @@ jQuery(function($){
|
|||
item.selected_domains = escapeHtml(item.selected_domains.toString().replace(/,/g, " "));
|
||||
item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?domainadmin=' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/domainadmin/' + encodeURI(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-domain-admin" data-api-url="delete/domain-admin" data-item="' + encodeURI(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
|
||||
'</div>';
|
||||
});
|
||||
|
|
|
@ -5,9 +5,9 @@ $(document).ready(function() {
|
|||
} else {
|
||||
var parent_btn_grp = $(elem).parentsUntil(".btn-group").parent();
|
||||
if (parent_btn_grp.hasClass('btn-group')) {
|
||||
parent_btn_grp.replaceWith('<button class="btn btn-default btn-sm" disabled>' + loading_text + '</a>');
|
||||
parent_btn_grp.replaceWith('<button class="btn btn-default btn-sm" disabled>' + lang_footer.loading + '</a>');
|
||||
}
|
||||
$(elem).text(loading_text);
|
||||
$(elem).text(lang_footer.loading);
|
||||
$(elem).attr('data-submitted', '1');
|
||||
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
|
||||
$(document).on("keydown", disableF5);
|
||||
|
@ -71,7 +71,7 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
// General API edit actions
|
||||
$(document).on('click', '#edit_selected', function(e) {
|
||||
$(document).on('click', "[data-action='edit_selected']", function(e) {
|
||||
e.preventDefault();
|
||||
var id = $(this).data('id');
|
||||
var api_url = $(this).data('api-url');
|
||||
|
@ -159,7 +159,7 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
// General API add actions
|
||||
$(document).on('click', '#add_item', function(e) {
|
||||
$(document).on('click', "[data-action='add_item']", function(e) {
|
||||
e.preventDefault();
|
||||
var id = $(this).data('id');
|
||||
var api_url = $(this).data('api-url');
|
||||
|
@ -252,7 +252,7 @@ $(document).ready(function() {
|
|||
});
|
||||
|
||||
// General API delete actions
|
||||
$(document).on('click', '#delete_selected', function(e) {
|
||||
$(document).on('click', "[data-action='delete_selected']", function(e) {
|
||||
e.preventDefault();
|
||||
var id = $(this).data('id');
|
||||
// If clicked element #delete_selected has data-item attribute, it is added to "items"
|
||||
|
@ -283,6 +283,7 @@ $(document).ready(function() {
|
|||
keyboard: false
|
||||
})
|
||||
.one('click', '#IsConfirmed', function(e) {
|
||||
if (is_active($('#IsConfirmed'))) { return false; }
|
||||
$.ajax({
|
||||
type: "POST",
|
||||
dataType: "json",
|
||||
|
|
|
@ -10,37 +10,43 @@ $(document).ready(function() {
|
|||
});
|
||||
$("#disable_sender_check").click(function( event ) {
|
||||
if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) {
|
||||
$('#sender_acl').prop('disabled', true);
|
||||
$('#sender_acl').selectpicker('refresh');
|
||||
$('#editSelectSenderACL').prop('disabled', true);
|
||||
$('#editSelectSenderACL').selectpicker('refresh');
|
||||
}
|
||||
else {
|
||||
$('#sender_acl').prop('disabled', false);
|
||||
$('#sender_acl').selectpicker('refresh');
|
||||
$('#editSelectSenderACL').prop('disabled', false);
|
||||
$('#editSelectSenderACL').selectpicker('refresh');
|
||||
}
|
||||
});
|
||||
if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
|
||||
$('#textarea_alias_goto').prop('disabled', true);
|
||||
}
|
||||
|
||||
$("#script_data").numberedtextarea({allowTabChar: true});
|
||||
|
||||
$("#mailbox-password-warning-close").click(function( event ) {
|
||||
$('#mailbox-passwd-hidden-info').addClass('hidden');
|
||||
$('#mailbox-passwd-form-groups').removeClass('hidden');
|
||||
});
|
||||
if ($("#multiple_bookings_select").val() == "custom") {
|
||||
});
|
||||
if ($("#editSelectMultipleBookings").val() == "custom") {
|
||||
$("#multiple_bookings_custom_div").show();
|
||||
$("#multiple_bookings").val($("#multiple_bookings_custom").val());
|
||||
$('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
|
||||
}
|
||||
$("#multiple_bookings_select").change(function() {
|
||||
$("#multiple_bookings").val($("#multiple_bookings_select").val());
|
||||
if ($("#multiple_bookings").val() == "custom") {
|
||||
$("#editSelectMultipleBookings").change(function() {
|
||||
$('input[name=multiple_bookings]').val($("#editSelectMultipleBookings").val());
|
||||
if ($('input[name=multiple_bookings]').val() == "custom") {
|
||||
$("#multiple_bookings_custom_div").show();
|
||||
}
|
||||
else {
|
||||
$("#multiple_bookings_custom_div").hide();
|
||||
}
|
||||
});
|
||||
if ($("#sender_acl option[value='\*']:selected").length > 0){
|
||||
if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
|
||||
$("#sender_acl_disabled").show();
|
||||
}
|
||||
$('#sender_acl').change(function() {
|
||||
if ($("#sender_acl option[value='\*']:selected").length > 0){
|
||||
$('#editSelectSenderACL').change(function() {
|
||||
if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
|
||||
$("#sender_acl_disabled").show();
|
||||
}
|
||||
else {
|
||||
|
@ -48,7 +54,7 @@ $('#sender_acl').change(function() {
|
|||
}
|
||||
});
|
||||
$("#multiple_bookings_custom").bind("change keypress keyup blur", function() {
|
||||
$("#multiple_bookings").val($("#multiple_bookings_custom").val());
|
||||
$('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
|
||||
});
|
||||
jQuery(function($){
|
||||
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
|
||||
|
@ -61,10 +67,10 @@ jQuery(function($){
|
|||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang.spamfilter_table_rule},
|
||||
{"sorted": true,"name":"value","title":lang_user.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"empty": lang_user.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/policy_wl_domain/' + table_for_domain,
|
||||
|
@ -78,7 +84,7 @@ jQuery(function($){
|
|||
item.chkbox = '<input type="checkbox" data-id="policy_wl_domain" name="multi_select" value="' + item.prefid + '" />';
|
||||
}
|
||||
else {
|
||||
item.chkbox = '<input type="checkbox" disabled title="' + lang.spamfilter_table_domain_policy + '" />';
|
||||
item.chkbox = '<input type="checkbox" disabled title="' + lang_user.spamfilter_table_domain_policy + '" />';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
@ -98,10 +104,10 @@ jQuery(function($){
|
|||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"40px","width":"40px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"name":"prefid","style":{"maxWidth":"40px","width":"40px"},"title":"ID","filterable": false,"sortable": false},
|
||||
{"sorted": true,"name":"value","title":lang.spamfilter_table_rule},
|
||||
{"sorted": true,"name":"value","title":lang_user.spamfilter_table_rule},
|
||||
{"name":"object","title":"Scope"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"empty": lang_user.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/policy_bl_domain/' + table_for_domain,
|
||||
|
@ -115,7 +121,7 @@ jQuery(function($){
|
|||
item.chkbox = '<input type="checkbox" data-id="policy_bl_domain" name="multi_select" value="' + item.prefid + '" />';
|
||||
}
|
||||
else {
|
||||
item.chkbox = '<input type="checkbox" disabled tooltip="' + lang.spamfilter_table_domain_policy + '" />';
|
||||
item.chkbox = '<input type="checkbox" disabled tooltip="' + lang_user.spamfilter_table_domain_policy + '" />';
|
||||
}
|
||||
});
|
||||
}
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
$(document).ready(function() {
|
||||
acl_data = JSON.parse(acl);
|
||||
FooTable.domainFilter = FooTable.Filtering.extend({
|
||||
construct: function(instance){
|
||||
this._super(instance);
|
||||
var domain_list = [];
|
||||
$.ajax({
|
||||
dataType: 'json',
|
||||
'async': false,
|
||||
url: '/api/v1/get/domain/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
|
@ -82,11 +82,12 @@ $(document).ready(function() {
|
|||
|
||||
$(".generate_password").click(function( event ) {
|
||||
event.preventDefault();
|
||||
$('[data-hibp]').trigger('input');
|
||||
var random_passwd = Math.random().toString(36).slice(-8)
|
||||
$('#password').prop('type', 'text');
|
||||
$('#password').val(random_passwd);
|
||||
$('#password2').prop('type', 'text');
|
||||
$('#password2').val(random_passwd);
|
||||
$(this).closest("form").find("input[name='password']").prop('type', 'text');
|
||||
$(this).closest("form").find("input[name='password2']").prop('type', 'text');
|
||||
$(this).closest("form").find("input[name='password']").val(random_passwd);
|
||||
$(this).closest("form").find("input[name='password2']").val(random_passwd);
|
||||
});
|
||||
|
||||
$(".goto_checkbox").click(function( event ) {
|
||||
|
@ -233,6 +234,13 @@ jQuery(function($){
|
|||
eval(draw_table + '()');
|
||||
});
|
||||
function table_mailbox_ready(ft, name) {
|
||||
if(is_dual) {
|
||||
$('.login_as').data("toggle", "tooltip")
|
||||
.attr("disabled", true)
|
||||
.removeAttr("href")
|
||||
.attr("title", "Dual login cannot be used twice")
|
||||
.tooltip();
|
||||
}
|
||||
heading = ft.$el.parents('.tab-pane').find('.panel-heading')
|
||||
var ft_paging = ft.use(FooTable.Paging)
|
||||
$(heading).children('.table-lines').text(function(){
|
||||
|
@ -264,10 +272,10 @@ jQuery(function($){
|
|||
},
|
||||
},
|
||||
{"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm","style":{"width":"125px"}},
|
||||
{"name":"rl","title":"RL","breakpoints":"xs sm md","style":{"width":"125px"}},
|
||||
{"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm"},
|
||||
{"name":"rl","title":"RL","breakpoints":"xs sm md","style":{"maxWidth":"100px","width":"100px"}},
|
||||
{"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm md"},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
|
||||
],
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
|
@ -292,11 +300,11 @@ jQuery(function($){
|
|||
item.chkbox = '<input type="checkbox" data-id="domain" name="multi_select" value="' + encodeURIComponent(item.domain_name) + '" />';
|
||||
item.action = '<div class="btn-group">';
|
||||
if (role == "admin") {
|
||||
item.action += '<a href="/edit.php?domain=' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-domain" data-api-url="delete/domain" data-item="' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>';
|
||||
item.action += '<a href="/edit/domain/' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-domain" data-api-url="delete/domain" data-item="' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>';
|
||||
}
|
||||
else {
|
||||
item.action += '<a href="/edit.php?domain=' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>';
|
||||
item.action += '<a href="/edit/domain/' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>';
|
||||
}
|
||||
item.action += '<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.domain_name) + '"><span class="glyphicon glyphicon-question-sign"></span> DNS</a></div>';
|
||||
});
|
||||
|
@ -345,6 +353,8 @@ jQuery(function($){
|
|||
},
|
||||
},
|
||||
{"name":"spam_aliases","filterable": false,"title":lang.spam_aliases,"breakpoints":"xs sm md"},
|
||||
{"name":"tls_enforce_in","filterable": false,"title":lang.tls_enforce_in,"breakpoints":"all"},
|
||||
{"name":"tls_enforce_out","filterable": false,"title":lang.tls_enforce_out,"breakpoints":"all"},
|
||||
{"name":"in_use","filterable": false,"type":"html","title":lang.in_use,"sortValue": function(value){
|
||||
return Number($(value).find(".progress-bar").attr('aria-valuenow'));
|
||||
},
|
||||
|
@ -374,17 +384,19 @@ jQuery(function($){
|
|||
}).join('/1');
|
||||
}
|
||||
item.chkbox = '<input type="checkbox" data-id="mailbox" name="multi_select" value="' + encodeURIComponent(item.username) + '" />';
|
||||
if (role == "admin") {
|
||||
item.tls_enforce_in = '<span class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success' : 'danger') + ' glyphicon glyphicon-lock"></span>';
|
||||
item.tls_enforce_out = '<span class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success' : 'danger') + ' glyphicon glyphicon-lock"></span>';
|
||||
if (acl_data.login_as === 1) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?mailbox=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
|
||||
'<a href="/edit/mailbox/' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="login_as btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
|
||||
'</div>';
|
||||
}
|
||||
else {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?mailbox=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/mailbox/' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-mailbox" data-api-url="delete/mailbox" data-item="' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
}
|
||||
item.in_use = '<div class="progress">' +
|
||||
|
@ -404,6 +416,7 @@ jQuery(function($){
|
|||
"delay": 100,
|
||||
"position": "left",
|
||||
"connectors": false,
|
||||
//"container": "#tab-mailboxes.panel",
|
||||
"placeholder": lang.filter_table
|
||||
},
|
||||
"components": {
|
||||
|
@ -451,8 +464,8 @@ jQuery(function($){
|
|||
item.multiple_bookings = '<span id="active-script" class="label label-danger">' + lang.booking_custom_short + ' (' + item.multiple_bookings + ')</span>';
|
||||
}
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?resource=' + encodeURIComponent(item.name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-resource" data-api-url="delete/resource" data-item="' + item.name + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/resource/' + encodeURIComponent(item.name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-resource" data-api-url="delete/resource" data-item="' + item.name + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="resource" name="multi_select" value="' + encodeURIComponent(item.name) + '" />';
|
||||
item.name = escapeHtml(item.name);
|
||||
|
@ -510,8 +523,8 @@ jQuery(function($){
|
|||
success: function (data) {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?bcc=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-bcc" data-api-url="delete/bcc" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/bcc/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-bcc" data-api-url="delete/bcc" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="bcc" name="multi_select" value="' + item.id + '" />';
|
||||
item.local_dest = escapeHtml(item.local_dest);
|
||||
|
@ -573,8 +586,8 @@ jQuery(function($){
|
|||
item.recipient_map_old = escapeHtml(item.recipient_map_old);
|
||||
item.recipient_map_new = escapeHtml(item.recipient_map_new);
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?recipient_map=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-recipient_map" data-api-url="delete/recipient_map" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/recipient_map/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-recipient_map" data-api-url="delete/recipient_map" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="recipient_map" name="multi_select" value="' + item.id + '" />';
|
||||
});
|
||||
|
@ -606,6 +619,69 @@ jQuery(function($){
|
|||
}
|
||||
});
|
||||
}
|
||||
function draw_tls_policy_table() {
|
||||
ft_tls_policy_table = FooTable.init('#tls_policy_table', {
|
||||
"columns": [
|
||||
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
|
||||
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
|
||||
{"name":"dest","title":lang.tls_map_dest},
|
||||
{"name":"policy","title":lang.tls_map_policy},
|
||||
{"name":"parameters","title":lang.tls_map_parameters},
|
||||
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active},
|
||||
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"}
|
||||
],
|
||||
"empty": lang.empty,
|
||||
"rows": $.ajax({
|
||||
dataType: 'json',
|
||||
url: '/api/v1/get/tls-policy-map/all',
|
||||
jsonp: false,
|
||||
error: function () {
|
||||
console.log('Cannot draw tls policy map table');
|
||||
},
|
||||
success: function (data) {
|
||||
if (role == "admin") {
|
||||
$.each(data, function (i, item) {
|
||||
item.dest = escapeHtml(item.dest);
|
||||
item.policy = '<b>' + escapeHtml(item.policy) + '</b>';
|
||||
if (item.parameters == '') {
|
||||
item.parameters = '<code>-</code>';
|
||||
} else {
|
||||
item.parameters = '<code>' + escapeHtml(item.parameters) + '</code>';
|
||||
}
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit/tls_policy_map/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-tls-policy-map" data-api-url="delete/tls-policy-map" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="tls-policy-map" name="multi_select" value="' + item.id + '" />';
|
||||
});
|
||||
}
|
||||
}
|
||||
}),
|
||||
"paging": {
|
||||
"enabled": true,
|
||||
"limit": 5,
|
||||
"size": pagination_size
|
||||
},
|
||||
"filtering": {
|
||||
"enabled": true,
|
||||
"delay": 100,
|
||||
"position": "left",
|
||||
"connectors": false,
|
||||
"placeholder": lang.filter_table
|
||||
},
|
||||
"sorting": {
|
||||
"enabled": true
|
||||
},
|
||||
"on": {
|
||||
"ready.ft.table": function(e, ft){
|
||||
table_mailbox_ready(ft, 'tls_policy_table');
|
||||
},
|
||||
"after.ft.paging": function(e, ft){
|
||||
paging_mailbox_after(ft, 'tls_policy_table');
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
function draw_alias_table() {
|
||||
ft_alias_table = FooTable.init('#alias_table', {
|
||||
"columns": [
|
||||
|
@ -628,8 +704,8 @@ jQuery(function($){
|
|||
success: function (data) {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?alias=' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-alias" data-api-url="delete/alias" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/alias/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-alias" data-api-url="delete/alias" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
|
||||
item.goto = escapeHtml(item.goto.replace(/,/g, " "));
|
||||
|
@ -703,8 +779,8 @@ jQuery(function($){
|
|||
success: function (data) {
|
||||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?aliasdomain=' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-alias-domain" data-api-url="delete/alias-domain" data-item="' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/aliasdomain/' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-alias-domain" data-api-url="delete/alias-domain" data-item="' + encodeURIComponent(item.alias_domain) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="#dnsInfoModal" class="btn btn-xs btn-info" data-toggle="modal" data-domain="' + encodeURIComponent(item.alias_domain) + '"><span class="glyphicon glyphicon-question-sign"></span> DNS</a></div>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />';
|
||||
|
@ -771,8 +847,8 @@ jQuery(function($){
|
|||
}
|
||||
item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1;
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?syncjob=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
|
||||
if (item.is_running == 1) {
|
||||
|
@ -842,8 +918,8 @@ jQuery(function($){
|
|||
item.script_data = '<pre style="margin:0px">' + escapeHtml(item.script_data) + '</pre>'
|
||||
item.filter_type = '<div class="label label-default">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>'
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?filter=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-filter" data-api-url="delete/filter" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/filter/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-filter" data-api-url="delete/filter" data-item="' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="filter_item" name="multi_select" value="' + item.id + '" />'
|
||||
});
|
||||
|
@ -884,5 +960,6 @@ jQuery(function($){
|
|||
draw_filter_table();
|
||||
draw_bcc_table();
|
||||
draw_recipient_map_table();
|
||||
draw_tls_policy_table();
|
||||
|
||||
});
|
||||
|
|
|
@ -0,0 +1,193 @@
|
|||
$(document).ready(function() {
|
||||
// mailcow alert box generator
|
||||
window.mailcow_alert_box = function(message, type) {
|
||||
msg = $('<span/>').text(message).text();
|
||||
if (type == 'danger') {
|
||||
auto_hide = 0;
|
||||
$('#' + localStorage.getItem("add_modal")).modal('show');
|
||||
localStorage.removeItem("add_modal");
|
||||
} else {
|
||||
auto_hide = 5000;
|
||||
}
|
||||
$.notify({message: msg},{z_index: 20000, delay: auto_hide, type: type,placement: {from: "bottom",align: "right"},animate: {enter: 'animated fadeInUp',exit: 'animated fadeOutDown'}});
|
||||
}
|
||||
|
||||
// https://stackoverflow.com/questions/4399005/implementing-jquerys-shake-effect-with-animate
|
||||
function shake(div,interval=100,distance=10,times=4) {
|
||||
$(div).css('position','relative');
|
||||
for(var iter=0;iter<(times+1);iter++){
|
||||
$(div).animate({ left: ((iter%2==0 ? distance : distance*-1))}, interval);
|
||||
}
|
||||
$(div).animate({ left: 0},interval);
|
||||
}
|
||||
|
||||
// form cache
|
||||
$('[data-cached-form="true"]').formcache({key: $(this).data('id')});
|
||||
|
||||
// tooltips
|
||||
$(function () {
|
||||
$('[data-toggle="tooltip"]').tooltip()
|
||||
});
|
||||
|
||||
// remember last navigation pill
|
||||
(function () {
|
||||
'use strict';
|
||||
if ($('a[data-toggle="tab"]').length) {
|
||||
$('a[data-toggle="tab"]').on('shown.bs.tab', function (e) {
|
||||
if ($(this).data('dont-remember') == 1) {
|
||||
return true;
|
||||
}
|
||||
var id = $(this).parents('[role="tablist"]').attr('id');
|
||||
var key = 'lastTag';
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
localStorage.setItem(key, $(e.target).attr('href'));
|
||||
});
|
||||
$('[role="tablist"]').each(function (idx, elem) {
|
||||
var id = $(elem).attr('id');
|
||||
var key = 'lastTag';
|
||||
if (id) {
|
||||
key += ':' + id;
|
||||
}
|
||||
var lastTab = localStorage.getItem(key);
|
||||
if (lastTab) {
|
||||
$('[href="' + lastTab + '"]').tab('show');
|
||||
}
|
||||
});
|
||||
}
|
||||
})();
|
||||
|
||||
// IE fix to hide scrollbars when table body is empty
|
||||
$('tbody').filter(function (index) {
|
||||
return $(this).children().length < 1;
|
||||
}).remove();
|
||||
|
||||
// selectpicker
|
||||
$('select').selectpicker();
|
||||
|
||||
// haveibeenpwned?
|
||||
$('[data-hibp]').after('<p class="small haveibeenpwned">↪ Check against haveibeenpwned.com</p><span class="hibp-out"></span>');
|
||||
$('[data-hibp]').on('input', function() {
|
||||
out_field = $(this).next('.haveibeenpwned').next('.hibp-out').text('').attr('class', 'hibp-out');
|
||||
});
|
||||
$('.haveibeenpwned:not(.task-running)').on('click', function() {
|
||||
var hibp_field = $(this)
|
||||
$(hibp_field).addClass('task-running');
|
||||
var hibp_result = $(hibp_field).next('.hibp-out')
|
||||
var password_field = $(this).prev('[data-hibp]')
|
||||
if ($(password_field).val() == '') {
|
||||
shake(password_field);
|
||||
}
|
||||
else {
|
||||
$(hibp_result).attr('class', 'hibp-out label label-info');
|
||||
$(hibp_result).text(lang_footer.loading);
|
||||
var password_digest = $.sha1($(password_field).val())
|
||||
var digest_five = password_digest.substring(0, 5).toUpperCase();
|
||||
var queryURL = "https://api.pwnedpasswords.com/range/" + digest_five;
|
||||
var compl_digest = password_digest.substring(5, 41).toUpperCase();
|
||||
$.ajax({
|
||||
url: queryURL,
|
||||
type: 'GET',
|
||||
success: function(res) {
|
||||
if (res.search(compl_digest) > -1){
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-danger');
|
||||
$(hibp_result).text(lang_footer.hibp_nok)
|
||||
} else {
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-success');
|
||||
$(hibp_result).text(lang_footer.hibp_ok)
|
||||
}
|
||||
$(hibp_field).removeClass('task-running');
|
||||
},
|
||||
error: function(xhr, status, error) {
|
||||
$(hibp_result).removeClass('label label-info').addClass('label label-warning');
|
||||
$(hibp_result).text('API error: ' + xhr.responseText)
|
||||
$(hibp_field).removeClass('task-running');
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
|
||||
// Disable disallowed inputs
|
||||
$('[data-acl="0"]').each(function(){
|
||||
if ($(this).hasClass('btn-group')) {
|
||||
$(this).find('a').each(function(){
|
||||
$(this).removeClass('dropdown-toggle')
|
||||
.removeAttr('data-toggle')
|
||||
.removeAttr('id')
|
||||
.attr("disabled", true);
|
||||
$(this).click(function(event) {
|
||||
event.preventDefault();
|
||||
return;
|
||||
});
|
||||
});
|
||||
$(this).find('button').each(function() {
|
||||
$(this).attr("disabled", true);
|
||||
});
|
||||
} else if ($(this).hasClass('input-group')) {
|
||||
$(this).find('input').each(function() {
|
||||
$(this).removeClass('dropdown-toggle')
|
||||
.removeAttr('data-toggle')
|
||||
.attr("disabled", true);
|
||||
$(this).click(function(event) {
|
||||
event.preventDefault();
|
||||
});
|
||||
});
|
||||
$(this).find('button').each(function() {
|
||||
$(this).attr("disabled", true);
|
||||
});
|
||||
} else if ($(this).hasClass('btn')) {
|
||||
$(this).attr("disabled", true);
|
||||
} else if ($(this).attr('data-provide', 'slider')) {
|
||||
$(this).slider("disable");
|
||||
}
|
||||
$(this).data("toggle", "tooltip");
|
||||
$(this).attr("title", lang_acl.prohibited);
|
||||
$(this).tooltip();
|
||||
});
|
||||
|
||||
// disable submit after submitting form (not API driven buttons)
|
||||
$('form').submit(function() {
|
||||
if ($('form button[type="submit"]').data('submitted') == '1') {
|
||||
return false;
|
||||
} else {
|
||||
$(this).find('button[type="submit"]').first().text(lang_footer.loading);
|
||||
$('form button[type="submit"]').attr('data-submitted', '1');
|
||||
function disableF5(e) { if ((e.which || e.keyCode) == 116 || (e.which || e.keyCode) == 82) e.preventDefault(); };
|
||||
$(document).on("keydown", disableF5);
|
||||
}
|
||||
});
|
||||
|
||||
// trigger container restart
|
||||
$('#RestartContainer').on('show.bs.modal', function(e) {
|
||||
var container = $(e.relatedTarget).data('container');
|
||||
$('#containerName').text(container);
|
||||
$('#triggerRestartContainer').click(function(){
|
||||
$(this).prop("disabled",true);
|
||||
$(this).html('<span class="glyphicon glyphicon-refresh glyphicon-spin"></span> ');
|
||||
$('#statusTriggerRestartContainer').html(lang_footer.restarting_container);
|
||||
$.ajax({
|
||||
method: 'get',
|
||||
url: '/inc/ajax/container_ctrl.php',
|
||||
timeout: docker_timeout,
|
||||
data: {
|
||||
'service': container,
|
||||
'action': 'restart'
|
||||
}
|
||||
})
|
||||
.always( function (data, status) {
|
||||
$('#statusTriggerRestartContainer').append(data);
|
||||
var htmlResponse = $.parseHTML(data)
|
||||
if ($(htmlResponse).find('span').hasClass('text-success')) {
|
||||
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-ok"></span> ');
|
||||
setTimeout(function(){
|
||||
$('#RestartContainer').modal('toggle');
|
||||
window.location = window.location.href.split("#")[0];
|
||||
}, 1200);
|
||||
} else {
|
||||
$('#triggerRestartContainer').html('<span class="glyphicon glyphicon-remove"></span> ');
|
||||
}
|
||||
})
|
||||
});
|
||||
})
|
||||
});
|
|
@ -28,7 +28,7 @@ jQuery(function($){
|
|||
$.each(data, function (i, item) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-info show_qid_info"><span class="glyphicon glyphicon-modal-window"></span> ' + lang.show_item + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="del-single-qitem" data-api-url="delete/qitem" data-item="' + encodeURI(item.id) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />';
|
||||
});
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
!function(r){var o=function(r,o){return r<<o|r>>>32-o},e=function(r){var o,e="";for(o=7;o>=0;o--)e+=(r>>>4*o&15).toString(16);return e};jQuery.extend({sha1:function(r){var a,t,n,h,C,c,f,d,u,i=new Array(80),A=1732584193,g=4023233417,s=2562383102,S=271733878,m=3285377520,p=(r=function(r){r=r.replace(/\x0d\x0a/g,"\n");for(var o="",e=0;e<r.length;e++){var a=r.charCodeAt(e);a<128?o+=String.fromCharCode(a):a>127&&a<2048?(o+=String.fromCharCode(a>>6|192),o+=String.fromCharCode(63&a|128)):(o+=String.fromCharCode(a>>12|224),o+=String.fromCharCode(a>>6&63|128),o+=String.fromCharCode(63&a|128))}return o}(r)).length,l=new Array;for(t=0;t<p-3;t+=4)n=r.charCodeAt(t)<<24|r.charCodeAt(t+1)<<16|r.charCodeAt(t+2)<<8|r.charCodeAt(t+3),l.push(n);switch(p%4){case 0:t=2147483648;break;case 1:t=r.charCodeAt(p-1)<<24|8388608;break;case 2:t=r.charCodeAt(p-2)<<24|r.charCodeAt(p-1)<<16|32768;break;case 3:t=r.charCodeAt(p-3)<<24|r.charCodeAt(p-2)<<16|r.charCodeAt(p-1)<<8|128}for(l.push(t);l.length%16!=14;)l.push(0);for(l.push(p>>>29),l.push(p<<3&4294967295),a=0;a<l.length;a+=16){for(t=0;t<16;t++)i[t]=l[a+t];for(t=16;t<=79;t++)i[t]=o(i[t-3]^i[t-8]^i[t-14]^i[t-16],1);for(h=A,C=g,c=s,f=S,d=m,t=0;t<=19;t++)u=o(h,5)+(C&c|~C&f)+d+i[t]+1518500249&4294967295,d=f,f=c,c=o(C,30),C=h,h=u;for(t=20;t<=39;t++)u=o(h,5)+(C^c^f)+d+i[t]+1859775393&4294967295,d=f,f=c,c=o(C,30),C=h,h=u;for(t=40;t<=59;t++)u=o(h,5)+(C&c|C&f|c&f)+d+i[t]+2400959708&4294967295,d=f,f=c,c=o(C,30),C=h,h=u;for(t=60;t<=79;t++)u=o(h,5)+(C^c^f)+d+i[t]+3395469782&4294967295,d=f,f=c,c=o(C,30),C=h,h=u;A=A+h&4294967295,g=g+C&4294967295,s=s+c&4294967295,S=S+f&4294967295,m=m+d&4294967295}return(u=e(A)+e(g)+e(s)+e(S)+e(m)).toLowerCase()}})}();
|
|
@ -64,7 +64,7 @@ jQuery(function($){
|
|||
$.each(data, function (i, item) {
|
||||
if (acl_data.spam_alias === 1) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="#" id="delete_selected" data-id="single-tla" data-api-url="delete/time_limited_alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-tla" data-api-url="delete/time_limited_alias" data-item="' + encodeURIComponent(item.address) + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
|
||||
item.address = escapeHtml(item.address);
|
||||
|
@ -122,8 +122,8 @@ jQuery(function($){
|
|||
item.server_w_port = escapeHtml(item.user1 + '@' + item.host1 + ':' + item.port1);
|
||||
if (acl_data.syncjobs === 1) {
|
||||
item.action = '<div class="btn-group">' +
|
||||
'<a href="/edit.php?syncjob=' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" id="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'<a href="/edit/syncjob/' + item.id + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>' +
|
||||
'<a href="#" data-action="delete_selected" data-id="single-syncjob" data-api-url="delete/syncjob" data-item="' + item.id + '" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> ' + lang.remove + '</a>' +
|
||||
'</div>';
|
||||
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
|
||||
}
|
||||
|
|
|
@ -153,6 +153,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
case "recipient_map":
|
||||
process_add_return(recipient_map('add', $attr));
|
||||
break;
|
||||
case "tls-policy-map":
|
||||
process_add_return(tls_policy_maps('add', $attr));
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "get":
|
||||
|
@ -164,7 +167,7 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
switch ($object) {
|
||||
case "actions":
|
||||
$curl = curl_init();
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/rspamd-sock/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_UNIX_SOCKET_PATH, '/var/lib/rspamd/rspamd.sock');
|
||||
curl_setopt($curl, CURLOPT_URL,"http://rspamd/stat");
|
||||
curl_setopt($curl, CURLOPT_RETURNTRANSFER, true);
|
||||
$data = curl_exec($curl);
|
||||
|
@ -662,6 +665,31 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
break;
|
||||
}
|
||||
break;
|
||||
case "tls-policy-map":
|
||||
switch ($object) {
|
||||
case "all":
|
||||
$tls_policy_maps_items = tls_policy_maps('get');
|
||||
if (!empty($tls_policy_maps_items)) {
|
||||
foreach ($tls_policy_maps_items as $tls_policy_maps_item) {
|
||||
if ($details = tls_policy_maps('details', $tls_policy_maps_item)) {
|
||||
$data[] = $details;
|
||||
}
|
||||
else {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
process_get_return($data);
|
||||
break;
|
||||
default:
|
||||
$data = tls_policy_maps('details', $object);
|
||||
if (!empty($data)) {
|
||||
$data[] = $details;
|
||||
}
|
||||
process_get_return($data);
|
||||
break;
|
||||
}
|
||||
break;
|
||||
case "policy_wl_mailbox":
|
||||
switch ($object) {
|
||||
default:
|
||||
|
@ -919,6 +947,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
case "recipient_map":
|
||||
process_delete_return(recipient_map('delete', array('id' => $items)));
|
||||
break;
|
||||
case "tls-policy-map":
|
||||
process_delete_return(tls_policy_maps('delete', array('id' => $items)));
|
||||
break;
|
||||
case "fwdhost":
|
||||
process_delete_return(fwdhost('delete', array('forwardinghost' => $items)));
|
||||
break;
|
||||
|
@ -991,6 +1022,9 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
case "recipient_map":
|
||||
process_edit_return(recipient_map('edit', array_merge(array('id' => $items), $attr)));
|
||||
break;
|
||||
case "tls-policy-map":
|
||||
process_edit_return(tls_policy_maps('edit', array_merge(array('id' => $items), $attr)));
|
||||
break;
|
||||
case "alias":
|
||||
process_edit_return(mailbox('edit', 'alias', array_merge(array('id' => $items), $attr)));
|
||||
break;
|
||||
|
@ -1039,6 +1073,12 @@ if (isset($_SESSION['mailcow_cc_role']) || isset($_SESSION['pending_mailcow_cc_u
|
|||
case "rl-mbox":
|
||||
process_edit_return(ratelimit('edit', 'mailbox', array_merge(array('object' => $items), $attr)));
|
||||
break;
|
||||
case "user-acl":
|
||||
process_edit_return(acl('edit', 'user', array_merge(array('username' => $items), $attr)));
|
||||
break;
|
||||
case "da-acl":
|
||||
process_edit_return(acl('edit', 'domainadmin', array_merge(array('username' => $items), $attr)));
|
||||
break;
|
||||
case "alias-domain":
|
||||
process_edit_return(mailbox('edit', 'alias_domain', array_merge(array('alias_domain' => $items), $attr)));
|
||||
break;
|
||||
|
|
|
@ -16,6 +16,9 @@ $lang['footer']['delete_these_items'] = 'Sind Sie sicher, dass die Änderungen a
|
|||
$lang['footer']['delete_now'] = 'Jetzt löschen';
|
||||
$lang['footer']['cancel'] = 'Abbrechen';
|
||||
|
||||
$lang['footer']['hibp_nok'] = 'Übereinstimmung gefunden! Dieses Passwort ist potentiell gefährlich!';
|
||||
$lang['footer']['hibp_ok'] = 'Keine Übereinstimmung gefunden.';
|
||||
|
||||
$lang['danger']['mysql_error'] = "MySQL Fehler: %s";
|
||||
$lang['danger']['redis_error'] = "Redis Fehler: %s";
|
||||
$lang['danger']['unknown_tfa_method'] = "Unbekannte TFA Methode";
|
||||
|
@ -43,6 +46,7 @@ $lang['danger']['domain_cannot_match_hostname'] = "Domain darf nicht dem Hostnam
|
|||
$lang['warning']['domain_added_sogo_failed'] = "Domain wurde hinzugefügt; SOGo konnte nicht neugestartet werden";
|
||||
$lang['danger']['rl_timeframe'] = "Ratelimit Zeitraum ist inkorrekt";
|
||||
$lang['success']['rl_saved'] = "Ratelimit für Objekt %s wurde gesetzt";
|
||||
$lang['success']['acl_saved'] = "ACL für Objekt %s wurde gesetzt";
|
||||
$lang['success']['deleted_syncjobs'] = "Syncjobs gelöscht: %s";
|
||||
$lang['success']['deleted_syncjob'] = "Syncjobs ID %s gelöscht";
|
||||
$lang['success']['delete_filters'] = "Filter gelöscht: %s";
|
||||
|
@ -236,6 +240,17 @@ $lang['header']['mailcow_settings'] = 'Konfiguration';
|
|||
$lang['header']['administration'] = 'Administration';
|
||||
$lang['header']['mailboxes'] = 'Mailboxen';
|
||||
$lang['header']['user_settings'] = 'Benutzereinstellungen';
|
||||
$lang['mailbox']['tls_policy_maps'] = 'TLS-Richtlinien';
|
||||
$lang['mailbox']['tls_policy_maps_long'] = 'Ausgehende TLS-Richtlinien';
|
||||
$lang['mailbox']['tls_policy_maps_info'] = 'Nachstehende Richtlinien erzwingen TLS-Transportregeln unabhängig von TLS-Richtlinieneinstellungen eines Benutzers.<br>
|
||||
Für weitere Informationen zur Syntax sollte <a href="http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps" target="_blank">die "smtp_tls_policy_maps" Dokumentation</a> konsultiert werden.';
|
||||
$lang['mailbox']['tls_enforce_in'] = 'Enforce TLS incoming';
|
||||
$lang['mailbox']['tls_enforce_out'] = 'Enforce TLS outgoing';
|
||||
$lang['mailbox']['tls_map_dest'] = 'Ziel';
|
||||
$lang['mailbox']['tls_map_dest_info'] = 'Beispiele: example.org, .example.org, mail@example.org, [mail.example.org]:25';
|
||||
$lang['mailbox']['tls_map_policy'] = 'Richtlinie';
|
||||
$lang['mailbox']['tls_map_parameters'] = 'Parameter';
|
||||
$lang['mailbox']['tls_map_parameters_info'] = 'Leer oder Parameter, Beispiele: protocols=!SSLv2 ciphers=medium exclude=3DES';
|
||||
$lang['mailbox']['booking_0'] = 'Immer als verfügbar anzeigen';
|
||||
$lang['mailbox']['booking_lt0'] = 'Unbegrenzt, jedoch anzeigen, wenn gebucht';
|
||||
$lang['mailbox']['booking_custom'] = 'Benutzerdefiniertes Limit';
|
||||
|
@ -332,6 +347,8 @@ $lang['edit']['relay_all_info'] = '<small>Wenn Sie <b>nicht</b> alle Empfänger-
|
|||
$lang['edit']['full_name'] = 'Voller Name';
|
||||
$lang['edit']['quota_mb'] = 'Speicherplatz (MiB)';
|
||||
$lang['edit']['sender_acl'] = 'Darf Nachrichten versenden als';
|
||||
$lang['edit']['sender_acl_disabled'] = '↳ <span class="label label-danger">Absenderprüfung deaktiviert</span>';
|
||||
$lang['user']['sender_acl_disabled'] = '<span class="label label-danger">Absenderprüfung deaktiviert</span>';
|
||||
$lang['edit']['previous'] = 'Vorherige Seite';
|
||||
$lang['edit']['unchanged_if_empty'] = 'Unverändert, wenn leer';
|
||||
$lang['edit']['dont_check_sender_acl'] = 'Absender für Domain %s u. Alias-Dom. nicht prüfen';
|
||||
|
@ -339,7 +356,22 @@ $lang['edit']['multiple_bookings'] = 'Mehrfaches Buchen';
|
|||
$lang['edit']['kind'] = 'Art';
|
||||
$lang['edit']['resource'] = 'Ressource';
|
||||
|
||||
$lang['add']['syncjob'] = 'Sync-Job erstellen';
|
||||
$lang['acl']['spam_alias'] = 'Temporäre E-Mail Aliasse';
|
||||
$lang['acl']['tls_policy'] = 'Verschlüsselungsrichtlinie';
|
||||
$lang['acl']['spam_score'] = 'Spam Bewertung';
|
||||
$lang['acl']['spam_policy'] = 'Blacklist/Whitelist';
|
||||
$lang['acl']['delimiter_action'] = 'Delimiter Aktionen (tags)';
|
||||
$lang['acl']['syncjobs'] = 'Sync Jobs';
|
||||
$lang['acl']['eas_reset'] = 'EAS-Cache zurücksetzen';
|
||||
$lang['acl']['quarantine'] = 'Quarantäne';
|
||||
$lang['acl']['login_as'] = 'Einloggen als Mailbox-Benutzer';
|
||||
$lang['acl']['bcc_maps'] = 'BCC Maps';
|
||||
$lang['acl']['filters'] = 'Filter';
|
||||
$lang['acl']['ratelimit'] = 'Rate limit';
|
||||
$lang['acl']['recipient_maps'] = 'Empfängerumschreibungen';
|
||||
$lang['acl']['prohibited'] = 'Untersagt durch Richtlinie';
|
||||
|
||||
$lang['add']['generate'] = 'generieren';
|
||||
$lang['add']['syncjob_hint'] = 'Passwörter werden unverschlüsselt abgelegt!';
|
||||
$lang['add']['hostname'] = 'Servername';
|
||||
$lang['add']['port'] = 'Port';
|
||||
|
@ -597,7 +629,7 @@ $lang['quarantine']['subj'] = "Betreff";
|
|||
$lang['quarantine']['text_plain_content'] = "Inhalt (text/plain)";
|
||||
$lang['quarantine']['text_from_html_content'] = "Inhalt (html, konvertiert)";
|
||||
$lang['quarantine']['atts'] = "Anhänge";
|
||||
$lang['danger']['fuzzy_learn_error'] = "Fuzzy Lernfehler: %s";
|
||||
$lang['warning']['fuzzy_learn_error'] = "Fuzzy Lernfehler: %s";
|
||||
$lang['danger']['spam_learn_error'] = "Spam Lernfehler: %s";
|
||||
$lang['success']['qlearn_spam'] = "Nachricht ID %s wurde als Spam gelernt und gelöscht";
|
||||
|
||||
|
@ -645,9 +677,13 @@ $lang['mailbox']['recipient_map_new_info'] = 'Der neue Empfänger muss eine E-Ma
|
|||
$lang['mailbox']['recipient_map_old'] = 'Original Empfänger';
|
||||
$lang['mailbox']['recipient_map_new'] = 'Neuer Empfänger';
|
||||
$lang['mailbox']['add_recipient_map_entry'] = 'Empfängerumschreibung hinzufügen';
|
||||
$lang['danger']['invalid_recipient_map_new'] = 'Neuer Empfänger %s ist ungültig';
|
||||
$lang['danger']['invalid_recipient_map_old'] = 'Originaler Empfänger %s ist ungültig';
|
||||
$lang['danger']['recipient_map_entry_exists'] = 'Eine Empfängerumschreibung für %s existiert bereits';
|
||||
$lang['success']['recipient_map_entry_saved'] = 'Empfängerumschreibung für Objekt %s wurde gespeichert';
|
||||
$lang['success']['recipient_map_entry_deleted'] = 'Empfängerumschreibung für Objekt %s wurde gelöscht';
|
||||
|
||||
$lang['danger']['invalid_recipient_map_new'] = 'Neuer Empfänger "%s" ist ungültig';
|
||||
$lang['danger']['invalid_recipient_map_old'] = 'Originaler Empfänger "%s" ist ungültig';
|
||||
$lang['danger']['recipient_map_entry_exists'] = 'Eine Empfängerumschreibung für Objekt "%s" existiert bereits';
|
||||
$lang['success']['recipient_map_entry_saved'] = 'Empfängerumschreibung für Objekt "%s" wurde gespeichert';
|
||||
$lang['success']['recipient_map_entry_deleted'] = 'Empfängerumschreibung mit der ID %s wurde gelöscht';
|
||||
$lang['danger']['tls_policy_map_entry_exists'] = 'Eine TLS-Richtlinie "%s" existiert bereits';
|
||||
$lang['success']['tls_policy_map_entry_saved'] = 'TLS-Richtlinieneintrag "%s" wurde gespeichert';
|
||||
$lang['success']['tls_policy_map_entry_deleted'] = 'TLS-Richtlinie mit der ID %s wurde gelöscht';
|
||||
$lang['mailbox']['add_tls_policy_map'] = "TLS-Richtlinieneintrag hinzufügen";
|
||||
$lang['danger']['tls_policy_map_parameter_invalid'] = "Parameter ist ungültig";
|
||||
|
|
|
@ -16,6 +16,9 @@ $lang['footer']['delete_these_items'] = 'Please confirm your changes to the foll
|
|||
$lang['footer']['delete_now'] = 'Delete now';
|
||||
$lang['footer']['cancel'] = 'Cancel';
|
||||
|
||||
$lang['footer']['hibp_nok'] = 'Matched! This is a potentially dangerous password!';
|
||||
$lang['footer']['hibp_ok'] = 'No match found.';
|
||||
|
||||
$lang['danger']['mysql_error'] = "MySQL error: %s";
|
||||
$lang['danger']['redis_error'] = "Redis error: %s";
|
||||
$lang['danger']['unknown_tfa_method'] = "Unknown TFA method";
|
||||
|
@ -43,6 +46,7 @@ $lang['danger']['domain_cannot_match_hostname'] = "Domain cannot match hostname"
|
|||
$lang['warning']['domain_added_sogo_failed'] = "Added domain but failed to restart SOGo, please check your server logs.";
|
||||
$lang['danger']['rl_timeframe'] = "Rate limit time frame is incorrect";
|
||||
$lang['success']['rl_saved'] = "Rate limit for object %s saved";
|
||||
$lang['success']['acl_saved'] = "ACL for object %s saved";
|
||||
$lang['success']['deleted_syncjobs'] = "Deleted syncjobs: %s";
|
||||
$lang['success']['deleted_syncjob'] = "Deleted syncjob ID %s";
|
||||
$lang['success']['delete_filters'] = "Deleted filters: %s";
|
||||
|
@ -238,6 +242,17 @@ $lang['header']['mailcow_settings'] = 'Configuration';
|
|||
$lang['header']['administration'] = 'Administration';
|
||||
$lang['header']['mailboxes'] = 'Mailboxes';
|
||||
$lang['header']['user_settings'] = 'User settings';
|
||||
$lang['mailbox']['tls_policy_maps'] = 'TLS policy maps';
|
||||
$lang['mailbox']['tls_policy_maps_long'] = 'Outgoing TLS policy map overrides';
|
||||
$lang['mailbox']['tls_policy_maps_info'] = 'This policy map overrides outgoing TLS transport rules independently of a users TLS policy settings.<br>
|
||||
Please check <a href="http://www.postfix.org/postconf.5.html#smtp_tls_policy_maps" target="_blank">the "smtp_tls_policy_maps" docs</a> for further information.';
|
||||
$lang['mailbox']['tls_enforce_in'] = 'Enforce TLS incoming';
|
||||
$lang['mailbox']['tls_enforce_out'] = 'Enforce TLS outgoing';
|
||||
$lang['mailbox']['tls_map_dest'] = 'Destination';
|
||||
$lang['mailbox']['tls_map_dest_info'] = 'Examples: example.org, .example.org, mail@example.org, [mail.example.org]:25';
|
||||
$lang['mailbox']['tls_map_policy'] = 'Policy';
|
||||
$lang['mailbox']['tls_map_parameters'] = 'Parameters';
|
||||
$lang['mailbox']['tls_map_parameters_info'] = 'Empty or parameters, for example: protocols=!SSLv2 ciphers=medium exclude=3DES';
|
||||
$lang['mailbox']['booking_0'] = 'Always show as free';
|
||||
$lang['mailbox']['booking_lt0'] = 'Unlimited, but show as busy when booked';
|
||||
$lang['mailbox']['booking_custom'] = 'Hard-limit to a custom amount of bookings';
|
||||
|
@ -342,6 +357,7 @@ $lang['edit']['full_name'] = 'Full name';
|
|||
$lang['edit']['quota_mb'] = 'Quota (MiB)';
|
||||
$lang['edit']['sender_acl'] = 'Allow to send as';
|
||||
$lang['edit']['sender_acl_disabled'] = '↳ <span class="label label-danger">Sender check is disabled</span>';
|
||||
$lang['user']['sender_acl_disabled'] = '<span class="label label-danger">Sender check is disabled</span>';
|
||||
$lang['edit']['previous'] = 'Previous page';
|
||||
$lang['edit']['unchanged_if_empty'] = 'If unchanged leave blank';
|
||||
$lang['edit']['dont_check_sender_acl'] = "Disable sender check for domain %s (+ alias domains)";
|
||||
|
@ -349,6 +365,22 @@ $lang['edit']['multiple_bookings'] = 'Multiple bookings';
|
|||
$lang['edit']['kind'] = 'Kind';
|
||||
$lang['edit']['resource'] = 'Resource';
|
||||
|
||||
$lang['acl']['spam_alias'] = 'Temporary aliases';
|
||||
$lang['acl']['tls_policy'] = 'TLS policy';
|
||||
$lang['acl']['spam_score'] = 'Spam score';
|
||||
$lang['acl']['spam_policy'] = 'Blacklist/Whitelist';
|
||||
$lang['acl']['delimiter_action'] = 'Delimiter action';
|
||||
$lang['acl']['syncjobs'] = 'Sync jobs';
|
||||
$lang['acl']['eas_reset'] = 'Reset EAS devices';
|
||||
$lang['acl']['quarantine'] = 'Quarantine';
|
||||
$lang['acl']['login_as'] = 'Login as mailbox user';
|
||||
$lang['acl']['bcc_maps'] = 'BCC maps';
|
||||
$lang['acl']['filters'] = 'Filters';
|
||||
$lang['acl']['ratelimit'] = 'Rate limit';
|
||||
$lang['acl']['recipient_maps'] = 'Recipient maps';
|
||||
$lang['acl']['prohibited'] = 'Prohibited by ACL';
|
||||
|
||||
$lang['add']['generate'] = 'generate';
|
||||
$lang['add']['syncjob'] = 'Add sync job';
|
||||
$lang['add']['syncjob_hint'] = 'Be aware that passwords need to be saved plain-text!';
|
||||
$lang['add']['hostname'] = 'Hostname';
|
||||
|
@ -610,7 +642,7 @@ $lang['quarantine']['subj'] = "Subject";
|
|||
$lang['quarantine']['text_plain_content'] = "Content (text/plain)";
|
||||
$lang['quarantine']['text_from_html_content'] = "Content (converted html)";
|
||||
$lang['quarantine']['atts'] = "Attachments";
|
||||
$lang['danger']['fuzzy_learn_error'] = "Fuzzy hash learn error: %s";
|
||||
$lang['warning']['fuzzy_learn_error'] = "Fuzzy hash learn error: %s";
|
||||
$lang['danger']['spam_learn_error'] = "Spam learn error: %s";
|
||||
$lang['success']['qlearn_spam'] = "Message ID %s was learned as spam and deleted";
|
||||
|
||||
|
@ -646,6 +678,7 @@ $lang['mailbox']['bcc_maps'] = "BCC maps";
|
|||
$lang['mailbox']['bcc_to_sender'] = "Switch to sender map type";
|
||||
$lang['mailbox']['bcc_to_rcpt'] = "Switch to recipient map type";
|
||||
$lang['mailbox']['add_bcc_entry'] = "Add BCC map";
|
||||
$lang['mailbox']['add_tls_policy_map'] = "Add TLS policy map";
|
||||
$lang['mailbox']['bcc_info'] = "BCC maps are used to silently forward copies of all messages to another address. A recipient map type entry is used, when the local destination acts as recipient of a mail. Sender maps conform to the same principle.<br/>
|
||||
The local destination will not be informed about a failed delivery.";
|
||||
$lang['mailbox']['address_rewriting'] = 'Address rewriting';
|
||||
|
@ -658,10 +691,14 @@ $lang['mailbox']['recipient_map_old'] = 'Original recipient';
|
|||
$lang['mailbox']['recipient_map_new'] = 'New recipient';
|
||||
$lang['danger']['invalid_recipient_map_new'] = 'Invalid new recipient specified: %s';
|
||||
$lang['danger']['invalid_recipient_map_old'] = 'Invalid original recipient specified: %s';
|
||||
$lang['danger']['recipient_map_entry_exists'] = 'A Recipient map entry for %s exists';
|
||||
$lang['success']['recipient_map_entry_saved'] = 'Recipient map entry for %s has been saved';
|
||||
$lang['success']['recipient_map_entry_deleted'] = 'Recipient map entry for %s has been deleted';
|
||||
$lang['danger']['recipient_map_entry_exists'] = 'A Recipient map entry "%s" exists';
|
||||
$lang['success']['recipient_map_entry_saved'] = 'Recipient map entry "%s" has been saved';
|
||||
$lang['success']['recipient_map_entry_deleted'] = 'Recipient map ID %s has been deleted';
|
||||
$lang['danger']['tls_policy_map_entry_exists'] = 'A TLS policy map entry "%s" exists';
|
||||
$lang['success']['tls_policy_map_entry_saved'] = 'TLS policy map entry "%s" has been saved';
|
||||
$lang['success']['tls_policy_map_entry_deleted'] = 'TLS policy map ID %s has been deleted';
|
||||
$lang['mailbox']['add_recipient_map_entry'] = 'Add recipient map';
|
||||
$lang['danger']['tls_policy_map_parameter_invalid'] = "Policy parameter is invalid";
|
||||
|
||||
$lang['oauth2']['scope_ask_permission'] = 'An application asked for the following permissions';
|
||||
$lang['oauth2']['profile'] = 'Profile';
|
||||
|
|
|
@ -592,7 +592,7 @@ $lang['quarantine']['subj'] = "Onderwerp";
|
|||
$lang['quarantine']['text_plain_content'] = "Inhoud (tekst)";
|
||||
$lang['quarantine']['text_from_html_content'] = "Inhoud (geconverteerde html)";
|
||||
$lang['quarantine']['atts'] = "Bijlagen";
|
||||
$lang['danger']['fuzzy_learn_error'] = "Fuzzy hash training-fout: %s";
|
||||
$lang['warning']['fuzzy_learn_error'] = "Fuzzy hash training-fout: %s";
|
||||
$lang['danger']['spam_learn_error'] = "Spamtraining-fout: %s";
|
||||
$lang['success']['qlearn_spam'] = "Bericht %s werd als spam geclassificeerd en is verwijderd";
|
||||
|
||||
|
|
|
@ -22,6 +22,7 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<li role="presentation"><a href="#tab-syncjobs" aria-controls="tab-syncjobs" role="tab" data-toggle="tab"><?=$lang['mailbox']['sync_jobs'];?></a></li>
|
||||
<li role="presentation"><a href="#tab-filters" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['filters'];?></a></li>
|
||||
<li role="presentation"><a href="#tab-bcc" aria-controls="tab-filters" role="tab" data-toggle="tab"><?=$lang['mailbox']['address_rewriting'];?></a></li>
|
||||
<li role="presentation"><a href="#tab-tls-policy" aria-controls="tab-tls-policy" role="tab" data-toggle="tab"><?=$lang['mailbox']['tls_policy_maps'];?></a></li>
|
||||
</ul>
|
||||
|
||||
<div class="row">
|
||||
|
@ -44,10 +45,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<? if($_SESSION['mailcow_cc_role'] == "admin"): ?>
|
||||
<li><a id="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="domain" data-api-url='edit/domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="domain" data-api-url='delete/domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="domain" data-api-url='delete/domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<? endif; ?>
|
||||
</ul>
|
||||
<? if($_SESSION['mailcow_cc_role'] == "admin"): ?>
|
||||
|
@ -74,10 +75,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="mailbox" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="mailbox" data-api-url='delete/mailbox' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addMailboxModal"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_mailbox'];?></a>
|
||||
</div>
|
||||
|
@ -101,10 +102,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="resource" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="resource" data-api-url='edit/resource' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="resource" data-api-url='delete/resource' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="resource" data-api-url='delete/resource' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addResourceModal"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_resource'];?></a>
|
||||
</div>
|
||||
|
@ -134,10 +135,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="alias-domain" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="alias-domain" data-api-url='edit/alias-domain' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="alias-domain" data-api-url='delete/alias-domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="alias-domain" data-api-url='delete/alias-domain' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addAliasDomainModal"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_domain_alias'];?></a>
|
||||
</div>
|
||||
|
@ -161,10 +162,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="alias" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="alias" data-api-url='edit/alias' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="alias" data-api-url='delete/alias' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="alias" data-api-url='delete/alias' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addAliasModal"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_alias'];?></a>
|
||||
</div>
|
||||
|
@ -184,16 +185,16 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<table class="table table-striped" id="sync_job_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-mailbox">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['syncjobs'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="syncjob" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"last_run":""}' href="#"><?=$lang['mailbox']['last_run_reset'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"last_run":""}' href="#"><?=$lang['mailbox']['last_run_reset'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="syncjob" data-api-url='delete/syncjob' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="syncjob" data-api-url='delete/syncjob' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addSyncJobModalAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['create_syncjob'];?></a>
|
||||
</div>
|
||||
|
@ -214,17 +215,17 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<table class="table table-striped" id="filter_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-mailbox">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['filters'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="filter_item" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"prefilter"}' href="#"><?=$lang['mailbox']['set_prefilter'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"postfilter"}' href="#"><?=$lang['mailbox']['set_postfilter'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"prefilter"}' href="#"><?=$lang['mailbox']['set_prefilter'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="filter_item" data-api-url='edit/filter' data-api-attr='{"filter_type":"postfilter"}' href="#"><?=$lang['mailbox']['set_postfilter'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="filter_item" data-api-url='delete/filter' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="filter_item" data-api-url='delete/filter' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addFilterModalAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_filter'];?></a>
|
||||
</div>
|
||||
|
@ -245,23 +246,23 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<table class="table table-striped" id="bcc_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-mailbox">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['bcc_maps'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="bcc" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"sender"}' href="#"><?=$lang['mailbox']['bcc_to_sender'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"rcpt"}' href="#"><?=$lang['mailbox']['bcc_to_rcpt'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"sender"}' href="#"><?=$lang['mailbox']['bcc_to_sender'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="bcc" data-api-url='edit/bcc' data-api-attr='{"type":"rcpt"}' href="#"><?=$lang['mailbox']['bcc_to_rcpt'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="bcc" data-api-url='delete/bcc' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="bcc" data-api-url='delete/bcc' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addBCCModalAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_bcc_entry'];?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="panel panel-default">
|
||||
<div class="panel panel-default <?=($_SESSION['mailcow_cc_role'] == "admin") ?: 'hidden';?>">
|
||||
<div class="panel-heading">
|
||||
<?=$lang['mailbox']['recipient_maps'];?> <span class="badge badge-info table-lines"></span>
|
||||
<div class="btn-group pull-right">
|
||||
|
@ -272,27 +273,49 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="recipient_map_table"></table>
|
||||
</div>
|
||||
<?php
|
||||
if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "admin"))
|
||||
$display = 'block';
|
||||
else
|
||||
$display = 'none';
|
||||
?>
|
||||
<div class="mass-actions-mailbox" style="display: <?php echo $display; ?>">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="recipient_map" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="recipient_map" data-api-url='edit/recipient_map' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="recipient_map" data-api-url='delete/recipient_map' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="recipient_map" data-api-url='delete/recipient_map' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addRecipientMapModalAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_recipient_map_entry'];?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="tabpanel" class="tab-pane <?=($_SESSION['mailcow_cc_role'] == "admin") ?: 'hidden';?>" id="tab-tls-policy">
|
||||
<div class="panel panel-default">
|
||||
<div class="panel-heading">
|
||||
<?=$lang['mailbox']['tls_policy_maps_long'];?> <span class="badge badge-info table-lines"></span>
|
||||
<div class="btn-group pull-right">
|
||||
<button class="btn btn-xs btn-default refresh_table" data-draw="draw_tls_policy_table" data-table="tls_policy_table"><?=$lang['admin']['refresh'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
<p style="margin:10px" class="help-block"><?=$lang['mailbox']['tls_policy_maps_info'];?></p>
|
||||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="tls_policy_table"></table>
|
||||
</div>
|
||||
<div class="mass-actions-mailbox">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="tls-policy-map" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="tls-policy-map" data-api-url='edit/tls-policy-map' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a data-action="delete_selected" data-id="tls-policy-map" data-api-url='delete/tls-policy-map' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addTLSPolicyMapAdmin"><span class="glyphicon glyphicon-plus"></span> <?=$lang['mailbox']['add_tls_policy_map'];?></a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div> <!-- /tab-content -->
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
|
@ -304,14 +327,17 @@ require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/mailbox.php';
|
|||
<?php
|
||||
$lang_mailbox = json_encode($lang['mailbox']);
|
||||
echo "var lang = ". $lang_mailbox . ";\n";
|
||||
echo "var acl = '". json_encode($_SESSION['acl']) . "';\n";
|
||||
echo "var csrf_token = '". $_SESSION['CSRF']['TOKEN'] . "';\n";
|
||||
$role = ($_SESSION['mailcow_cc_role'] == "admin") ? 'admin' : 'domainadmin';
|
||||
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? 'true' : 'false';
|
||||
echo "var role = '". $role . "';\n";
|
||||
echo "var is_dual = " . $is_dual . ";\n";
|
||||
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/mailbox.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/mailbox.js"></script>
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
} else {
|
||||
|
|
|
@ -17,13 +17,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="desc" id="desc" required>
|
||||
<input type="text" class="form-control" id="adminRspamdSettingsDesc" name="desc" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" id="content" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
|
||||
<textarea class="form-control" id="adminRspamdSettingsContent" name="content" rows="10"><?=$rsetting_details['content'];?></textarea>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -35,7 +35,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="rsetting" data-api-url='add/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="rsetting" data-api-url='add/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -60,14 +60,14 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="username" id="username" required>
|
||||
<input type="text" class="form-control" name="username" required>
|
||||
↳ <kbd>a-z A-Z - _ .</kbd>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="name"><?=$lang['admin']['admin_domains'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select title="<?=$lang['admin']['search_domain_da'];?>" style="width:100%" name="domains" size="5" multiple>
|
||||
<select title="<?=$lang['admin']['search_domain_da'];?>" class="full-width-select" name="domains" size="5" multiple>
|
||||
<?php
|
||||
foreach (mailbox('get', 'domains') as $domain) {
|
||||
echo "<option>".htmlspecialchars($domain)."</option>";
|
||||
|
@ -79,13 +79,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['admin']['password'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="" required>
|
||||
<input type="password" class="form-control" data-hibp="true" name="password" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password2"><?=$lang['admin']['password_repeat'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password2" id="password2" placeholder="" required>
|
||||
<input type="password" class="form-control" name="password2" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -97,7 +97,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_domain_admin" data-api-url='add/domain-admin' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_domain_admin" data-api-url='add/domain-admin' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-plus" aria-hidden="true"></span> <?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -115,11 +115,11 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" id="test_relayhost_form" role="form" method="post">
|
||||
<input type="hidden" class="form-control" name="relayhost_id" id="relayhost_id">
|
||||
<input type="hidden" class="form-control" name="relayhost_id">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="mail_from"><?=$lang['admin']['relay_from'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="mail_from" id="mail_from" placeholder="relay@example.org">
|
||||
<input type="text" class="form-control" name="mail_from" placeholder="relay@example.org">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
|
|
@ -8,19 +8,19 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="key_id" id="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
<input type="text" class="form-control" name="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<p class="help-block"><?=$lang['tfa']['api_register'];?></p>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="yubico_id" id="yubico_id" placeholder="Yubico API ID" autocomplete="off" required>
|
||||
<input type="text" class="form-control" name="yubico_id" placeholder="Yubico API ID" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="yubico_key" id="yubico_key" placeholder="Yubico API Key" autocomplete="off" required>
|
||||
<input type="text" class="form-control" name="yubico_key" placeholder="Yubico API Key" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
|
@ -43,10 +43,10 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
<div class="modal-body">
|
||||
<form role="form" method="post" id="u2f_reg_form">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="key_id" id="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
<input type="text" class="form-control" name="key_id" placeholder="<?=$lang['tfa']['key_id'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<p id="u2f_status_reg"></p>
|
||||
|
@ -67,16 +67,16 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="form-group">
|
||||
<input type="text" class="form-control" name="key_id" id="key_id" placeholder="<?=$lang['tfa']['key_id_totp'];?>" autocomplete="off" required>
|
||||
<input type="text" class="form-control" name="key_id" placeholder="<?=$lang['tfa']['key_id_totp'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
</div>
|
||||
<hr>
|
||||
<?php
|
||||
$totp_secret = $tfa->createSecret();
|
||||
?>
|
||||
<input type="hidden" value="<?=$totp_secret;?>" name="totp_secret" id="totp_secret"/>
|
||||
<input type="hidden" value="<?=$totp_secret;?>" name="totp_secret">
|
||||
<input type="hidden" name="tfa_method" value="totp">
|
||||
<ol>
|
||||
<li>
|
||||
|
@ -88,7 +88,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
</li>
|
||||
<li>
|
||||
<p><?=$lang['tfa']['confirm_totp_token'];?>:</p>
|
||||
<p><input type="number" style="width:33%" class="form-control" name="totp_confirm_token" id="totp_confirm_token" autocomplete="off" required></p>
|
||||
<p><input type="number" style="width:33%" class="form-control" name="totp_confirm_token" autocomplete="off" required></p>
|
||||
<p><button class="btn btn-default" type="submit" name="set_tfa"><?=$lang['tfa']['confirm'];?></button></p>
|
||||
</li>
|
||||
</ol>
|
||||
|
@ -105,7 +105,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
|
|||
<div class="modal-body">
|
||||
<form role="form" method="post">
|
||||
<div class="input-group">
|
||||
<input type="password" class="form-control" name="confirm_password" id="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="confirm_password" placeholder="<?=$lang['user']['password_now'];?>" autocomplete="off" required>
|
||||
<span class="input-group-btn">
|
||||
<input type="hidden" name="tfa_method" value="none">
|
||||
<button class="btn btn-danger" type="submit" name="set_tfa"><?=$lang['tfa']['delete_tfa'];?></button>
|
||||
|
@ -135,7 +135,7 @@ if (isset($_SESSION['pending_tfa_method'])):
|
|||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span>
|
||||
<input type="text" name="token" id="token" class="form-control" autocomplete="off" placeholder="Touch Yubikey" aria-describedby="yubi-addon">
|
||||
<input type="text" name="token" class="form-control" autocomplete="off" placeholder="Touch Yubikey" aria-describedby="yubi-addon">
|
||||
<input type="hidden" name="tfa_method" value="yubi_otp">
|
||||
</div>
|
||||
</div>
|
||||
|
@ -160,7 +160,7 @@ if (isset($_SESSION['pending_tfa_method'])):
|
|||
<div class="form-group">
|
||||
<div class="input-group">
|
||||
<span class="input-group-addon" id="tfa-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></span>
|
||||
<input type="number" min="000000" max="999999" name="token" id="token" class="form-control" placeholder="123456" aria-describedby="tfa-addon">
|
||||
<input type="number" min="000000" max="999999" name="token" class="form-control" placeholder="123456" aria-describedby="tfa-addon">
|
||||
<input type="hidden" name="tfa_method" value="totp">
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -17,13 +17,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="local_part"><?=$lang['add']['mailbox_username'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" pattern="[A-Za-z0-9\.!#$%&'*+/=?^_`{|}~-]+" autocorrect="off" autocapitalize="none" class="form-control" name="local_part" id="local_part" required>
|
||||
<input type="text" pattern="[A-Za-z0-9\.!#$%&'*+/=?^_`{|}~-]+" autocorrect="off" autocapitalize="none" class="form-control" name="local_part" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="addSelectDomain" name="domain" id="domain" required>
|
||||
<select class="full-width-select" data-live-search="true" id="addSelectDomain" name="domain" required>
|
||||
<?php
|
||||
foreach (mailbox('get', 'domains') as $domain) {
|
||||
echo "<option>".htmlspecialchars($domain)."</option>";
|
||||
|
@ -35,7 +35,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="name"><?=$lang['add']['full_name'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" id="name">
|
||||
<input type="text" class="form-control" name="name">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -48,16 +48,15 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?></label>
|
||||
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?> (<a href="#" class="generate_password"><?=$lang['add']['generate'];?></a>)</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password" id="password" placeholder="" required>
|
||||
(<a href="#" class="generate_password">Generate</a>)
|
||||
<input type="password" data-hibp="true" class="form-control" name="password" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password2"><?=$lang['add']['password_repeat'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password2" id="password2" placeholder="" required>
|
||||
<input type="password" class="form-control" name="password2" placeholder="" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -69,7 +68,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_mailbox" data-api-url='add/mailbox' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_mailbox" data-api-url='add/mailbox' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -90,37 +89,37 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" autocorrect="off" autocapitalize="none" class="form-control" name="domain" id="domain" required>
|
||||
<input type="text" autocorrect="off" autocapitalize="none" class="form-control" name="domain" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="description" required>
|
||||
<input type="text" class="form-control" name="description" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="aliases"><?=$lang['add']['max_aliases'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="aliases" id="aliases" value="400" required>
|
||||
<input type="number" class="form-control" name="aliases" value="400" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['add']['max_mailboxes'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="mailboxes" id="mailboxes" value="10" required>
|
||||
<input type="number" class="form-control" name="mailboxes" value="10" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxquota"><?=$lang['add']['mailbox_quota_m'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxquota" id="maxquota" value="3072" required>
|
||||
<input type="number" class="form-control" name="maxquota" value="3072" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="quota"><?=$lang['add']['domain_quota_m'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="quota" id="quota" value="10240" required>
|
||||
<input type="number" class="form-control" name="quota" value="10240" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -134,10 +133,10 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="quota">Ratelimit</label>
|
||||
<div class="col-sm-7">
|
||||
<input name="rl_value" id="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
<input name="rl_value" type="number" value="<?=(!empty($rl['value'])) ? $rl['value'] : null;?>" class="form-control" placeholder="disabled">
|
||||
</div>
|
||||
<div class="col-sm-3">
|
||||
<select name="rl_frame" id="rl_frame" class="form-control">
|
||||
<select name="rl_frame" class="form-control">
|
||||
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
|
||||
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
|
||||
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
|
||||
|
@ -159,8 +158,8 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<hr>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{}' href="#"><?=$lang['add']['add_domain_only'];?></button>
|
||||
<button class="btn btn-default" id="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"restart_sogo":"1"}' href="#"><?=$lang['add']['add_domain_restart'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{}' href="#"><?=$lang['add']['add_domain_only'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_domain" data-api-url='add/domain' data-api-attr='{"restart_sogo":"1"}' href="#"><?=$lang['add']['add_domain_restart'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
<p><span class="glyphicon glyphicon-exclamation-sign text-danger"></span> <?=$lang['add']['restart_sogo_hint'];?></p>
|
||||
|
@ -182,13 +181,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="description" required>
|
||||
<input type="text" class="form-control" name="description" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" name="domain" id="domain" title="<?=$lang['add']['select'];?>" required>
|
||||
<select data-live-search="true" name="domain" title="<?=$lang['add']['select'];?>" required>
|
||||
<?php
|
||||
foreach (mailbox('get', 'domains') as $domain) {
|
||||
echo "<option>".htmlspecialchars($domain)."</option>";
|
||||
|
@ -200,7 +199,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['kind'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select name="kind" id="kind" title="<?=$lang['add']['select'];?>" required>
|
||||
<select name="kind" title="<?=$lang['add']['select'];?>" required>
|
||||
<option value="location">Location</option>
|
||||
<option value="group">Group</option>
|
||||
<option value="thing">Thing</option>
|
||||
|
@ -231,7 +230,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_resource" data-api-url='add/resource' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_resource" data-api-url='add/resource' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -263,13 +262,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<textarea id="textarea_alias_goto" autocorrect="off" autocapitalize="none" class="form-control" rows="5" id="goto" name="goto" required></textarea>
|
||||
<p><?=$lang['add']['target_address_info'];?></p>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox" id="goto_null" type="checkbox" value="1" name="goto_null"> <?=$lang['add']['goto_null'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_null"> <?=$lang['add']['goto_null'];?></label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox" id="goto_spam" type="checkbox" value="1" name="goto_spam"> <?=$lang['add']['goto_spam'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_spam"> <?=$lang['add']['goto_spam'];?></label>
|
||||
</div>
|
||||
<div class="checkbox">
|
||||
<label><input class="goto_checkbox" id="goto_ham" type="checkbox" value="1" name="goto_ham"> <?=$lang['add']['goto_ham'];?></label>
|
||||
<label><input class="goto_checkbox" type="checkbox" value="1" name="goto_ham"> <?=$lang['add']['goto_ham'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -282,7 +281,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_alias" data-api-url='add/alias' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_alias" data-api-url='add/alias' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -311,7 +310,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="target_domain"><?=$lang['add']['target_domain'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" name="target_domain" id="target_domain" title="<?=$lang['add']['select'];?>" required>
|
||||
<select data-live-search="true" name="target_domain" title="<?=$lang['add']['select'];?>" required>
|
||||
<?php
|
||||
foreach (mailbox('get', 'domains') as $domain) {
|
||||
echo "<option>".htmlspecialchars($domain)."</option>";
|
||||
|
@ -329,7 +328,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_alias_domain" data-api-url='add/alias-domain' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_alias_domain" data-api-url='add/alias-domain' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -351,7 +350,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="addSelectUsername" name="username" id="username" required>
|
||||
<select data-live-search="true" name="username" required>
|
||||
<?php
|
||||
$domains = mailbox('get', 'domains');
|
||||
if (!empty($domains)) {
|
||||
|
@ -369,32 +368,32 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="host1" id="host1" required>
|
||||
<input type="text" class="form-control" name="host1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="port1" id="port1" min="1" max="65535" value="143" required>
|
||||
<input type="number" class="form-control" name="port1" min="1" max="65535" value="143" required>
|
||||
<small class="help-block">1-65535</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="user1" id="user1" required>
|
||||
<input type="text" class="form-control" name="user1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password1" id="password1" required>
|
||||
<input type="password" class="form-control" name="password1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<select name="enc1" id="enc1" title="<?=$lang['add']['select'];?>" required>
|
||||
<select name="enc1" title="<?=$lang['add']['select'];?>" required>
|
||||
<option selected>TLS</option>
|
||||
<option>SSL</option>
|
||||
<option>PLAIN</option>
|
||||
|
@ -411,47 +410,47 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="External">
|
||||
<input type="text" class="form-control" name="subfolder2" value="External">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="0">
|
||||
<input type="number" class="form-control" name="maxage" min="0" max="32000" value="0">
|
||||
<small class="help-block">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<small class="help-block">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="timeout1"><?=$lang['edit']['timeout1'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout1" id="timeout1" min="1" max="32000" value="600">
|
||||
<input type="number" class="form-control" name="timeout1" min="1" max="32000" value="600">
|
||||
<small class="help-block">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="timeout2"><?=$lang['edit']['timeout2'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="timeout2" id="timeout2" min="1" max="32000" value="600">
|
||||
<input type="number" class="form-control" name="timeout2" min="1" max="32000" value="600">
|
||||
<small class="help-block">1-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="exclude" id="exclude" value="(?i)spam|(?i)junk">
|
||||
<input type="text" class="form-control" name="exclude" value="(?i)spam|(?i)junk">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="custom_params"><?=$lang['add']['custom_params'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="custom_params" id="custom_params" placeholder="--delete2folders --otheroption">
|
||||
<input type="text" class="form-control" name="custom_params" placeholder="--delete2folders --otheroption">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -505,7 +504,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -526,7 +525,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="addSelectUsername" name="username" id="username" required>
|
||||
<select data-live-search="true" name="username" required>
|
||||
<?php
|
||||
$domains = mailbox('get', 'domains');
|
||||
if (!empty($domains)) {
|
||||
|
@ -544,7 +543,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="filter_type"><?=$lang['add']['sieve_type'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="addFilterType" name="filter_type" id="filter_type" required>
|
||||
<select id="addFilterType" name="filter_type" required>
|
||||
<option value="prefilter">Prefilter</option>
|
||||
<option value="postfilter">Postfilter</option>
|
||||
</select>
|
||||
|
@ -553,7 +552,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="script_desc"><?=$lang['add']['sieve_desc'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="script_desc" id="script_desc" required maxlength="255">
|
||||
<input type="text" class="form-control" name="script_desc" required maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -573,7 +572,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10" id="add_filter_btns">
|
||||
<button class="btn btn-default" id="validate_sieve" href="#"><?=$lang['add']['validate'];?></button>
|
||||
<button class="btn btn-success" id="add_item" data-id="add_filter" data-api-url='add/filter' data-api-attr='{}' href="#" disabled><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-success" data-action="add_item" data-id="add_filter" data-api-url='add/filter' data-api-attr='{}' href="#" disabled><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -594,7 +593,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="local_dest"><?=$lang['mailbox']['bcc_local_dest'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" id="addSelectLocalDest" name="local_dest" id="local_dest" required>
|
||||
<select data-live-search="true" name="local_dest" required>
|
||||
<?php
|
||||
$domains = mailbox('get', 'domains');
|
||||
$alias_domains = mailbox('get', 'alias_domains');
|
||||
|
@ -623,7 +622,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="type"><?=$lang['mailbox']['bcc_map_type'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select id="addFBCCType" name="type" id="type" required>
|
||||
<select name="type" required>
|
||||
<option value="sender"><?=$lang['mailbox']['bcc_sender_map'];?></option>
|
||||
<option value="rcpt"><?=$lang['mailbox']['bcc_rcpt_map'];?></option>
|
||||
</select>
|
||||
|
@ -632,7 +631,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destination'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="bcc_dest" id="bcc_dest">
|
||||
<input type="text" class="form-control" name="bcc_dest">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -644,7 +643,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="add_item" data-id="add_bcc" data-api-url='add/bcc' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-success" data-action="add_item" data-id="add_bcc" data-api-url='add/bcc' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -665,14 +664,14 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="recipient_map_old"><?=$lang['mailbox']['recipient_map_old'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="recipient_map_old" id="recipient_map_old">
|
||||
<input type="text" class="form-control" name="recipient_map_old">
|
||||
<small><?=$lang['mailbox']['recipient_map_old_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="recipient_map_new" id="recipient_map_new">
|
||||
<input type="text" class="form-control" name="recipient_map_new">
|
||||
<small><?=$lang['mailbox']['recipient_map_new_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -685,7 +684,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" id="add_item" data-id="add_recipient_map" data-api-url='add/recipient_map' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-success" data-action="add_item" data-id="add_recipient_map" data-api-url='add/recipient_map' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -693,6 +692,62 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
</div>
|
||||
</div><!-- add add_recipient_map modal -->
|
||||
<!-- add add_tls_policy_map modal -->
|
||||
<div class="modal fade" id="addTLSPolicyMapAdmin" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-lg">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span></button>
|
||||
<h3 class="modal-title"><?=$lang['mailbox']['tls_policy_maps'];?></h3>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" data-cached-form="true" role="form" data-id="add_tls_policy_map">
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="dest"><?=$lang['mailbox']['tls_map_dest'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="dest">
|
||||
<small><?=$lang['mailbox']['tls_map_dest_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="policy"><?=$lang['mailbox']['tls_map_policy'];?>:</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="full-width-select" name="policy" required>
|
||||
<option value="none">none</option>
|
||||
<option value="may">may</option>
|
||||
<option value="encrypt">encrypt</option>
|
||||
<option value="dane">dane</option>
|
||||
<option value="dane-only">dane-only</option>
|
||||
<option value="fingerprint">fingerprint</option>
|
||||
<option value="verify">verify</option>
|
||||
<option value="secure">secure</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="parameters"><?=$lang['mailbox']['tls_map_parameters'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="parameters">
|
||||
<small><?=$lang['mailbox']['tls_map_parameters_info'];?></small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<div class="checkbox">
|
||||
<label><input type="checkbox" value="1" name="active" checked> <?=$lang['add']['active'];?></label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-success" data-action="add_item" data-id="add_tls_policy_map" data-api-url='add/tls-policy-map' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div><!-- add add_tls_policy_map modal -->
|
||||
<!-- log modal -->
|
||||
<div class="modal fade" id="syncjobLogModal" tabindex="-1" role="dialog" aria-labelledby="syncjobLogModalLabel">
|
||||
<div class="modal-dialog modal-lg" role="document">
|
||||
|
|
|
@ -18,32 +18,32 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="host1" id="host1" required>
|
||||
<input type="text" class="form-control" name="host1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="port1" id="port1" min="1" max="65535" value="143" required>
|
||||
<input type="number" class="form-control" name="port1" min="1" max="65535" value="143" required>
|
||||
<small class="help-block">1-65535</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="user1" id="user1" required>
|
||||
<input type="text" class="form-control" name="user1" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="password" class="form-control" name="password1" id="password1" required>
|
||||
<input type="password" class="form-control" name="password1" data-hibp="true" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<select name="enc1" id="enc1" title="<?=$lang['add']['select'];?>" required>
|
||||
<select name="enc1" title="<?=$lang['add']['select'];?>" required>
|
||||
<option selected>TLS</option>
|
||||
<option>SSL</option>
|
||||
<option>PLAIN</option>
|
||||
|
@ -60,27 +60,27 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="subfolder2" id="subfolder2" value="External">
|
||||
<input type="text" class="form-control" name="subfolder2" value="External">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxage" id="maxage" min="0" max="32000" value="0">
|
||||
<input type="number" class="form-control" name="maxage" min="0" max="32000" value="0">
|
||||
<small class="help-block">0-32000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" id="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<input type="number" class="form-control" name="maxbytespersecond" min="0" max="125000000" value="0">
|
||||
<small class="help-block">0-125000000</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="exclude" id="exclude" value="(?i)spam|(?i)junk">
|
||||
<input type="text" class="form-control" name="exclude" value="(?i)spam|(?i)junk">
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
|
@ -127,7 +127,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-2 col-sm-10">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_syncjob" data-api-url='add/syncjob' data-api-attr='{}' href="#"><?=$lang['admin']['add'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
@ -155,13 +155,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="user_new_pass"><?=$lang['user']['new_password'];?></label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" class="form-control" name="user_new_pass" id="user_new_pass" autocomplete="off" required>
|
||||
<input type="password" data-hibp="true" class="form-control" name="user_new_pass" autocomplete="off" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="user_new_pass2"><?=$lang['user']['new_password_repeat'];?></label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" class="form-control" name="user_new_pass2" id="user_new_pass2" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="user_new_pass2" autocomplete="off" required>
|
||||
<p class="help-block"><?=$lang['user']['new_password_description'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -169,12 +169,12 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
|
|||
<div class="form-group">
|
||||
<label class="control-label col-sm-3" for="user_old_pass"><?=$lang['user']['password_now'];?></label>
|
||||
<div class="col-sm-5">
|
||||
<input type="password" class="form-control" name="user_old_pass" id="user_old_pass" autocomplete="off" required>
|
||||
<input type="password" class="form-control" name="user_old_pass" autocomplete="off" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-group">
|
||||
<div class="col-sm-offset-3 col-sm-9">
|
||||
<button class="btn btn-default" id="edit_selected" data-id="pwchange" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#"><?=$lang['user']['change_password'];?></button>
|
||||
<button class="btn btn-default" data-action="edit_selected" data-id="pwchange" data-item="null" data-api-url='edit/self' data-api-attr='{}' href="#"><?=$lang['user']['change_password'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
|
|
|
@ -18,15 +18,15 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
|||
<table id="quarantinetable" class="table table-striped"></table>
|
||||
</div>
|
||||
<div class="mass-actions-quarantine">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['quarantine'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="qitems" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['quarantine']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['quarantine']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#"><?=$lang['quarantine']['release'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"release"}' href="#"><?=$lang['quarantine']['release'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#"><?=$lang['quarantine']['learn_spam_delete'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="qitems" data-api-url='edit/qitem' data-api-attr='{"action":"learnspam"}' href="#"><?=$lang['quarantine']['learn_spam_delete'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="qitems" data-api-url='delete/qitem' href="#"><?=$lang['quarantine']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="qitems" data-api-url='delete/qitem' href="#"><?=$lang['quarantine']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -47,8 +47,8 @@ echo "var role = '". $role . "';\n";
|
|||
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/quarantine.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/quarantine.js"></script>
|
||||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/footer.inc.php';
|
||||
} else {
|
||||
|
|
|
@ -10,6 +10,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
|
|||
$_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
|
||||
$tfa_data = get_tfa();
|
||||
$username = $_SESSION['mailcow_cc_username'];
|
||||
|
||||
?>
|
||||
<div class="container">
|
||||
<h3><?=$lang['user']['user_settings'];?></h3>
|
||||
|
@ -28,6 +29,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
|
|||
else: echo "Last login: -"; endif;
|
||||
?>
|
||||
</small></p>
|
||||
<p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
|
@ -88,7 +90,6 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
fclose($fh);
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
<div class="container">
|
||||
<h3><?=$lang['user']['user_settings'];?></h3>
|
||||
|
@ -103,6 +104,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<?php endif; ?>
|
||||
<p><a href="#pwChangeModal" data-toggle="modal">[<?=$lang['user']['change_password'];?>]</a></p>
|
||||
<p><a target="_blank" href="https://mailcow.github.io/mailcow-dockerized-docs/client/#<?=$clientconfigstr;?>">[<?=$lang['user']['client_configuration'];?>]</a></p>
|
||||
<p><a href="#userFilterModal" data-toggle="modal">[<?=$lang['user']['show_sieve_filters'];?>]</a></p>
|
||||
<p><small>
|
||||
<?php
|
||||
if ($_SESSION['mailcow_cc_last_login']['remote']):
|
||||
|
@ -115,13 +117,6 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"> <span class="glyphicon glyphicon-filter"></span></div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><a href="#userFilterModal" data-toggle="modal">[<?=$lang['user']['show_sieve_filters'];?>]</a></p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<?php // Get user information about aliases
|
||||
$user_get_alias_details = user_get_alias_details($username);
|
||||
?>
|
||||
|
@ -145,7 +140,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['aliases_also_send_as'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<p><?=$user_get_alias_details['aliases_also_send_as'];?></p>
|
||||
<p><?=($user_get_alias_details['aliases_also_send_as'] == '*') ? $lang['user']['sender_acl_disabled'] : $user_get_alias_details['aliases_also_send_as'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
|
@ -172,87 +167,71 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<p><?=formatBytes($mailboxdata['quota_used'], 2);?> / <?=formatBytes($mailboxdata['quota'], 2);?>, <?=$mailboxdata['messages'];?> <?=$lang['user']['messages'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<?php
|
||||
($_SESSION['acl']['delimiter_action'] == 0 && $_SESSION['acl']['delimiter_action'] == 0 && $_SESSION['acl']['delimiter_action'] == 0) ? null : '<hr>';
|
||||
// Show tagging options
|
||||
if ($_SESSION['acl']['delimiter_action'] == 1):
|
||||
$get_tagging_options = mailbox('get', 'delimiter_action', $username);
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['tag_handling'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<div class="btn-group">
|
||||
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['delimiter_action'];?>">
|
||||
<button type="button" class="btn btn-sm btn-default <?=($get_tagging_options == "subfolder") ? 'active' : null; ?>"
|
||||
id="edit_selected"
|
||||
data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subfolder"}'><?=$lang['user']['tag_in_subfolder'];?></button>
|
||||
|
||||
<button type="button" class="btn btn-sm btn-default <?=($get_tagging_options == "subject") ? 'active' : null; ?>"
|
||||
id="edit_selected"
|
||||
data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"subject"}'><?=$lang['user']['tag_in_subject'];?></button>
|
||||
|
||||
<button type="button" class="btn btn-sm btn-default <?=($get_tagging_options == "none") ? 'active' : null; ?>"
|
||||
id="edit_selected"
|
||||
data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="delimiter_action"
|
||||
data-api-url='edit/delimiter_action'
|
||||
data-api-attr='{"tagged_mail_handler":"none"}'><?=$lang['user']['tag_in_none'];?></button>
|
||||
|
||||
</div>
|
||||
<p class="help-block"><?=$lang['user']['tag_help_explain'];?></p>
|
||||
<p class="help-block"><?=$lang['user']['tag_help_example'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
// Show TLS policy options
|
||||
if ($_SESSION['acl']['tls_policy'] == 1):
|
||||
$get_tls_policy = mailbox('get', 'tls_policy', $username);
|
||||
?>
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['tls_policy'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<div class="btn-group">
|
||||
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['tls_policy'];?>">
|
||||
<button type="button" class="btn btn-sm btn-default <?=($get_tls_policy['tls_enforce_in'] == "1") ? "active" : null;?>"
|
||||
id="edit_selected"
|
||||
data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_in":<?=($get_tls_policy['tls_enforce_in'] == "1") ? "0" : "1";?>}'><?=$lang['user']['tls_enforce_in'];?></button>
|
||||
|
||||
<button type="button" class="btn btn-sm btn-default <?=($get_tls_policy['tls_enforce_out'] == "1") ? "active" : null;?>"
|
||||
id="edit_selected"
|
||||
data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="tls_policy"
|
||||
data-api-url='edit/tls_policy'
|
||||
data-api-attr='{"tls_enforce_out":<?=($get_tls_policy['tls_enforce_out'] == "1") ? "0" : "1";?>}'><?=$lang['user']['tls_enforce_out'];?></button>
|
||||
|
||||
</div>
|
||||
<p class="help-block"><?=$lang['user']['tls_policy_warning'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
// Rest EAS devices
|
||||
if ($_SESSION['acl']['eas_reset'] == 1):
|
||||
?>
|
||||
|
||||
<div class="row">
|
||||
<div class="col-md-3 col-xs-5 text-right"><?=$lang['user']['eas_reset'];?>:</div>
|
||||
<div class="col-md-9 col-xs-7">
|
||||
<button class="btn btn-xs btn-default" id="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-item="<?= htmlentities($username); ?>" data-id="eas_cache" data-api-url='delete/eas_cache' href="#"><?=$lang['user']['eas_reset_now'];?></button>
|
||||
<button class="btn btn-xs btn-default" data-acl="<?=$_SESSION['acl']['eas_reset'];?>" data-action="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-item="<?= htmlentities($username); ?>" data-id="eas_cache" data-api-url='delete/eas_cache' href="#"><?=$lang['user']['eas_reset_now'];?></button>
|
||||
<p class="help-block"><?=$lang['user']['eas_reset_help'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -273,35 +252,31 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if ($_SESSION['acl']['spam_alias'] == 1):
|
||||
?>
|
||||
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_alias'];?>">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="tla" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-time"></span> + 1h</a></li>
|
||||
<li><a data-action="edit_selected" data-id="tla" data-api-url='edit/time_limited_alias' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-time"></span> + 1h</a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-id="tla" data-api-url='delete/time_limited_alias' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-id="tla" data-api-url='delete/time_limited_alias' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-success dropdown-toggle" data-toggle="dropdown" href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['alias_create_random'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"1"}' href="#">1 <?=$lang['user']['hour'];?></a></li>
|
||||
<li><a id="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"6"}' href="#">6 <?=$lang['user']['hours'];?></a></li>
|
||||
<li><a id="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"24"}' href="#">1 <?=$lang['user']['day'];?></a></li>
|
||||
<li><a id="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"168"}' href="#">1 <?=$lang['user']['week'];?></a></li>
|
||||
<li><a id="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"672"}' href="#">4 <?=$lang['user']['weeks'];?></a></li>
|
||||
<li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"1"}' href="#">1 <?=$lang['user']['hour'];?></a></li>
|
||||
<li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"6"}' href="#">6 <?=$lang['user']['hours'];?></a></li>
|
||||
<li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"24"}' href="#">1 <?=$lang['user']['day'];?></a></li>
|
||||
<li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"168"}' href="#">1 <?=$lang['user']['week'];?></a></li>
|
||||
<li><a data-action="add_item" data-api-url='add/time_limited_alias' data-api-attr='{"validity":"672"}' href="#">4 <?=$lang['user']['weeks'];?></a></li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</div>
|
||||
|
||||
<div role="tabpanel" class="tab-pane" id="Spamfilter">
|
||||
|
@ -309,7 +284,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<form class="form-horizontal" role="form" data-id="spam_score" method="post">
|
||||
<div class="form-group">
|
||||
<div class="col-lg-6 col-sm-12">
|
||||
<input name="spam_score" id="spam_score" type="text" style="width: 100%;"
|
||||
<input data-acl="<?=$_SESSION['acl']['spam_score'];?>" name="spam_score" id="spam_score" type="text" style="width: 100%;"
|
||||
data-provide="slider"
|
||||
data-slider-min="1"
|
||||
data-slider-max="2000"
|
||||
|
@ -330,21 +305,17 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<p><?=$lang['user']['spamfilter_hint'];?></p>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
if ($_SESSION['acl']['spam_score'] == 1):
|
||||
?>
|
||||
|
||||
<div class="form-group">
|
||||
<div class="col-sm-10">
|
||||
<button type="button" class="btn btn-sm btn-success" id="edit_selected"
|
||||
<button data-acl="<?=$_SESSION['acl']['spam_score'];?>" type="button" class="btn btn-sm btn-success" data-action="edit_selected"
|
||||
data-item="<?= htmlentities($username); ?>"
|
||||
data-id="spam_score"
|
||||
data-api-url='edit/spam-score'
|
||||
data-api-attr='{}'><?=$lang['user']['save_changes'];?></button>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</form>
|
||||
<hr>
|
||||
<div class="row">
|
||||
|
@ -354,26 +325,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="wl_policy_mailbox_table"></table>
|
||||
</div>
|
||||
<?php
|
||||
if ($_SESSION['acl']['spam_policy'] == 1):
|
||||
?>
|
||||
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_wl_mailbox" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_wl_mailbox" data-api-url='delete/mailbox-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<a class="btn btn-sm btn-danger" data-action="delete_selected" data-id="policy_wl_mailbox" data-api-url='delete/mailbox-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" data-id="add_wl_policy_mailbox">
|
||||
<div class="input-group">
|
||||
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_wl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username":<?= json_encode($username); ?>,"object_list":"wl"}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_wl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username":<?= json_encode($username); ?>,"object_list":"wl"}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</div>
|
||||
<div class="col-sm-6">
|
||||
<h4><?=$lang['user']['spamfilter_bl'];?></h4>
|
||||
|
@ -381,28 +348,22 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div class="table-responsive">
|
||||
<table class="table table-striped table-condensed" id="bl_policy_mailbox_table"></table>
|
||||
</div>
|
||||
<?php
|
||||
if ($_SESSION['acl']['spam_policy'] == 1):
|
||||
?>
|
||||
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="policy_bl_mailbox" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-danger" id="delete_selected" data-id="policy_bl_mailbox" data-api-url='delete/mailbox-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<a class="btn btn-sm btn-danger" data-action="delete_selected" data-id="policy_bl_mailbox" data-api-url='delete/mailbox-policy' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</div>
|
||||
</div>
|
||||
<form class="form-inline" data-id="add_bl_policy_mailbox">
|
||||
<div class="input-group">
|
||||
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>">
|
||||
<input type="text" class="form-control" name="object_from" id="object_from" placeholder="*@example.org" required>
|
||||
<input type="hidden" name="username" value="<?= htmlentities($username) ;?>">
|
||||
<input type="hidden" name="object_list" value="bl">
|
||||
<span class="input-group-btn">
|
||||
<button class="btn btn-default" id="add_item" data-id="add_bl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username":<?= json_encode($username); ?>,"object_list":"bl"}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
<button class="btn btn-default" data-action="add_item" data-id="add_bl_policy_mailbox" data-api-url='add/mailbox-policy' data-api-attr='{"username":<?= json_encode($username); ?>,"object_list":"bl"}' href="#"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['spamfilter_table_add'];?></button>
|
||||
</span>
|
||||
</div>
|
||||
</form>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -411,25 +372,21 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div class="table-responsive">
|
||||
<table class="table table-striped" id="sync_job_table"></table>
|
||||
</div>
|
||||
<?php
|
||||
if ($_SESSION['acl']['syncjobs'] == 1):
|
||||
?>
|
||||
|
||||
<div class="mass-actions-user">
|
||||
<div class="btn-group">
|
||||
<div class="btn-group" data-acl="<?=$_SESSION['acl']['syncjobs'];?>">
|
||||
<a class="btn btn-sm btn-default" id="toggle_multi_select_all" data-id="syncjob" href="#"><span class="glyphicon glyphicon-check" aria-hidden="true"></span> <?=$lang['mailbox']['toggle_all'];?></a>
|
||||
<a class="btn btn-sm btn-default dropdown-toggle" data-toggle="dropdown" href="#"><?=$lang['mailbox']['quick_actions'];?> <span class="caret"></span></a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a id="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a id="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"1"}' href="#"><?=$lang['mailbox']['activate'];?></a></li>
|
||||
<li><a data-action="edit_selected" data-id="syncjob" data-api-url='edit/syncjob' data-api-attr='{"active":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
|
||||
<li role="separator" class="divider"></li>
|
||||
<li><a id="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="syncjob" data-api-url='delete/syncjob' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
<li><a data-action="delete_selected" data-text="<?=$lang['user']['eas_reset'];?>?" data-id="syncjob" data-api-url='delete/syncjob' href="#"><?=$lang['mailbox']['remove'];?></a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm btn-success" href="#" data-toggle="modal" data-target="#addSyncJobModal"><span class="glyphicon glyphicon-plus"></span> <?=$lang['user']['create_syncjob'];?></a>
|
||||
</div>
|
||||
</div>
|
||||
<?php
|
||||
endif;
|
||||
?>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
@ -437,7 +394,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
|
|||
<div style="margin-bottom:200px;"></div>
|
||||
<?php
|
||||
}
|
||||
if (isset($_SESSION['mailcow_cc_role'])) {
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] != 'admin') {
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/modals/user.php';
|
||||
?>
|
||||
<script type='text/javascript'>
|
||||
|
@ -450,8 +407,8 @@ echo "var mailcow_cc_username = '". $_SESSION['mailcow_cc_username'] . "';\n";
|
|||
echo "var pagination_size = '". $PAGINATION_SIZE . "';\n";
|
||||
?>
|
||||
</script>
|
||||
<script src="js/footable.min.js"></script>
|
||||
<script src="js/user.js"></script>
|
||||
<script src="/js/footable.min.js"></script>
|
||||
<script src="/js/user.js"></script>
|
||||
<?php
|
||||
require_once("inc/footer.inc.php");
|
||||
}
|
||||
|
|
|
@ -2,7 +2,7 @@ version: '2.1'
|
|||
services:
|
||||
|
||||
unbound-mailcow:
|
||||
image: mailcow/unbound:1.1
|
||||
image: mailcow/unbound:1.2
|
||||
build: ./data/Dockerfiles/unbound
|
||||
command: /usr/sbin/unbound
|
||||
environment:
|
||||
|
@ -10,6 +10,7 @@ services:
|
|||
volumes:
|
||||
- ./data/conf/unbound/unbound.conf:/etc/unbound/unbound.conf:ro
|
||||
restart: always
|
||||
tty: true
|
||||
networks:
|
||||
mailcow-network:
|
||||
ipv4_address: ${IPV4_NETWORK:-172.22.1}.254
|
||||
|
@ -20,6 +21,7 @@ services:
|
|||
image: mariadb:10.2
|
||||
volumes:
|
||||
- mysql-vol-1:/var/lib/mysql/
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
- ./data/conf/mysql/:/etc/mysql/conf.d/:ro
|
||||
environment:
|
||||
- TZ=${TZ}
|
||||
|
@ -71,7 +73,7 @@ services:
|
|||
- clamd
|
||||
|
||||
rspamd-mailcow:
|
||||
image: mailcow/rspamd:1.24
|
||||
image: mailcow/rspamd:1.27
|
||||
build: ./data/Dockerfiles/rspamd
|
||||
stop_grace_period: 30s
|
||||
depends_on:
|
||||
|
@ -79,11 +81,10 @@ services:
|
|||
environment:
|
||||
- TZ=${TZ}
|
||||
volumes:
|
||||
- ./data/conf/rspamd/custom/:/etc/rspamd/custom:ro
|
||||
- ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:rw
|
||||
- ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:ro
|
||||
- ./data/conf/rspamd/custom/:/etc/rspamd/custom
|
||||
- ./data/conf/rspamd/override.d/:/etc/rspamd/override.d
|
||||
- ./data/conf/rspamd/local.d/:/etc/rspamd/local.d
|
||||
- ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro
|
||||
- rspamd-sock:/rspamd-sock
|
||||
- rspamd-vol-1:/var/lib/rspamd
|
||||
restart: always
|
||||
dns:
|
||||
|
@ -95,7 +96,7 @@ services:
|
|||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: mailcow/phpfpm:1.18
|
||||
image: mailcow/phpfpm:1.21
|
||||
build: ./data/Dockerfiles/phpfpm
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
|
@ -103,7 +104,8 @@ services:
|
|||
volumes:
|
||||
- ./data/web:/web:rw
|
||||
- ./data/conf/rspamd/dynmaps:/dynmaps:ro
|
||||
- rspamd-sock:/rspamd-sock
|
||||
- rspamd-vol-1:/var/lib/rspamd
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
- ./data/conf/rspamd/meta_exporter:/meta_exporter:ro
|
||||
- ./data/conf/phpfpm/php-fpm.d/pools.conf:/usr/local/etc/php-fpm.d/z-pools.conf
|
||||
- ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini
|
||||
|
@ -136,7 +138,7 @@ services:
|
|||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: mailcow/sogo:1.34
|
||||
image: mailcow/sogo:1.38
|
||||
build: ./data/Dockerfiles/sogo
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
|
@ -147,6 +149,7 @@ services:
|
|||
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
|
||||
volumes:
|
||||
- ./data/conf/sogo/:/etc/sogo/
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
restart: always
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
|
@ -157,7 +160,7 @@ services:
|
|||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: mailcow/dovecot:1.33
|
||||
image: mailcow/dovecot:1.38
|
||||
build: ./data/Dockerfiles/dovecot
|
||||
cap_add:
|
||||
- NET_BIND_SERVICE
|
||||
|
@ -167,13 +170,16 @@ services:
|
|||
- ./data/conf/sogo/:/etc/sogo/
|
||||
- vmail-vol-1:/var/vmail
|
||||
- crypt-vol-1:/mail_crypt/
|
||||
- rspamd-sock:/rspamd-sock
|
||||
- ./data/conf/rspamd/custom/:/etc/rspamd/custom
|
||||
- rspamd-vol-1:/var/lib/rspamd
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
- DBPASS=${DBPASS}
|
||||
- TZ=${TZ}
|
||||
- MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440}
|
||||
ports:
|
||||
- "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
|
||||
- "${IMAP_PORT:-143}:143"
|
||||
|
@ -196,14 +202,15 @@ services:
|
|||
- dovecot
|
||||
|
||||
postfix-mailcow:
|
||||
image: mailcow/postfix:1.21
|
||||
image: mailcow/postfix:1.23
|
||||
build: ./data/Dockerfiles/postfix
|
||||
volumes:
|
||||
- ./data/conf/postfix:/opt/postfix/conf
|
||||
- ./data/assets/ssl:/etc/ssl/mail/:ro
|
||||
- postfix-vol-1:/var/spool/postfix
|
||||
- crypt-vol-1:/var/lib/zeyple
|
||||
- rspamd-sock:/rspamd-sock
|
||||
- rspamd-vol-1:/var/lib/rspamd
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
- TZ=${TZ}
|
||||
|
@ -264,6 +271,8 @@ services:
|
|||
- ./data/assets/ssl/:/etc/ssl/mail/:ro
|
||||
- ./data/conf/nginx/:/etc/nginx/conf.d/:rw
|
||||
- ./data/conf/rspamd/meta_exporter:/meta_exporter:ro
|
||||
volumes_from:
|
||||
- sogo-mailcow
|
||||
ports:
|
||||
- "${HTTPS_BIND:-0.0.0.0}:${HTTPS_PORT:-443}:${HTTPS_PORT:-443}"
|
||||
- "${HTTP_BIND:-0.0.0.0}:${HTTP_PORT:-80}:${HTTP_PORT:-80}"
|
||||
|
@ -278,8 +287,7 @@ services:
|
|||
acme-mailcow:
|
||||
depends_on:
|
||||
- nginx-mailcow
|
||||
- mysql-mailcow
|
||||
image: mailcow/acme:1.37
|
||||
image: mailcow/acme:1.38
|
||||
build: ./data/Dockerfiles/acme
|
||||
dns:
|
||||
- ${IPV4_NETWORK:-172.22.1}.254
|
||||
|
@ -297,6 +305,7 @@ services:
|
|||
- ./data/web/.well-known/acme-challenge:/var/www/acme:rw
|
||||
- ./data/assets/ssl:/var/lib/acme/:rw
|
||||
- ./data/assets/ssl-example:/var/lib/ssl-example/:ro
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
restart: always
|
||||
networks:
|
||||
mailcow-network:
|
||||
|
@ -328,13 +337,14 @@ services:
|
|||
- /lib/modules:/lib/modules:ro
|
||||
|
||||
watchdog-mailcow:
|
||||
image: mailcow/watchdog:1.19
|
||||
image: mailcow/watchdog:1.24
|
||||
# Debug
|
||||
#command: /watchdog.sh
|
||||
build: ./data/Dockerfiles/watchdog
|
||||
oom_kill_disable: true
|
||||
volumes:
|
||||
- rspamd-sock:/rspamd-sock
|
||||
- rspamd-vol-1:/var/lib/rspamd
|
||||
- mysql-socket-vol-1:/var/run/mysqld/
|
||||
restart: always
|
||||
environment:
|
||||
- LOG_LINES=${LOG_LINES:-9999}
|
||||
|
@ -354,7 +364,7 @@ services:
|
|||
- watchdog
|
||||
|
||||
dockerapi-mailcow:
|
||||
image: mailcow/dockerapi:1.13
|
||||
image: mailcow/dockerapi:1.18
|
||||
restart: always
|
||||
build: ./data/Dockerfiles/dockerapi
|
||||
oom_kill_disable: true
|
||||
|
@ -363,6 +373,7 @@ services:
|
|||
volumes:
|
||||
- /var/run/docker.sock:/var/run/docker.sock:ro
|
||||
- ./data/conf/rspamd/override.d/worker-controller-password.inc:/access.inc:rw
|
||||
- vmail-vol-1:/var/vmail:ro
|
||||
networks:
|
||||
mailcow-network:
|
||||
aliases:
|
||||
|
@ -390,8 +401,8 @@ networks:
|
|||
volumes:
|
||||
vmail-vol-1:
|
||||
mysql-vol-1:
|
||||
mysql-socket-vol-1:
|
||||
redis-vol-1:
|
||||
rspamd-vol-1:
|
||||
postfix-vol-1:
|
||||
crypt-vol-1:
|
||||
rspamd-sock:
|
||||
|
|
|
@ -104,6 +104,12 @@ TZ=${MAILCOW_TZ}
|
|||
# Fixed project name
|
||||
COMPOSE_PROJECT_NAME=mailcowdockerized
|
||||
|
||||
# Garbage collector cleanup
|
||||
# Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring
|
||||
# How long should objects remain in the garbage until they are being deleted? (value in minutes)
|
||||
# Check interval is hourly
|
||||
MAILDIR_GC_TIME=1440
|
||||
|
||||
# Additional SAN for the certificate
|
||||
ADDITIONAL_SAN=
|
||||
|
||||
|
|
|
@ -5,8 +5,8 @@ if [[ ! ${1} =~ (backup|restore) ]]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
if [[ ${1} == "backup" && ! ${2} =~ (vmail|redis|rspamd|postfix|mysql|all) ]]; then
|
||||
echo "Second parameter needs to be 'vmail', 'redis', 'rspamd', 'postfix', 'mysql' or 'all'"
|
||||
if [[ ${1} == "backup" && ! ${2} =~ (crypt|vmail|redis|rspamd|postfix|mysql|all) ]]; then
|
||||
echo "Second parameter needs to be 'vmail', 'crypt', 'redis', 'rspamd', 'postfix', 'mysql' or 'all'"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
@ -62,6 +62,12 @@ function backup() {
|
|||
-v $(docker volume ls -qf name=${CMPS_PRJ}_vmail-vol-1):/vmail \
|
||||
debian:stretch-slim /bin/tar --warning='no-file-ignored' -Pcvpzf /backup/backup_vmail.tar.gz /vmail
|
||||
;;&
|
||||
crypt|all)
|
||||
docker run --rm \
|
||||
-v ${BACKUP_LOCATION}/mailcow-${DATE}:/backup \
|
||||
-v $(docker volume ls -qf name=${CMPS_PRJ}_crypt-vol-1):/crypt \
|
||||
debian:stretch-slim /bin/tar --warning='no-file-ignored' -Pcvpzf /backup/backup_crypt.tar.gz /crypt
|
||||
;;&
|
||||
redis|all)
|
||||
docker exec $(docker ps -qf name=redis-mailcow) redis-cli save
|
||||
docker run --rm \
|
||||
|
@ -128,6 +134,14 @@ function restore() {
|
|||
debian:stretch-slim /bin/tar -Pxvzf /backup/backup_redis.tar.gz
|
||||
docker start $(docker ps -aqf name=redis-mailcow)
|
||||
;;
|
||||
crypt)
|
||||
docker stop $(docker ps -qf name=dovecot-mailcow)
|
||||
docker run -it --rm \
|
||||
-v ${RESTORE_LOCATION}:/backup \
|
||||
-v $(docker volume ls -qf name=${CMPS_PRJ}_crypt-vol-1):/crypt \
|
||||
debian:stretch-slim /bin/tar -Pxvzf /backup/backup_crypt.tar.gz
|
||||
docker start $(docker ps -aqf name=dovecot-mailcow)
|
||||
;;
|
||||
rspamd)
|
||||
docker stop $(docker ps -qf name=rspamd-mailcow)
|
||||
docker run -it --rm \
|
||||
|
@ -189,7 +203,7 @@ elif [[ ${1} == "restore" ]]; then
|
|||
echo
|
||||
declare -A FILE_SELECTION
|
||||
RESTORE_POINT="${FOLDER_SELECTION[${input_sel}]}"
|
||||
if [[ -z $(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 -type f -regex ".*\(redis\|rspamd\|mysql\|vmail\|postfix\).*") ]]; then
|
||||
if [[ -z $(find "${FOLDER_SELECTION[${input_sel}]}" -maxdepth 1 -type f -regex ".*\(redis\|rspamd\|mysql\|crypt\|vmail\|postfix\).*") ]]; then
|
||||
echo "No datasets found"
|
||||
exit 1
|
||||
fi
|
||||
|
@ -198,6 +212,10 @@ elif [[ ${1} == "restore" ]]; then
|
|||
echo "[ ${i} ] - Mail directory (/var/vmail)"
|
||||
FILE_SELECTION[${i}]="vmail"
|
||||
((i++))
|
||||
elif [[ ${file} =~ crypt ]]; then
|
||||
echo "[ ${i} ] - Crypt data"
|
||||
FILE_SELECTION[${i}]="crypt"
|
||||
((i++))
|
||||
elif [[ ${file} =~ redis ]]; then
|
||||
echo "[ ${i} ] - Redis DB"
|
||||
FILE_SELECTION[${i}]="redis"
|
||||
|
|
|
@ -0,0 +1,31 @@
|
|||
version: '2.1'
|
||||
services:
|
||||
|
||||
php-fpm-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
sogo-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
dovecot-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
postfix-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
acme-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
watchdog-mailcow:
|
||||
volumes:
|
||||
- /var/run/mysqld/mysqld.sock:/var/run/mysqld/mysqld.sock
|
||||
|
||||
mysql-mailcow:
|
||||
image: alpine:3.8
|
||||
command: /bin/true
|
||||
restart: "no"
|
|
@ -64,7 +64,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
|||
|
||||
ADMIN_NC_PASS=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
||||
|
||||
curl -L# -o nextcloud.tar.bz2 "https://download.nextcloud.com/server/releases/latest-13.tar.bz2" || { echo "Failed to download Nextcloud archive."; exit 1; } \
|
||||
curl -L# -o nextcloud.tar.bz2 "https://download.nextcloud.com/server/releases/latest-14.tar.bz2" || { echo "Failed to download Nextcloud archive."; exit 1; } \
|
||||
&& tar -xjf nextcloud.tar.bz2 -C ./data/web/ \
|
||||
&& rm nextcloud.tar.bz2 \
|
||||
&& rm -rf ./data/web/nextcloud/updater \
|
||||
|
|
12
update.sh
12
update.sh
|
@ -12,7 +12,6 @@ DATE=$(date +%Y-%m-%d_%H_%M_%S)
|
|||
BRANCH=$(git rev-parse --abbrev-ref HEAD)
|
||||
|
||||
docker_garbage() {
|
||||
echo -e "\e[32mCollecting garbage...\e[0m"
|
||||
IMGS_TO_DELETE=()
|
||||
for container in $(grep -oP "image: \Kmailcow.+" docker-compose.yml); do
|
||||
REPOSITORY=${container/:*}
|
||||
|
@ -74,6 +73,7 @@ while (($#)); do
|
|||
MERGE_STRATEGY=ours
|
||||
;;
|
||||
--gc)
|
||||
echo -e "\e[32mCollecting garbage...\e[0m"
|
||||
docker_garbage
|
||||
exit 0
|
||||
;;
|
||||
|
@ -119,6 +119,7 @@ CONFIG_ARRAY=(
|
|||
"SQL_PORT"
|
||||
"API_KEY"
|
||||
"API_ALLOW_FROM"
|
||||
"MAILDIR_GC_TIME"
|
||||
)
|
||||
|
||||
sed -i '$a\' mailcow.conf
|
||||
|
@ -200,6 +201,15 @@ for option in ${CONFIG_ARRAY[@]}; do
|
|||
echo '# Use this IPv6 for outgoing connections (SNAT)' >> mailcow.conf
|
||||
echo "#SNAT6_TO_SOURCE=" >> mailcow.conf
|
||||
fi
|
||||
elif [[ ${option} == "MAILDIR_GC_TIME" ]]; then
|
||||
if ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo '# Garbage collector cleanup' >> mailcow.conf
|
||||
echo '# Deleted domains and mailboxes are moved to /var/vmail/_garbage/timestamp_sanitizedstring' >> mailcow.conf
|
||||
echo '# How long should objects remain in the garbage until they are being deleted? (value in minutes)' >> mailcow.conf
|
||||
echo '# Check interval is hourly' >> mailcow.conf
|
||||
echo 'MAILDIR_GC_TIME=1440' >> mailcow.conf
|
||||
fi
|
||||
elif ! grep -q ${option} mailcow.conf; then
|
||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||
echo "${option}=n" >> mailcow.conf
|
||||
|
|
Loading…
Reference in New Issue