[Docker API] Use TLS encryption for communication with "on-the-fly" created key paris (non-exposed)

[Docker API] Create pipe to pass Rspamd UI worker password
[Dovecot] Pull Spamassassin ruleset to be read by Rspamd (MANY THANKS to Peer Heinlein!)
[Dovecot] Garbage collector for deleted maildirs (set keep time via MAILDIR_GC_TIME which defaults to 1440 minutes)
[Web] Flush memcached after mailbox item changes, fixes #1808
[Web] Fix duplicate IDs, fixes #1792
[Compose] Use SQL sockets
[PHP-FPM] Update APCu and Redis libs
[Dovecot] Encrypt maildir with global key pair in crypt-vol-1 (BACKUP!), also fixes #1791
[Web] Fix deletion of spam aliases
[Helper] Add "crypt" to backup script
[Helper] Override file for external SQL socket (not supported!)
[Compose] New images for Rspamd, PHP-FPM, SOGo, Dovecot, Docker API, Watchdog, ACME, Postfix
master
André 2018-09-29 22:01:23 +02:00
parent 96c985abad
commit 0fb43f4916
49 changed files with 11437 additions and 419 deletions

View File

@ -37,7 +37,7 @@ mkdir -p ${ACME_BASE}/acme/private
restart_containers(){ restart_containers(){
for container in $*; do for container in $*; do
log_f "Restarting ${container}..." no_nl 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 log_f "${C_REST_OUT}" no_date
done done
} }
@ -125,7 +125,7 @@ else
fi fi
log_f "Waiting for database... " 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 sleep 2
done done
log_f "Initializing, please wait... " log_f "Initializing, please wait... "
@ -161,19 +161,19 @@ while true; do
fi fi
# Container ids may have changed # 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 log_f "Waiting for domain table... " no_nl
while [[ -z ${DOMAIN_TABLE} ]]; do while [[ -z ${DOMAIN_TABLE} ]]; do
curl --silent http://nginx/ >/dev/null 2>&1 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 [[ -z ${DOMAIN_TABLE} ]] && sleep 10
done done
log_f "OK" no_date log_f "OK" no_date
while read domains; do while read domains; do
SQL_DOMAIN_ARR+=("${domains}") 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 for SQL_DOMAIN in "${SQL_DOMAIN_ARR[@]}"; do
A_CONFIG=$(dig A autoconfig.${SQL_DOMAIN} +short | tail -n 1) A_CONFIG=$(dig A autoconfig.${SQL_DOMAIN} +short | tail -n 1)

View File

@ -1,8 +1,10 @@
FROM python:2-alpine FROM alpine:3.8
LABEL maintainer "Andre Peters <andre.peters@servercow.de>" LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
RUN apk add -U --no-cache iptables ip6tables tzdata RUN apk add -U --no-cache python2 python-dev py-pip gcc musl-dev tzdata openssl-dev libffi-dev \
RUN pip install docker==3.0.1 flask flask-restful && pip2 install --upgrade docker==3.0.1 flask flask-restful pyOpenSSL \
&& apk del python-dev py2-pip gcc
COPY server.py / COPY server.py /
CMD ["python2", "-u", "/server.py"] CMD ["python2", "-u", "/server.py"]

View File

@ -3,12 +3,16 @@ from flask_restful import Resource, Api
from flask import jsonify from flask import jsonify
from flask import request from flask import request
from threading import Thread from threading import Thread
from OpenSSL import crypto
import docker import docker
import uuid
import signal import signal
import time import time
import os import os
import re import re
import sys import sys
import ssl
import socket
docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto') docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
app = Flask(__name__) app = Flask(__name__)
@ -93,22 +97,74 @@ class container_post(Resource):
return sieve_return.output return sieve_return.output
except Exception as e: except Exception as e:
return jsonify(type='danger', msg=str(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", "/bin/mv '/var/vmail/" + request.json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'"], 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']: elif request.json['cmd'] == 'worker_password' and request.json['raw']:
try: try:
for container in docker_client.containers.list(filters={"id": container_id}): 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') worker_shell = container.exec_run(["/bin/bash"], stdin=True, socket=True, user='_rspamd')
if hash.exit_code == 0: worker_cmd = "/usr/bin/rspamadm pw -e -p '" + request.json['raw'].replace("'", "'\\''") + "' 2> /dev/null\n"
hash_stdout = str(hash.output) worker_socket = worker_shell.output;
for line in hash_stdout.split("\n"): 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: if '$2$' in line:
matched = True
hash = line.strip() hash = line.strip()
hash_out = re.search('\$2\$.+$', hash).group(0)
f = open("/access.inc", "w") 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() f.close()
container.restart() container.restart()
if matched:
return jsonify(type='success', msg='command completed successfully') return jsonify(type='success', msg='command completed successfully')
else: 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: except Exception as e:
return jsonify(type='danger', msg=str(e)) return jsonify(type='danger', msg=str(e))
elif request.json['cmd'] == 'mailman_password' and request.json['email'] and request.json['passwd']: elif request.json['cmd'] == 'mailman_password' and request.json['email'] and request.json['passwd']:
@ -137,11 +193,62 @@ class GracefulKiller:
signal.signal(signal.SIGINT, self.exit_gracefully) signal.signal(signal.SIGINT, self.exit_gracefully)
signal.signal(signal.SIGTERM, self.exit_gracefully) signal.signal(signal.SIGTERM, self.exit_gracefully)
def exit_gracefully(self,signum, frame): def exit_gracefully(self, signum, frame):
self.kill_now = True self.kill_now = True
def startFlaskAPI(): 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(containers_get, '/containers/json')
api.add_resource(container_get, '/containers/<string:container_id>/json') api.add_resource(container_get, '/containers/<string:container_id>/json')

View File

@ -14,6 +14,7 @@ RUN apt-get update && apt-get -y --no-install-recommends install \
cpanminus \ cpanminus \
curl \ curl \
default-libmysqlclient-dev \ default-libmysqlclient-dev \
dnsutils \
libjson-webtoken-perl \ libjson-webtoken-perl \
libcgi-pm-perl \ libcgi-pm-perl \
libcrypt-openssl-rsa-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 cpanm Data::Uniqid Mail::IMAPClient String::Util
RUN echo '* * * * * root /usr/local/bin/imapsync_cron.pl' > /etc/cron.d/imapsync 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 '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 '30 2 * * * 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 trim_logs.sh /usr/local/bin/trim_logs.sh
COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf COPY syslog-ng.conf /etc/syslog-ng/syslog-ng.conf
COPY imapsync /usr/local/bin/imapsync 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 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-ham /usr/local/lib/dovecot/sieve/rspamd-pipe-ham
COPY rspamd-pipe-spam /usr/local/lib/dovecot/sieve/rspamd-pipe-spam 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 docker-entrypoint.sh /
COPY supervisord.conf /etc/supervisor/supervisord.conf 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/imapsync_cron.pl \
/usr/local/bin/postlogin.sh \ /usr/local/bin/postlogin.sh \
/usr/local/bin/imapsync \ /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 \ RUN groupadd -g 5000 vmail \
&& groupadd -g 401 dovecot \ && groupadd -g 401 dovecot \

View File

@ -2,7 +2,7 @@
set -e set -e
# Wait for MySQL to warm-up # 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..." echo "Waiting for database to come up..."
sleep 2 sleep 2
done done
@ -15,6 +15,7 @@ sed -i "s/LOG_LINES/${LOG_LINES}/g" /usr/local/bin/trim_logs.sh
# Create missing directories # Create missing directories
[[ ! -d /usr/local/etc/dovecot/sql/ ]] && mkdir -p /usr/local/etc/dovecot/sql/ [[ ! -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 /var/vmail/sieve ]] && mkdir -p /var/vmail/sieve
[[ ! -d /etc/sogo ]] && mkdir -p /etc/sogo [[ ! -d /etc/sogo ]] && mkdir -p /etc/sogo
@ -23,7 +24,7 @@ DBPASS=$(echo ${DBPASS} | sed 's/"/\\"/g')
# Create quota dict for Dovecot # Create quota dict for Dovecot
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-quota.conf 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 { map {
pattern = priv/quota/storage pattern = priv/quota/storage
table = quota2 table = quota2
@ -40,7 +41,7 @@ EOF
# Create dict used for sieve pre and postfilters # Create dict used for sieve pre and postfilters
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_before.conf 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 { map {
pattern = priv/sieve/name/\$script_name pattern = priv/sieve/name/\$script_name
table = sieve_before table = sieve_before
@ -62,7 +63,7 @@ map {
EOF EOF
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-sieve_after.conf 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 { map {
pattern = priv/sieve/name/\$script_name pattern = priv/sieve/name/\$script_name
table = sieve_after table = sieve_after
@ -87,7 +88,7 @@ EOF
# Create userdb dict for Dovecot # Create userdb dict for Dovecot
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-userdb.conf cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-userdb.conf
driver = mysql 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' 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'; iterate_query = SELECT username FROM mailbox WHERE active='1';
EOF EOF
@ -95,7 +96,7 @@ EOF
# Create pass dict for Dovecot # Create pass dict for Dovecot
cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-passdb.conf cat <<EOF > /usr/local/etc/dovecot/sql/dovecot-dict-sql-passdb.conf
driver = mysql 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 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%%' 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 EOF
@ -106,6 +107,7 @@ cat /usr/local/etc/dovecot/sieve_after > /var/vmail/sieve/global.sieve
# Check permissions of vmail directory. # 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. # 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/) != "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 # Create random master for SOGo sieve features
RAND_USER=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 16 | head -n 1) RAND_USER=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 16 | head -n 1)
@ -139,7 +141,7 @@ touch /etc/crontab /etc/cron.*/*
# Clean stopped imapsync jobs # Clean stopped imapsync jobs
rm -f /tmp/imapsync_busy.lock rm -f /tmp/imapsync_busy.lock
IMAPSYNC_TABLE=$(mysql -h mysql-mailcow -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "SHOW TABLES LIKE 'imapsync'" -Bs) IMAPSYNC_TABLE=$(mysql --socket=/var/run/mysqld/mysqld.sock -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'" [[ ! -z ${IMAPSYNC_TABLE} ]] && mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "UPDATE imapsync SET is_running='0'"
exec "$@" exec "$@"

View File

@ -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 {} \;

View File

@ -1,4 +1,3 @@
#!/bin/sh #!/bin/sh
export MASTER_USER=$USER export MASTER_USER=$USER
exec "$@" exec "$@"

View File

@ -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 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 https://dockerapi/containers/${CONTAINER_ID}/restart
fi
fi
fi
rm -r /tmp/sa-rules-heinlein /tmp/sa-rules.tar.gz

View File

@ -1,8 +1,7 @@
#!/bin/bash #!/bin/bash
/usr/bin/redis-cli -h redis LTRIM ACME_LOG 0 LOG_LINES
redis-cli -h redis LTRIM ACME_LOG 0 LOG_LINES /usr/bin/redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 LOG_LINES
redis-cli -h redis LTRIM POSTFIX_MAILLOG 0 LOG_LINES /usr/bin/redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 LOG_LINES
redis-cli -h redis LTRIM DOVECOT_MAILLOG 0 LOG_LINES /usr/bin/redis-cli -h redis LTRIM SOGO_LOG 0 LOG_LINES
redis-cli -h redis LTRIM SOGO_LOG 0 LOG_LINES /usr/bin/redis-cli -h redis LTRIM NETFILTER_LOG 0 LOG_LINES
redis-cli -h redis LTRIM NETFILTER_LOG 0 LOG_LINES /usr/bin/redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 LOG_LINES
redis-cli -h redis LTRIM AUTODISCOVER_LOG 0 LOG_LINES

View File

@ -1,11 +1,11 @@
FROM php:7.2-fpm-alpine3.7 FROM php:7.2-fpm-alpine3.7
LABEL maintainer "Andre Peters <andre.peters@servercow.de>" 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 IMAGICK_PECL 3.4.3
ENV MAILPARSE_PECL 3.0.2 ENV MAILPARSE_PECL 3.0.2
ENV MEMCACHED_PECL 3.0.4 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 \ RUN apk add -U --no-cache autoconf \
bash \ bash \

View File

@ -4,11 +4,13 @@ set -e
function array_by_comma { local IFS=","; echo "$*"; } function array_by_comma { local IFS=","; echo "$*"; }
# Wait for containers # 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 sleep 2
done done
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do
echo "Waiting for Redis..."
sleep 2 sleep 2
done done
@ -18,11 +20,11 @@ redis-cli -h redis-mailcow DEL DOMAIN_MAP
while read line while read line
do do
DOMAIN_ARR+=("$line") 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 while read line
do do
DOMAIN_ARR+=("$line") 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 if [[ ! -z ${DOMAIN_ARR} ]]; then
for domain in "${DOMAIN_ARR[@]}"; do for domain in "${DOMAIN_ARR[@]}"; do
@ -48,7 +50,7 @@ if [[ ${API_ALLOW_FROM} != "invalid" ]] && \
done done
VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]}) VALIDATED_IPS=$(array_by_comma ${VALIDATED_API_ALLOW_FROM_ARR[*]})
if [[ ! -z ${VALIDATED_IPS} ]]; then 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) INSERT INTO api (username, api_key, active, allow_from)
SELECT username, "${API_KEY}", '1', "${VALIDATED_IPS}" FROM admin WHERE superadmin='1' AND active='1' 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}"; ON DUPLICATE KEY UPDATE active = '1', allow_from = "${VALIDATED_IPS}", api_key = "${API_KEY}";

View File

@ -14,7 +14,7 @@ newaliases;
cat <<EOF > /opt/postfix/conf/sql/mysql_relay_recipient_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_relay_recipient_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT DISTINCT query = SELECT DISTINCT
CASE WHEN '%d' IN ( CASE WHEN '%d' IN (
@ -32,7 +32,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf cat <<EOF > /opt/postfix/conf/sql/mysql_tls_enforce_in_policy.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT IF(EXISTS( query = SELECT IF(EXISTS(
SELECT 'TLS_ACTIVE' FROM alias SELECT 'TLS_ACTIVE' FROM alias
@ -49,7 +49,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_sender_dependent_default_transport_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT GROUP_CONCAT(transport SEPARATOR '') AS transport_maps query = SELECT GROUP_CONCAT(transport SEPARATOR '') AS transport_maps
FROM ( FROM (
@ -80,7 +80,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_sasl_passwd_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM relayhosts query = SELECT CONCAT_WS(':', username, password) AS auth_data FROM relayhosts
WHERE id IN ( WHERE id IN (
@ -96,7 +96,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_catchall_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_catchall_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT goto FROM alias, alias_domain query = SELECT goto FROM alias, alias_domain
WHERE alias_domain.alias_domain = '%d' WHERE alias_domain.alias_domain = '%d'
@ -107,7 +107,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_domain_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT username FROM mailbox, alias_domain query = SELECT username FROM mailbox, alias_domain
WHERE alias_domain.alias_domain = '%d' WHERE alias_domain.alias_domain = '%d'
@ -119,7 +119,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_alias_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT goto FROM alias query = SELECT goto FROM alias
WHERE address='%s' WHERE address='%s'
@ -129,7 +129,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_bcc_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT bcc_dest FROM bcc_maps query = SELECT bcc_dest FROM bcc_maps
WHERE local_dest='%s' WHERE local_dest='%s'
@ -140,7 +140,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_sender_bcc_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_sender_bcc_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT bcc_dest FROM bcc_maps query = SELECT bcc_dest FROM bcc_maps
WHERE local_dest='%s' WHERE local_dest='%s'
@ -151,7 +151,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_recipient_canonical_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT new_dest FROM recipient_maps query = SELECT new_dest FROM recipient_maps
WHERE old_dest='%s' WHERE old_dest='%s'
@ -161,7 +161,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_domains_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT alias_domain from alias_domain WHERE alias_domain='%s' AND active='1' query = SELECT alias_domain from alias_domain WHERE alias_domain='%s' AND active='1'
UNION UNION
@ -174,7 +174,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_mailbox_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1' query = SELECT maildir FROM mailbox WHERE username='%s' AND active = '1'
EOF EOF
@ -182,7 +182,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_relay_domain_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '1' AND active = '1' query = SELECT domain FROM domain WHERE domain='%s' AND backupmx = '1' AND active = '1'
EOF EOF
@ -190,7 +190,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_sender_acl.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_sender_acl.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
# First select queries domain and alias_domain to determine if domains are active. # First select queries domain and alias_domain to determine if domains are active.
query = SELECT goto FROM alias query = SELECT goto FROM alias
@ -231,7 +231,7 @@ EOF
cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf cat <<EOF > /opt/postfix/conf/sql/mysql_virtual_spamalias_maps.cf
user = ${DBUSER} user = ${DBUSER}
password = ${DBPASS} password = ${DBPASS}
hosts = mysql hosts = unix:/var/run/mysqld/mysqld.sock
dbname = ${DBNAME} dbname = ${DBNAME}
query = SELECT goto FROM spamalias query = SELECT goto FROM spamalias
WHERE address='%s' WHERE address='%s'

View File

@ -2,5 +2,6 @@
chown -R _rspamd:_rspamd /var/lib/rspamd chown -R _rspamd:_rspamd /var/lib/rspamd
[[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Placeholder' > /etc/rspamd/override.d/worker-controller-password.inc [[ ! -f /etc/rspamd/override.d/worker-controller-password.inc ]] && echo '# Placeholder' > /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 "$@" exec "$@"

View File

@ -1,7 +1,7 @@
#!/bin/bash #!/bin/bash
# Wait for MySQL to warm-up # 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..." echo "Waiting for database to come up..."
sleep 2 sleep 2
done done
@ -15,10 +15,10 @@ done
# Recreate view # 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 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 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 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, '($|,)') 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' WHERE mailbox.active = '1'
GROUP BY mailbox.username; GROUP BY mailbox.username;
EOF 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 VIEW_OK=OK
else else
echo "Will retry to setup SOGo view in 3s" 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 # Wait for static view table if missing after update and update content
while [[ ${STATIC_VIEW_OK} != 'OK' ]]; do 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 STATIC_VIEW_OK=OK
echo "Updating _sogo_static_view content..." 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 --socket=/var/run/mysqld/mysqld.sock -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 "DELETE FROM _sogo_static_view WHERE c_uid NOT IN (SELECT username FROM mailbox WHERE active = '1')"
else else
echo "Waiting for database initialization..." echo "Waiting for database initialization..."
sleep 3 sleep 3
@ -50,10 +50,10 @@ done
# Recreate password update trigger # 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 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 - DELIMITER -
CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view CREATE TRIGGER sogo_update_password AFTER UPDATE ON _sogo_static_view
FOR EACH ROW FOR EACH ROW
@ -63,7 +63,7 @@ END;
- -
DELIMITER ; DELIMITER ;
EOF 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 TRIGGER_OK=OK
else else
echo "Will retry to setup SOGo password update trigger in 3s" 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"> <plist version="0.9">
<dict> <dict>
<key>OCSAclURL</key> <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> <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> <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> <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> <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> <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> <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> <key>SOGoTimeZone</key>
<string>${TZ}</string> <string>${TZ}</string>
<key>domains</key> <key>domains</key>
@ -138,11 +138,11 @@ while read line
<key>prependPasswordScheme</key> <key>prependPasswordScheme</key>
<string>YES</string> <string>YES</string>
<key>viewURL</key> <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> </dict>
</array> </array>
</dict>" >> /var/lib/sogo/GNUstep/Defaults/sogod.plist </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 # Generate footer
echo ' </dict> echo ' </dict>

View File

@ -68,12 +68,12 @@ get_container_ip() {
until [[ ${CONTAINER_IP} =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]] || [[ ${LOOP_C} -gt 5 ]]; do 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 sleep 0.5
# get long container id for exact match # 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 # returned id can have multiple elements (if scaled), shuffle for random test
CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf)) CONTAINER_ID=($(printf "%s\n" "${CONTAINER_ID[@]}" | shuf))
if [[ ! -z ${CONTAINER_ID} ]]; then if [[ ! -z ${CONTAINER_ID} ]]; then
for matched_container in "${CONTAINER_ID[@]}"; do for matched_container in "${CONTAINER_ID[@]}"; do
CONTAINER_IPS=($(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 for ip_match in "${CONTAINER_IPS[@]}"; do
# grep will do nothing if one of these vars is empty # grep will do nothing if one of these vars is empty
[[ -z ${ip_match} ]] && continue [[ -z ${ip_match} ]] && continue
@ -123,8 +123,8 @@ mysql_checks() {
while [ ${err_count} -lt ${THRESHOLD} ]; do while [ ${err_count} -lt ${THRESHOLD} ]; do
host_ip=$(get_container_ip mysql-mailcow) host_ip=$(get_container_ip mysql-mailcow)
err_c_cur=${err_count} 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 -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 -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_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} -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} )) [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
progress "MySQL/MariaDB" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} progress "MySQL/MariaDB" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
@ -342,12 +342,12 @@ done
# Monitor dockerapi # Monitor dockerapi
( (
while true; do while true; do
while nc -z dockerapi 8080; do while nc -z dockerapi 443; do
sleep 3 sleep 3
done done
log_msg "Cannot find dockerapi-mailcow, waiting to recover..." log_msg "Cannot find dockerapi-mailcow, waiting to recover..."
kill -STOP ${BACKGROUND_TASKS[*]} kill -STOP ${BACKGROUND_TASKS[*]}
until nc -z dockerapi 8080; do until nc -z dockerapi 443; do
sleep 3 sleep 3
done done
kill -CONT ${BACKGROUND_TASKS[*]} kill -CONT ${BACKGROUND_TASKS[*]}
@ -362,10 +362,10 @@ while true; do
if [[ ${com_pipe_answer} =~ .+-mailcow ]]; then if [[ ${com_pipe_answer} =~ .+-mailcow ]]; then
kill -STOP ${BACKGROUND_TASKS[*]} kill -STOP ${BACKGROUND_TASKS[*]}
sleep 3 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 if [[ ! -z ${CONTAINER_ID} ]]; then
log_msg "Sending restart command to ${CONTAINER_ID}..." 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 fi
log_msg "Wait for restarted container to settle and continue watching..." log_msg "Wait for restarted container to settle and continue watching..."
sleep 30s sleep 30s

View File

@ -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 "$@"

View File

@ -14,7 +14,7 @@ disable_plaintext_auth = yes
login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k" login_log_format_elements = "user=<%u> method=%m rip=%r lip=%l mpid=%e %c %k"
mail_home = /var/vmail/%d/%n mail_home = /var/vmail/%d/%n
mail_location = maildir:~/ 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 # Dovecot 2.2
#ssl_protocols = !SSLv3 #ssl_protocols = !SSLv3
@ -223,7 +223,7 @@ service pop3-login {
} }
service imap { service imap {
executable = imap imap-postlogin executable = imap imap-postlogin
user = dovenull user = vmail
vsz_limit = 256 M vsz_limit = 256 M
} }
service managesieve { service managesieve {
@ -244,11 +244,11 @@ userdb {
} }
protocol imap { protocol imap {
imap_metadata = yes 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 mail_attribute_dict = file:%h/dovecot-attributes
protocol lmtp { 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 auth_socket_path = /usr/local/var/run/dovecot/auth-master
} }
protocol sieve { protocol sieve {
@ -288,9 +288,12 @@ plugin {
sieve_before = dict:proxy::sieve_before;name=active;bindir=/var/vmail/sieve_before_bindir 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_after = dict:proxy::sieve_after;name=active;bindir=/var/vmail/sieve_after_bindir
sieve_after2 = /var/vmail/sieve/global.sieve 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 # -- Global keys
#mail_crypt_save_version = 2 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+ # Enable compression while saving, lz4 Dovecot v2.2.11+
zlib_save = lz4 zlib_save = lz4
} }

File diff suppressed because it is too large Load Diff

View File

@ -9,7 +9,8 @@ require_once "vars.inc.php";
ini_set('error_reporting', 0); 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 = [ $opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,

View File

@ -6,7 +6,8 @@ require_once "vars.inc.php";
// Do not show errors, we log to using error_log // Do not show errors, we log to using error_log
ini_set('error_reporting', 0); ini_set('error_reporting', 0);
// Init database // 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 = [ $opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,

View File

@ -1 +1 @@
# Placeholder enable_password = "$2$gtgqjrojzkhoxjis6tygn6sexd8nonah$zi9m3bwnmhtosh4rgqwrdruixx56t8d31iez4mooxqd8a7onaoxy";

View File

@ -22,25 +22,25 @@ $tfa_data = get_tfa();
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label> <label class="control-label col-sm-3" for="admin_user"><?=$lang['admin']['admin'];?>:</label>
<div class="col-sm-9"> <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>
&rdsh; <kbd>a-z A-Z - _ .</kbd> &rdsh; <kbd>a-z A-Z - _ .</kbd>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="admin_pass"><?=$lang['admin']['password'];?>:</label> <label class="control-label col-sm-3" for="admin_pass"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-9"> <div class="col-sm-9">
<input type="password" data-hibp="true" 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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="admin_pass2"><?=$lang['admin']['password_repeat'];?>:</label> <label class="control-label col-sm-3" for="admin_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-9"> <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> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-3 col-sm-9"> <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>
</div> </div>
</form> </form>
@ -124,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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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 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> </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> <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> </div>
@ -155,13 +155,13 @@ $tfa_data = get_tfa();
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="rspamd_ui_pass"><?=$lang['admin']['password'];?>:</label> <label class="control-label col-sm-3" for="rspamd_ui_pass"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-9"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="rspamd_ui_pass2"><?=$lang['admin']['password_repeat'];?>:</label> <label class="control-label col-sm-3" for="rspamd_ui_pass2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-9"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -201,7 +201,7 @@ $tfa_data = get_tfa();
<div class="mass-actions-admin"> <div class="mass-actions-admin">
<div class="btn-group btn-group-sm"> <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="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>
</div> </div>
<?php <?php
@ -309,7 +309,7 @@ $tfa_data = get_tfa();
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="domain">Selector</label> <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>
<div class="form-group"> <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> <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>
@ -317,7 +317,7 @@ $tfa_data = get_tfa();
<option data-subtext="bits">2048</option> <option data-subtext="bits">2048</option>
</select> </select>
</div> </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> </form>
<legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" id="import_dkim_legend" unselectable="on" data-toggle="collapse"> <legend data-target="#import_dkim" style="margin-top:40px;cursor:pointer" id="import_dkim_legend" unselectable="on" data-toggle="collapse">
@ -327,17 +327,17 @@ $tfa_data = get_tfa();
<form class="form" data-id="dkim_import" role="form" method="post"> <form class="form" data-id="dkim_import" role="form" method="post">
<div class="form-group"> <div class="form-group">
<label for="domain">Domain:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="domain">Selector:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="private_key_file"><?=$lang['admin']['private_key'];?>:</label> <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> <textarea class="form-control input-sm" rows="10" name="private_key_file" id="private_key_file" required placeholder="-----BEGIN RSA KEY-----"></textarea>
</div> </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> </form>
</div> </div>
@ -383,7 +383,7 @@ $tfa_data = get_tfa();
</select> </select>
</div> </div>
</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> </form>
</div> </div>
@ -403,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> <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> <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"> <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 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 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":"1"}' href="#">Disable spam filter</a></li>
<li role="separator" class="divider"></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> </ul>
</div> </div>
</div> </div>
@ -415,7 +415,7 @@ $tfa_data = get_tfa();
<form class="form" data-id="fwdhost" role="form" method="post"> <form class="form" data-id="fwdhost" role="form" method="post">
<div class="form-group"> <div class="form-group">
<label for="hostname"><?=$lang['admin']['host'];?></label> <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>
<div class="form-group"> <div class="form-group">
<select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="<?=$lang['user']['spamfilter'];?>" required> <select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="<?=$lang['user']['spamfilter'];?>" required>
@ -423,7 +423,7 @@ $tfa_data = get_tfa();
<option value="0"><?=$lang['admin']['inactive'];?></option> <option value="0"><?=$lang['admin']['inactive'];?></option>
</select> </select>
</div> </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> </form>
</div> </div>
</div> </div>
@ -438,41 +438,41 @@ $tfa_data = get_tfa();
<form class="form" data-id="f2b" role="form" method="post"> <form class="form" data-id="f2b" role="form" method="post">
<div class="form-group"> <div class="form-group">
<label for="ban_time"><?=$lang['admin']['f2b_ban_time'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="max_attempts"><?=$lang['admin']['f2b_max_attempts'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="retry_window"><?=$lang['admin']['f2b_retry_window'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="netban_ipv4"><?=$lang['admin']['f2b_netban_ipv4'];?>:</label> <label for="netban_ipv4"><?=$lang['admin']['f2b_netban_ipv4'];?>:</label>
<div class="input-group"> <div class="input-group">
<span class="input-group-addon">/</span> <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> </div>
<div class="form-group"> <div class="form-group">
<label for="netban_ipv6"><?=$lang['admin']['f2b_netban_ipv6'];?>:</label> <label for="netban_ipv6"><?=$lang['admin']['f2b_netban_ipv6'];?>:</label>
<div class="input-group"> <div class="input-group">
<span class="input-group-addon">/</span> <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>
</div> </div>
<p class="help-block"><?=$lang['admin']['f2b_list_info'];?></p> <p class="help-block"><?=$lang['admin']['f2b_list_info'];?></p>
<div class="form-group"> <div class="form-group">
<label for="whitelist"><?=$lang['admin']['f2b_whitelist'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="blacklist"><?=$lang['admin']['f2b_blacklist'];?>:</label> <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>
<div class="btn-group"> <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> <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> </div>
</form> </form>
@ -490,9 +490,9 @@ $tfa_data = get_tfa();
<?php <?php
if ($active_bans['queued_for_unban'] == 0): 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 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 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 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 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":"blacklist"}' href="#">[blacklist]</a>
<?php <?php
else: else:
?> ?>
@ -527,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> <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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </ul>
</div> </div>
</div> </div>
@ -539,17 +539,17 @@ $tfa_data = get_tfa();
<form class="form" data-id="rlyhost" role="form" method="post"> <form class="form" data-id="rlyhost" role="form" method="post">
<div class="form-group"> <div class="form-group">
<label for="hostname"><?=$lang['admin']['host'];?></label> <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>
<div class="form-group"> <div class="form-group">
<label for="hostname"><?=$lang['admin']['username'];?></label> <label for="hostname"><?=$lang['admin']['username'];?></label>
<input class="form-control" id="username" name="username"> <input class="form-control" name="username">
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="hostname"><?=$lang['admin']['password'];?></label> <label for="hostname"><?=$lang['admin']['password'];?></label>
<input class="form-control" id="password" name="password"> <input class="form-control" name="password">
</div> </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> </form>
</div> </div>
</div> </div>
@ -564,19 +564,19 @@ $tfa_data = get_tfa();
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label for="retention_size"><?=$lang['admin']['quarantine_retention_size'];?></label> <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> </div>
<div class="col-sm-6"> <div class="col-sm-6">
<div class="form-group"> <div class="form-group">
<label for="max_size"><?=$lang['admin']['quarantine_max_size'];?></label> <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>
</div> </div>
<div class="form-group"> <div class="form-group">
<label for="exclude_domains"><?=$lang['admin']['quarantine_exclude_domains'];?></label><br /> <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 <?php
foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain): foreach (array_merge(mailbox('get', 'domains'), mailbox('get', 'alias_domains')) as $domain):
?> ?>
@ -586,7 +586,7 @@ $tfa_data = get_tfa();
?> ?>
</select> </select>
</div> </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> </form>
</div> </div>
</div> </div>
@ -648,19 +648,19 @@ $tfa_data = get_tfa();
<input type="hidden" name="active" value="0"> <input type="hidden" name="active" value="0">
<div class="form-group"> <div class="form-group">
<label for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="content"><?=$lang['admin']['rsetting_content'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label> <label>
<input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?> <input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?>
</label> </label>
</div> </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-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" 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-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> </form>
</div> </div>
<?php <?php
@ -743,7 +743,7 @@ $tfa_data = get_tfa();
?> ?>
</table> </table>
<p><div class="btn-group"> <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> <button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
</div></p> </div></p>
</form> </form>
@ -754,21 +754,21 @@ $tfa_data = get_tfa();
<form class="form" data-id="uitexts" role="form" method="post"> <form class="form" data-id="uitexts" role="form" method="post">
<div class="form-group"> <div class="form-group">
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="main_name"><?=$lang['admin']['main_name'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="apps_name"><?=$lang['admin']['apps_name'];?>:</label> <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>
<div class="form-group"> <div class="form-group">
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label> <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> <textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
</div> </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> </form>
</div> </div>
</div> </div>

View File

@ -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 = [ $opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,

View File

@ -39,13 +39,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="col-sm-10"> <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> <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"> <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>
<div class="checkbox"> <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>
<div class="checkbox"> <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> </div>
</div> </div>
@ -58,7 +58,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -92,7 +92,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domains"><?=$lang['edit']['domains'];?></label> <label class="control-label col-sm-2" for="domains"><?=$lang['edit']['domains'];?></label>
<div class="col-sm-10"> <div class="col-sm-10">
<select data-live-search="true" class="full-width-select" id="domains" name="domains" multiple required> <select data-live-search="true" class="full-width-select" name="domains" multiple required>
<?php <?php
foreach ($result['selected_domains'] as $domain): foreach ($result['selected_domains'] as $domain):
?> ?>
@ -111,13 +111,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label> <label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="password" data-hibp="true" class="form-control" name="password" id="password" placeholder=""> <input type="password" data-hibp="true" class="form-control" name="password" placeholder="">
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label> <label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -136,7 +136,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -159,7 +159,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<button class="btn btn-default" id="edit_selected" data-id="daacl" data-item="<?=htmlspecialchars($domain_admin);?>" data-api-url='edit/da-acl' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button> <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> </div>
</div> </div>
@ -189,7 +189,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['edit']['description'];?></label> <label class="control-label col-sm-2" for="description"><?=$lang['edit']['description'];?></label>
<div class="col-sm-10"> <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>
</div> </div>
<?php <?php
@ -198,31 +198,31 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="aliases"><?=$lang['edit']['max_aliases'];?></label> <label class="control-label col-sm-2" for="aliases"><?=$lang['edit']['max_aliases'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['edit']['max_mailboxes'];?></label> <label class="control-label col-sm-2" for="mailboxes"><?=$lang['edit']['max_mailboxes'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxquota"><?=$lang['edit']['max_quota'];?></label> <label class="control-label col-sm-2" for="maxquota"><?=$lang['edit']['max_quota'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="quota"><?=$lang['edit']['domain_quota'];?></label> <label class="control-label col-sm-2" for="quota"><?=$lang['edit']['domain_quota'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="quota">Relayhost</label> <label class="control-label col-sm-2" for="quota">Relayhost</label>
<div class="col-sm-10"> <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 <?php
foreach ($rlyhosts as $rlyhost) { foreach ($rlyhosts as $rlyhost) {
?> ?>
@ -257,7 +257,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -280,17 +280,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<form data-id="domratelimit" class="form-inline well" method="post"> <form data-id="domratelimit" class="form-inline well" method="post">
<div class="form-group"> <div class="form-group">
<label class="control-label">Ratelimit</label> <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>
<div class="form-group"> <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="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="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> <option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<button data-acl="<?=$_SESSION['acl']['ratelimit'];?>" 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> </div>
</form> </form>
<hr> <hr>
@ -304,15 +304,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="mass-actions-user"> <div class="mass-actions-user">
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> <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-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> </ul>
</div> </div>
</div> </div>
<form class="form-inline" data-id="add_wl_policy_domain"> <form class="form-inline" data-id="add_wl_policy_domain">
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> <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="text" class="form-control" name="object_from" placeholder="*@example.org" required>
<span class="input-group-btn"> <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> </span>
</div> </div>
</form> </form>
@ -326,15 +326,15 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="mass-actions-user"> <div class="mass-actions-user">
<div class="btn-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> <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-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> </ul>
</div> </div>
</div> </div>
<form class="form-inline" data-id="add_bl_policy_domain"> <form class="form-inline" data-id="add_bl_policy_domain">
<div class="input-group" data-acl="<?=$_SESSION['acl']['spam_policy'];?>"> <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="text" class="form-control" name="object_from" placeholder="*@example.org" required>
<span class="input-group-btn"> <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> </span>
</div> </div>
</form> </form>
@ -362,7 +362,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="target_domain"><?=$lang['edit']['target_domain'];?></label> <label class="control-label col-sm-2" for="target_domain"><?=$lang['edit']['target_domain'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -374,7 +374,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -382,17 +382,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<form data-id="domratelimit" class="form-inline well" method="post"> <form data-id="domratelimit" class="form-inline well" method="post">
<div class="form-group"> <div class="form-group">
<label class="control-label">Ratelimit</label> <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>
<div class="form-group"> <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="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="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> <option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select> </select>
</div> </div>
<div class="form-group"> <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> </div>
</form> </form>
<?php <?php
@ -430,7 +430,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="name"><?=$lang['edit']['full_name'];?>:</label> <label class="control-label col-sm-2" for="name"><?=$lang['edit']['full_name'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -438,13 +438,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<br /><span id="quotaBadge" class="badge">max. <?=intval($result['max_new_quota'] / 1048576)?> MiB</span> <br /><span id="quotaBadge" class="badge">max. <?=intval($result['max_new_quota'] / 1048576)?> MiB</span>
</label> </label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="sender_acl"><?=$lang['edit']['sender_acl'];?>:</label> <label class="control-label col-sm-2" for="sender_acl"><?=$lang['edit']['sender_acl'];?>:</label>
<div class="col-sm-10"> <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 <?php
$sender_acl_handles = mailbox('get', 'sender_acl_handles', $mailbox); $sender_acl_handles = mailbox('get', 'sender_acl_handles', $mailbox);
@ -498,13 +498,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label> <label class="control-label col-sm-2" for="password"><?=$lang['edit']['password'];?></label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="password" data-hibp="true" 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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label> <label class="control-label col-sm-2" for="password2"><?=$lang['edit']['password_repeat'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -524,7 +524,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -536,17 +536,17 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="col-sm-10"> <div class="col-sm-10">
<div class="form-group"> <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>
<div class="form-group"> <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="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="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> <option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
</select> </select>
</div> </div>
<div class="form-group"> <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> </div>
</div> </div>
@ -570,7 +570,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</select> </select>
</div> </div>
<div class="form-group"> <div class="form-group">
<button class="btn btn-default" id="edit_selected" data-id="useracl" data-item="<?=htmlspecialchars($mailbox);?>" data-api-url='edit/user-acl' data-api-attr='{}' href="#"><?=$lang['admin']['save'];?></button> <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> </div>
</div> </div>
@ -589,19 +589,19 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="hostname"><?=$lang['add']['hostname'];?></label> <label class="control-label col-sm-2" for="hostname"><?=$lang['add']['hostname'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?></label> <label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <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'];?></label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="password" data-hibp="true" 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> </div>
<div class="form-group"> <div class="form-group">
@ -613,7 +613,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -636,13 +636,13 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label> <label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['edit']['kind'];?>:</label> <label class="control-label col-sm-2" for="domain"><?=$lang['edit']['kind'];?>:</label>
<div class="col-sm-10"> <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="location" <?=($result['kind'] == "location") ? "selected" : null;?>>Location</option>
<option value="group" <?=($result['kind'] == "group") ? "selected" : null;?>>Group</option> <option value="group" <?=($result['kind'] == "group") ? "selected" : null;?>>Group</option>
<option value="thing" <?=($result['kind'] == "thing") ? "selected" : null;?>>Thing</option> <option value="thing" <?=($result['kind'] == "thing") ? "selected" : null;?>>Thing</option>
@ -652,7 +652,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="multiple_bookings_select"><?=$lang['add']['multiple_bookings'];?>:</label> <label class="control-label col-sm-2" for="multiple_bookings_select"><?=$lang['add']['multiple_bookings'];?>:</label>
<div class="col-sm-10"> <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="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="-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> <option value="custom" <?=($result['multiple_bookings'] >= 1) ? "selected" : null;?>><?=$lang['mailbox']['booking_custom'];?></option>
@ -673,7 +673,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -719,7 +719,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -766,7 +766,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -933,7 +933,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -984,7 +984,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>

View File

@ -59,7 +59,7 @@ $(document).ready(function() {
}); });
$('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>'); $('#u2f_status_auth').html('<p><span class="glyphicon glyphicon-refresh glyphicon-spin"></span> Initializing, please wait...</p>');
$('#ConfirmTFAModal').on('shown.bs.modal', function(){ $('#ConfirmTFAModal').on('shown.bs.modal', function(){
$(this).find('#token').focus(); $(this).find('input[name=token]').focus();
// If U2F // If U2F
if(document.getElementById("u2f_auth_data") !== null) { if(document.getElementById("u2f_auth_data") !== null) {
$.ajax({ $.ajax({
@ -146,7 +146,7 @@ $(document).ready(function() {
}); });
// CSRF // 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") { if (sessionStorage.scrollTop != "undefined") {
$(window).scrollTop(sessionStorage.scrollTop); $(window).scrollTop(sessionStorage.scrollTop);
} }

View File

@ -2,10 +2,13 @@
function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $extra_headers = null) { function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $extra_headers = null) {
global $DOCKER_TIMEOUT; global $DOCKER_TIMEOUT;
$curl = curl_init(); $curl = curl_init();
curl_setopt($curl, CURLOPT_HTTPHEADER,array( 'Content-Type: application/json' )); 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) { switch($action) {
case 'get_id': 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_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
@ -38,7 +41,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
} }
return false; return false;
case 'containers': 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_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
@ -74,7 +77,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
break; break;
case 'info': case 'info':
if (empty($service_name)) { 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_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0); curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
@ -82,7 +85,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
else { else {
$container_id = docker('get_id', $service_name); $container_id = docker('get_id', $service_name);
if (ctype_xdigit($container_id)) { 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 { else {
// logger(array('return' => array( // logger(array('return' => array(
@ -144,7 +147,7 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
if (!empty($attr1)) { if (!empty($attr1)) {
$container_id = docker('get_id', $service_name); $container_id = docker('get_id', $service_name);
if (ctype_xdigit($container_id) && ctype_alnum($attr1)) { 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_POST, 1);
curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT); curl_setopt($curl, CURLOPT_TIMEOUT, $DOCKER_TIMEOUT);
if (!empty($attr2)) { if (!empty($attr2)) {
@ -158,19 +161,19 @@ function docker($action, $service_name = null, $attr1 = null, $attr2 = null, $ex
if ($response === false) { if ($response === false) {
$err = curl_error($curl); $err = curl_error($curl);
curl_close($curl); curl_close($curl);
logger(array('return' => array(array( // logger(array('return' => array(array(
'type' => 'danger', // 'type' => 'danger',
'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), // 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
'msg' => $err, // 'msg' => $err,
)))); // ))));
return $err; return $err;
} }
else { else {
curl_close($curl); curl_close($curl);
logger(array('return' => array(array( // logger(array('return' => array(array(
'type' => 'success', // 'type' => 'success',
'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers), // 'log' => array(__FUNCTION__, $action, $service_name, $attr1, $attr2, $extra_headers),
)))); // ))));
if (empty($response)) { if (empty($response)) {
return true; return true;
} }

View File

@ -18,6 +18,17 @@ function last_login($user) {
return false; return false;
} }
} }
function flush_memcached() {
try {
$m = new Memcached();
$m->addServer('memcached', 11211);
$m->flush();
}
catch ( Exception $e ) {
// Dunno
}
}
function logger($_data = false) { function logger($_data = false) {
/* /*
logger() will be called as last function logger() will be called as last function
@ -510,6 +521,7 @@ function update_sogo_static_view() {
$stmt = $pdo->query("REPLACE INTO _sogo_static_view SELECT * from sogo_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');"); $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) { function edit_user_account($_data) {
global $lang; global $lang;

View File

@ -2776,6 +2776,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
`mailbox`.`active` AS `active_int`, `mailbox`.`active` AS `active_int`,
CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`, CASE `mailbox`.`active` WHEN 1 THEN '".$lang['mailbox']['yes']."' ELSE '".$lang['mailbox']['no']."' END AS `active`,
`mailbox`.`domain`, `mailbox`.`domain`,
`mailbox`.`maildir`,
`mailbox`.`quota`, `mailbox`.`quota`,
`quota2`.`bytes`, `quota2`.`bytes`,
`attributes`, `attributes`,
@ -2806,6 +2807,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$mailboxdata['active'] = $row['active']; $mailboxdata['active'] = $row['active'];
$mailboxdata['active_int'] = $row['active_int']; $mailboxdata['active_int'] = $row['active_int'];
$mailboxdata['domain'] = $row['domain']; $mailboxdata['domain'] = $row['domain'];
$mailboxdata['maildir'] = $row['maildir'];
$mailboxdata['quota'] = $row['quota']; $mailboxdata['quota'] = $row['quota'];
$mailboxdata['attributes'] = json_decode($row['attributes'], true); $mailboxdata['attributes'] = json_decode($row['attributes'], true);
$mailboxdata['quota_used'] = intval($row['bytes']); $mailboxdata['quota_used'] = intval($row['bytes']);
@ -3054,6 +3056,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
); );
continue; 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']
);
}
return false;
$stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain"); $stmt = $pdo->prepare("DELETE FROM `domain` WHERE `domain` = :domain");
$stmt->execute(array( $stmt->execute(array(
':domain' => $domain, ':domain' => $domain,
@ -3078,17 +3090,17 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$stmt->execute(array( $stmt->execute(array(
':domain' => '%@'.$domain, ':domain' => '%@'.$domain,
)); ));
$stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` = :domain"); $stmt = $pdo->prepare("DELETE FROM `quota2` WHERE `username` LIKE :domain");
$stmt->execute(array( $stmt->execute(array(
':domain' => '%@'.$domain, ':domain' => '%@'.$domain,
)); ));
$stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` = :domain"); $stmt = $pdo->prepare("DELETE FROM `spamalias` WHERE `address` LIKE :domain");
$stmt->execute(array( $stmt->execute(array(
':domain' => '%@'.$domain, ':domain' => '%@'.$domain,
)); ));
$stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain"); $stmt = $pdo->prepare("DELETE FROM `filterconf` WHERE `object` = :domain");
$stmt->execute(array( $stmt->execute(array(
':domain' => '%@'.$domain, ':domain' => $domain,
)); ));
$stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain"); $stmt = $pdo->prepare("DELETE FROM `bcc_maps` WHERE `local_dest` = :domain");
$stmt->execute(array( $stmt->execute(array(
@ -3227,6 +3239,16 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
); );
continue; 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 = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
$stmt->execute(array( $stmt->execute(array(
':username' => $username ':username' => $username

View File

@ -3,7 +3,7 @@ function init_db_schema() {
try { try {
global $pdo; global $pdo;
$db_version = "01092018_1902"; $db_version = "21092018_1902";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));

View File

@ -35,7 +35,7 @@ $hrs = floor($mins / 60);
$mins -= $hrs * 60; $mins -= $hrs * 60;
$offset = sprintf('%+d:%02d', $hrs*$sgn, $mins); $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 = [ $opt = [
PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION, PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC, PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
@ -46,11 +46,20 @@ try {
$pdo = new PDO($dsn, $database_user, $database_pass, $opt); $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
} }
catch (PDOException $e) { 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 <?php
exit; 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) { function pdo_exception_handler($e) {
print_r($e); print_r($e);
if ($e instanceof PDOException) { if ($e instanceof PDOException) {
@ -146,3 +155,4 @@ if (isset($_SESSION['mailcow_cc_role'])) {
acl('to_session'); acl('to_session');
} }
$UI_TEXTS = customize('get', 'ui_texts'); $UI_TEXTS = customize('get', 'ui_texts');

View File

@ -9,6 +9,7 @@ This file will be reset on upgrades.
// SQL database connection variables // SQL database connection variables
$database_type = 'mysql'; $database_type = 'mysql';
$database_sock = '/var/run/mysqld/mysqld.sock';
$database_host = 'mysql'; $database_host = 'mysql';
$database_user = getenv('DBUSER'); $database_user = getenv('DBUSER');
$database_pass = getenv('DBPASS'); $database_pass = getenv('DBPASS');

View File

@ -19,13 +19,13 @@ jQuery(function($){
}); });
$("#rspamd_preset_1").on('click', function(e) { $("#rspamd_preset_1").on('click', function(e) {
e.preventDefault(); e.preventDefault();
$("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_1); $("form[data-id=rsetting]").find("#adminRspamdSettingsDesc").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("#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) { $("#rspamd_preset_2").on('click', function(e) {
e.preventDefault(); e.preventDefault();
$("form[data-id=rsetting]").find("#desc").val(lang.rsettings_preset_2); $("form[data-id=rsetting]").find("#adminRspamdSettingsDesc").val(lang.rsettings_preset_2);
$("form[data-id=rsetting]").find("#content").val('priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;'); $("form[data-id=rsetting]").find("#adminRspamdSettingsContent").val('priority = 10;\nrcpt = "/postmaster@.*/";\nwant_spam = yes;');
}); });
$("#dkim_missing_keys").on('click', function(e) { $("#dkim_missing_keys").on('click', function(e) {
e.preventDefault(); e.preventDefault();
@ -122,14 +122,14 @@ jQuery(function($){
item.action = '<div class="btn-group">' + 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="#" 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="rlyhosts" name="multi_select" value="' + item.id + '" />';
}); });
} else if (table == 'forwardinghoststable') { } else if (table == 'forwardinghoststable') {
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.action = '<div class="btn-group">' + 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>'; '</div>';
if (item.keep_spam == "yes") { if (item.keep_spam == "yes") {
item.keep_spam = lang.no; item.keep_spam = lang.no;
@ -145,7 +145,7 @@ jQuery(function($){
item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />'; item.chkbox = '<input type="checkbox" data-id="domain_admins" name="multi_select" value="' + item.username + '" />';
item.action = '<div class="btn-group">' + 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="/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="#" 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>' + '<a href="/index.php?duallogin=' + encodeURIComponent(item.username) + '" class="btn btn-xs btn-success"><span class="glyphicon glyphicon-user"></span> Login</a>' +
'</div>'; '</div>';
}); });

View File

@ -71,7 +71,7 @@ $(document).ready(function() {
}); });
// General API edit actions // General API edit actions
$(document).on('click', '#edit_selected', function(e) { $(document).on('click', "[data-action='edit_selected']", function(e) {
e.preventDefault(); e.preventDefault();
var id = $(this).data('id'); var id = $(this).data('id');
var api_url = $(this).data('api-url'); var api_url = $(this).data('api-url');
@ -159,7 +159,7 @@ $(document).ready(function() {
}); });
// General API add actions // General API add actions
$(document).on('click', '#add_item', function(e) { $(document).on('click', "[data-action='add_item']", function(e) {
e.preventDefault(); e.preventDefault();
var id = $(this).data('id'); var id = $(this).data('id');
var api_url = $(this).data('api-url'); var api_url = $(this).data('api-url');
@ -252,7 +252,7 @@ $(document).ready(function() {
}); });
// General API delete actions // General API delete actions
$(document).on('click', '#delete_selected', function(e) { $(document).on('click', "[data-action='delete_selected']", function(e) {
e.preventDefault(); e.preventDefault();
var id = $(this).data('id'); var id = $(this).data('id');
// If clicked element #delete_selected has data-item attribute, it is added to "items" // If clicked element #delete_selected has data-item attribute, it is added to "items"
@ -283,6 +283,7 @@ $(document).ready(function() {
keyboard: false keyboard: false
}) })
.one('click', '#IsConfirmed', function(e) { .one('click', '#IsConfirmed', function(e) {
if (is_active($('#IsConfirmed'))) { return false; }
$.ajax({ $.ajax({
type: "POST", type: "POST",
dataType: "json", dataType: "json",

View File

@ -10,37 +10,43 @@ $(document).ready(function() {
}); });
$("#disable_sender_check").click(function( event ) { $("#disable_sender_check").click(function( event ) {
if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) { if ($("form[data-id='editmailbox'] #disable_sender_check:checked").length > 0) {
$('#sender_acl').prop('disabled', true); $('#editSelectSenderACL').prop('disabled', true);
$('#sender_acl').selectpicker('refresh'); $('#editSelectSenderACL').selectpicker('refresh');
} }
else { else {
$('#sender_acl').prop('disabled', false); $('#editSelectSenderACL').prop('disabled', false);
$('#sender_acl').selectpicker('refresh'); $('#editSelectSenderACL').selectpicker('refresh');
} }
}); });
if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) { if ($("form[data-id='editalias'] .goto_checkbox:checked").length > 0) {
$('#textarea_alias_goto').prop('disabled', true); $('#textarea_alias_goto').prop('disabled', true);
} }
$("#script_data").numberedtextarea({allowTabChar: 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_custom_div").show();
$("#multiple_bookings").val($("#multiple_bookings_custom").val()); $('input[name=multiple_bookings]').val($("#multiple_bookings_custom").val());
} }
$("#multiple_bookings_select").change(function() { $("#editSelectMultipleBookings").change(function() {
$("#multiple_bookings").val($("#multiple_bookings_select").val()); $('input[name=multiple_bookings]').val($("#editSelectMultipleBookings").val());
if ($("#multiple_bookings").val() == "custom") { if ($('input[name=multiple_bookings]').val() == "custom") {
$("#multiple_bookings_custom_div").show(); $("#multiple_bookings_custom_div").show();
} }
else { else {
$("#multiple_bookings_custom_div").hide(); $("#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_disabled").show();
} }
$('#sender_acl').change(function() { $('#editSelectSenderACL').change(function() {
if ($("#sender_acl option[value='\*']:selected").length > 0){ if ($("#editSelectSenderACL option[value='\*']:selected").length > 0){
$("#sender_acl_disabled").show(); $("#sender_acl_disabled").show();
} }
else { else {
@ -48,7 +54,7 @@ $('#sender_acl').change(function() {
} }
}); });
$("#multiple_bookings_custom").bind("change keypress keyup blur", 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($){ jQuery(function($){
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript

View File

@ -6,7 +6,6 @@ $(document).ready(function() {
var domain_list = []; var domain_list = [];
$.ajax({ $.ajax({
dataType: 'json', dataType: 'json',
'async': false,
url: '/api/v1/get/domain/all', url: '/api/v1/get/domain/all',
jsonp: false, jsonp: false,
error: function () { error: function () {
@ -85,10 +84,10 @@ $(document).ready(function() {
event.preventDefault(); event.preventDefault();
$('[data-hibp]').trigger('input'); $('[data-hibp]').trigger('input');
var random_passwd = Math.random().toString(36).slice(-8) var random_passwd = Math.random().toString(36).slice(-8)
$('#password').prop('type', 'text'); $(this).closest("form").find("input[name='password']").prop('type', 'text');
$('#password').val(random_passwd); $(this).closest("form").find("input[name='password2']").prop('type', 'text');
$('#password2').prop('type', 'text'); $(this).closest("form").find("input[name='password']").val(random_passwd);
$('#password2').val(random_passwd); $(this).closest("form").find("input[name='password2']").val(random_passwd);
}); });
$(".goto_checkbox").click(function( event ) { $(".goto_checkbox").click(function( event ) {
@ -302,7 +301,7 @@ jQuery(function($){
item.action = '<div class="btn-group">'; item.action = '<div class="btn-group">';
if (role == "admin") { 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>' + 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>'; '<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 { 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.php?domain=' + encodeURIComponent(item.domain_name) + '" class="btn btn-xs btn-default"><span class="glyphicon glyphicon-pencil"></span> ' + lang.edit + '</a>';
@ -386,14 +385,14 @@ jQuery(function($){
if (acl_data.login_as === 1) { if (acl_data.login_as === 1) {
item.action = '<div class="btn-group">' + 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="/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="#" 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>' + '<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>'; '</div>';
} }
else { else {
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
} }
item.in_use = '<div class="progress">' + item.in_use = '<div class="progress">' +
@ -461,7 +460,7 @@ jQuery(function($){
} }
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="resource" name="multi_select" value="' + encodeURIComponent(item.name) + '" />'; item.chkbox = '<input type="checkbox" data-id="resource" name="multi_select" value="' + encodeURIComponent(item.name) + '" />';
item.name = escapeHtml(item.name); item.name = escapeHtml(item.name);
@ -520,7 +519,7 @@ jQuery(function($){
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="bcc" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="bcc" name="multi_select" value="' + item.id + '" />';
item.local_dest = escapeHtml(item.local_dest); item.local_dest = escapeHtml(item.local_dest);
@ -583,7 +582,7 @@ jQuery(function($){
item.recipient_map_new = escapeHtml(item.recipient_map_new); item.recipient_map_new = escapeHtml(item.recipient_map_new);
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="recipient_map" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="recipient_map" name="multi_select" value="' + item.id + '" />';
}); });
@ -638,7 +637,7 @@ jQuery(function($){
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.id) + '" />'; item.chkbox = '<input type="checkbox" data-id="alias" name="multi_select" value="' + encodeURIComponent(item.id) + '" />';
item.goto = escapeHtml(item.goto.replace(/,/g, " ")); item.goto = escapeHtml(item.goto.replace(/,/g, " "));
@ -713,7 +712,7 @@ jQuery(function($){
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.action = '<div class="btn-group">' + 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="/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="#" 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>' + '<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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />'; item.chkbox = '<input type="checkbox" data-id="alias-domain" name="multi_select" value="' + encodeURIComponent(item.alias_domain) + '" />';
@ -781,7 +780,7 @@ jQuery(function($){
item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1; item.server_w_port = escapeHtml(item.user1) + '@' + item.host1 + ':' + item.port1;
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
if (item.is_running == 1) { if (item.is_running == 1) {
@ -852,7 +851,7 @@ jQuery(function($){
item.filter_type = '<div class="label label-default">' + item.filter_type.charAt(0).toUpperCase() + item.filter_type.slice(1).toLowerCase() + '</div>' 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">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="filter_item" name="multi_select" value="' + item.id + '" />' item.chkbox = '<input type="checkbox" data-id="filter_item" name="multi_select" value="' + item.id + '" />'
}); });

View File

@ -110,7 +110,7 @@ $(document).ready(function() {
// Disable disallowed inputs // Disable disallowed inputs
$('[data-acl="0"]').each(function(){ $('[data-acl="0"]').each(function(){
if ($(this).attr('class') == 'btn-group') { if ($(this).hasClass('btn-group')) {
$(this).find('a').each(function(){ $(this).find('a').each(function(){
$(this).removeClass('dropdown-toggle') $(this).removeClass('dropdown-toggle')
.removeAttr('data-toggle') .removeAttr('data-toggle')
@ -124,7 +124,7 @@ $(document).ready(function() {
$(this).find('button').each(function() { $(this).find('button').each(function() {
$(this).attr("disabled", true); $(this).attr("disabled", true);
}); });
} else if ($(this).attr('class') == 'input-group') { } else if ($(this).hasClass('input-group')) {
$(this).find('input').each(function() { $(this).find('input').each(function() {
$(this).removeClass('dropdown-toggle') $(this).removeClass('dropdown-toggle')
.removeAttr('data-toggle') .removeAttr('data-toggle')

View File

@ -28,7 +28,7 @@ jQuery(function($){
$.each(data, function (i, item) { $.each(data, function (i, item) {
item.action = '<div class="btn-group">' + 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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="qitems" name="multi_select" value="' + item.id + '" />';
}); });

View File

@ -64,7 +64,7 @@ jQuery(function($){
$.each(data, function (i, item) { $.each(data, function (i, item) {
if (acl_data.spam_alias === 1) { if (acl_data.spam_alias === 1) {
item.action = '<div class="btn-group">' + 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />'; item.chkbox = '<input type="checkbox" data-id="tla" name="multi_select" value="' + encodeURIComponent(item.address) + '" />';
item.address = escapeHtml(item.address); item.address = escapeHtml(item.address);
@ -123,7 +123,7 @@ jQuery(function($){
if (acl_data.syncjobs === 1) { if (acl_data.syncjobs === 1) {
item.action = '<div class="btn-group">' + 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="/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="#" 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>'; '</div>';
item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />'; item.chkbox = '<input type="checkbox" data-id="syncjob" name="multi_select" value="' + item.id + '" />';
} }

View File

@ -44,10 +44,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> <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"> <ul class="dropdown-menu">
<? if($_SESSION['mailcow_cc_role'] == "admin"): ?> <? 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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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; ?> <? endif; ?>
</ul> </ul>
<? if($_SESSION['mailcow_cc_role'] == "admin"): ?> <? if($_SESSION['mailcow_cc_role'] == "admin"): ?>
@ -74,10 +74,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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -101,10 +101,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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -134,10 +134,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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -161,10 +161,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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -188,12 +188,12 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
<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" 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> <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"> <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 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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -218,13 +218,13 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
<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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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 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 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":"postfilter"}' href="#"><?=$lang['mailbox']['set_postfilter'];?></a></li>
<li role="separator" class="divider"></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> </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> <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> </div>
@ -249,13 +249,13 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
<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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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 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 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":"rcpt"}' href="#"><?=$lang['mailbox']['bcc_to_rcpt'];?></a></li>
<li role="separator" class="divider"></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> </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> <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>
@ -277,10 +277,10 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
<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" 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> <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"> <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 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 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":"0"}' href="#"><?=$lang['mailbox']['deactivate'];?></a></li>
<li role="separator" class="divider"></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> </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> <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>

View File

@ -17,13 +17,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label> <label class="control-label col-sm-2" for="desc"><?=$lang['admin']['rsetting_desc'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="content"><?=$lang['admin']['rsetting_content'];?>:</label> <label class="control-label col-sm-2" for="content"><?=$lang['admin']['rsetting_content'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -35,7 +35,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -60,7 +60,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label> <label class="control-label col-sm-2" for="username"><?=$lang['admin']['username'];?>:</label>
<div class="col-sm-10"> <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>
&rdsh; <kbd>a-z A-Z - _ .</kbd> &rdsh; <kbd>a-z A-Z - _ .</kbd>
</div> </div>
</div> </div>
@ -79,13 +79,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['admin']['password'];?>:</label> <label class="control-label col-sm-2" for="password"><?=$lang['admin']['password'];?>:</label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="password" class="form-control" data-hibp="true" name="password" id="password" placeholder="" required> <input type="password" class="form-control" data-hibp="true" name="password" placeholder="" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['admin']['password_repeat'];?>:</label> <label class="control-label col-sm-2" for="password2"><?=$lang['admin']['password_repeat'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -97,7 +97,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -115,11 +115,11 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="modal-body"> <div class="modal-body">
<form class="form-horizontal" data-cached-form="true" id="test_relayhost_form" role="form" method="post"> <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"> <div class="form-group">
<label class="control-label col-sm-2" for="mail_from"><?=$lang['admin']['relay_from'];?></label> <label class="control-label col-sm-2" for="mail_from"><?=$lang['admin']['relay_from'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">

View File

@ -8,19 +8,19 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
<div class="modal-body"> <div class="modal-body">
<form role="form" method="post"> <form role="form" method="post">
<div class="form-group"> <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>
<hr> <hr>
<p class="help-block"><?=$lang['tfa']['api_register'];?></p> <p class="help-block"><?=$lang['tfa']['api_register'];?></p>
<div class="form-group"> <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>
<div class="form-group"> <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> </div>
<hr> <hr>
<div class="form-group"> <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>
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
@ -43,10 +43,10 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
<div class="modal-body"> <div class="modal-body">
<form role="form" method="post" id="u2f_reg_form"> <form role="form" method="post" id="u2f_reg_form">
<div class="form-group"> <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>
<div class="form-group"> <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>
<hr> <hr>
<p id="u2f_status_reg"></p> <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"> <div class="modal-body">
<form role="form" method="post"> <form role="form" method="post">
<div class="form-group"> <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>
<div class="form-group"> <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>
<hr> <hr>
<?php <?php
$totp_secret = $tfa->createSecret(); $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"> <input type="hidden" name="tfa_method" value="totp">
<ol> <ol>
<li> <li>
@ -88,7 +88,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
</li> </li>
<li> <li>
<p><?=$lang['tfa']['confirm_totp_token'];?>:</p> <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> <p><button class="btn btn-default" type="submit" name="set_tfa"><?=$lang['tfa']['confirm'];?></button></p>
</li> </li>
</ol> </ol>
@ -105,7 +105,7 @@ if (isset($_SESSION['mailcow_cc_role']) && ($_SESSION['mailcow_cc_role'] == "adm
<div class="modal-body"> <div class="modal-body">
<form role="form" method="post"> <form role="form" method="post">
<div class="input-group"> <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"> <span class="input-group-btn">
<input type="hidden" name="tfa_method" value="none"> <input type="hidden" name="tfa_method" value="none">
<button class="btn btn-danger" type="submit" name="set_tfa"><?=$lang['tfa']['delete_tfa'];?></button> <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="form-group">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="yubi-addon"><img alt="Yubicon Icon" src="/img/yubi.ico"></span> <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"> <input type="hidden" name="tfa_method" value="yubi_otp">
</div> </div>
</div> </div>
@ -160,7 +160,7 @@ if (isset($_SESSION['pending_tfa_method'])):
<div class="form-group"> <div class="form-group">
<div class="input-group"> <div class="input-group">
<span class="input-group-addon" id="tfa-addon"><span class="glyphicon glyphicon-lock" aria-hidden="true"></span></span> <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"> <input type="hidden" name="tfa_method" value="totp">
</div> </div>
</div> </div>

View File

@ -17,13 +17,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="local_part"><?=$lang['add']['mailbox_username'];?></label> <label class="control-label col-sm-2" for="local_part"><?=$lang['add']['mailbox_username'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label> <label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select class="full-width-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 <?php
foreach (mailbox('get', 'domains') as $domain) { foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>"; echo "<option>".htmlspecialchars($domain)."</option>";
@ -35,7 +35,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="name"><?=$lang['add']['full_name'];?></label> <label class="control-label col-sm-2" for="name"><?=$lang['add']['full_name'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -50,13 +50,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password"><?=$lang['add']['password'];?> (<a href="#" class="generate_password"><?=$lang['add']['generate'];?></a>)</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"> <div class="col-sm-10">
<input type="password" data-hibp="true" class="form-control" name="password" id="password" placeholder="" required> <input type="password" data-hibp="true" class="form-control" name="password" placeholder="" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password2"><?=$lang['add']['password_repeat'];?></label> <label class="control-label col-sm-2" for="password2"><?=$lang['add']['password_repeat'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -68,7 +68,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -89,37 +89,37 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label> <label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label> <label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="aliases"><?=$lang['add']['max_aliases'];?></label> <label class="control-label col-sm-2" for="aliases"><?=$lang['add']['max_aliases'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="mailboxes"><?=$lang['add']['max_mailboxes'];?></label> <label class="control-label col-sm-2" for="mailboxes"><?=$lang['add']['max_mailboxes'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxquota"><?=$lang['add']['mailbox_quota_m'];?></label> <label class="control-label col-sm-2" for="maxquota"><?=$lang['add']['mailbox_quota_m'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="quota"><?=$lang['add']['domain_quota_m'];?></label> <label class="control-label col-sm-2" for="quota"><?=$lang['add']['domain_quota_m'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -133,10 +133,10 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="quota">Ratelimit</label> <label class="control-label col-sm-2" for="quota">Ratelimit</label>
<div class="col-sm-7"> <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>
<div class="col-sm-3"> <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="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="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> <option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
@ -158,8 +158,8 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<hr> <hr>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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" 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" 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='{"restart_sogo":"1"}' href="#"><?=$lang['add']['add_domain_restart'];?></button>
</div> </div>
</div> </div>
<p><span class="glyphicon glyphicon-exclamation-sign text-danger"></span> <?=$lang['add']['restart_sogo_hint'];?></p> <p><span class="glyphicon glyphicon-exclamation-sign text-danger"></span> <?=$lang['add']['restart_sogo_hint'];?></p>
@ -181,13 +181,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label> <label class="control-label col-sm-2" for="description"><?=$lang['add']['description'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label> <label class="control-label col-sm-2" for="domain"><?=$lang['add']['domain'];?>:</label>
<div class="col-sm-10"> <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 <?php
foreach (mailbox('get', 'domains') as $domain) { foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>"; echo "<option>".htmlspecialchars($domain)."</option>";
@ -199,7 +199,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="domain"><?=$lang['add']['kind'];?>:</label> <label class="control-label col-sm-2" for="domain"><?=$lang['add']['kind'];?>:</label>
<div class="col-sm-10"> <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="location">Location</option>
<option value="group">Group</option> <option value="group">Group</option>
<option value="thing">Thing</option> <option value="thing">Thing</option>
@ -230,7 +230,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -262,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> <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> <p><?=$lang['add']['target_address_info'];?></p>
<div class="checkbox"> <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>
<div class="checkbox"> <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>
<div class="checkbox"> <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> </div>
</div> </div>
@ -281,7 +281,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -310,7 +310,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="target_domain"><?=$lang['add']['target_domain'];?></label> <label class="control-label col-sm-2" for="target_domain"><?=$lang['add']['target_domain'];?></label>
<div class="col-sm-10"> <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 <?php
foreach (mailbox('get', 'domains') as $domain) { foreach (mailbox('get', 'domains') as $domain) {
echo "<option>".htmlspecialchars($domain)."</option>"; echo "<option>".htmlspecialchars($domain)."</option>";
@ -328,7 +328,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -350,7 +350,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label> <label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
<div class="col-sm-10"> <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 <?php
$domains = mailbox('get', 'domains'); $domains = mailbox('get', 'domains');
if (!empty($domains)) { if (!empty($domains)) {
@ -368,32 +368,32 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label> <label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label> <label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">1-65535</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label> <label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label> <label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label> <label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label>
<div class="col-sm-10"> <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 selected>TLS</option>
<option>SSL</option> <option>SSL</option>
<option>PLAIN</option> <option>PLAIN</option>
@ -410,47 +410,47 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label> <label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label> <label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">0-32000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label> <label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">0-125000000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="timeout1"><?=$lang['edit']['timeout1'];?></label> <label class="control-label col-sm-2" for="timeout1"><?=$lang['edit']['timeout1'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">1-32000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="timeout2"><?=$lang['edit']['timeout2'];?></label> <label class="control-label col-sm-2" for="timeout2"><?=$lang['edit']['timeout2'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">1-32000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label> <label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="custom_params"><?=$lang['add']['custom_params'];?></label> <label class="control-label col-sm-2" for="custom_params"><?=$lang['add']['custom_params'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -504,7 +504,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -525,7 +525,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label> <label class="control-label col-sm-2" for="username"><?=$lang['add']['username'];?>:</label>
<div class="col-sm-10"> <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 <?php
$domains = mailbox('get', 'domains'); $domains = mailbox('get', 'domains');
if (!empty($domains)) { if (!empty($domains)) {
@ -543,7 +543,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="filter_type"><?=$lang['add']['sieve_type'];?>:</label> <label class="control-label col-sm-2" for="filter_type"><?=$lang['add']['sieve_type'];?>:</label>
<div class="col-sm-10"> <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="prefilter">Prefilter</option>
<option value="postfilter">Postfilter</option> <option value="postfilter">Postfilter</option>
</select> </select>
@ -552,7 +552,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="script_desc"><?=$lang['add']['sieve_desc'];?>:</label> <label class="control-label col-sm-2" for="script_desc"><?=$lang['add']['sieve_desc'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -572,7 +572,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10" id="add_filter_btns"> <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-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>
</div> </div>
</form> </form>
@ -593,7 +593,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="local_dest"><?=$lang['mailbox']['bcc_local_dest'];?>:</label> <label class="control-label col-sm-2" for="local_dest"><?=$lang['mailbox']['bcc_local_dest'];?>:</label>
<div class="col-sm-10"> <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 <?php
$domains = mailbox('get', 'domains'); $domains = mailbox('get', 'domains');
$alias_domains = mailbox('get', 'alias_domains'); $alias_domains = mailbox('get', 'alias_domains');
@ -622,7 +622,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="type"><?=$lang['mailbox']['bcc_map_type'];?>:</label> <label class="control-label col-sm-2" for="type"><?=$lang['mailbox']['bcc_map_type'];?>:</label>
<div class="col-sm-10"> <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="sender"><?=$lang['mailbox']['bcc_sender_map'];?></option>
<option value="rcpt"><?=$lang['mailbox']['bcc_rcpt_map'];?></option> <option value="rcpt"><?=$lang['mailbox']['bcc_rcpt_map'];?></option>
</select> </select>
@ -631,7 +631,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destination'];?>:</label> <label class="control-label col-sm-2" for="bcc_dest"><?=$lang['mailbox']['bcc_destination'];?>:</label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -643,7 +643,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -664,14 +664,14 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_old"><?=$lang['mailbox']['recipient_map_old'];?></label> <label class="control-label col-sm-2" for="recipient_map_old"><?=$lang['mailbox']['recipient_map_old'];?></label>
<div class="col-sm-10"> <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> <small><?=$lang['mailbox']['recipient_map_old_info'];?></small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?></label> <label class="control-label col-sm-2" for="recipient_map_new"><?=$lang['mailbox']['recipient_map_new'];?></label>
<div class="col-sm-10"> <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> <small><?=$lang['mailbox']['recipient_map_new_info'];?></small>
</div> </div>
</div> </div>
@ -684,7 +684,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>

View File

@ -18,32 +18,32 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label> <label class="control-label col-sm-2" for="host1"><?=$lang['add']['hostname'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label> <label class="control-label col-sm-2" for="port1"><?=$lang['add']['port'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">1-65535</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label> <label class="control-label col-sm-2" for="user1"><?=$lang['add']['username'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label> <label class="control-label col-sm-2" for="password1"><?=$lang['add']['password'];?></label>
<div class="col-sm-10"> <div class="col-sm-10">
<input type="password" class="form-control" name="password1" id="password1" data-hibp="true" required> <input type="password" class="form-control" name="password1" data-hibp="true" required>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label> <label class="control-label col-sm-2" for="enc1"><?=$lang['add']['enc_method'];?></label>
<div class="col-sm-10"> <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 selected>TLS</option>
<option>SSL</option> <option>SSL</option>
<option>PLAIN</option> <option>PLAIN</option>
@ -60,27 +60,27 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label> <label class="control-label col-sm-2" for="subfolder2"><?=$lang['edit']['subfolder2'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label> <label class="control-label col-sm-2" for="maxage"><?=$lang['edit']['maxage'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">0-32000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label> <label class="control-label col-sm-2" for="maxbytespersecond"><?=$lang['edit']['maxbytespersecond'];?></label>
<div class="col-sm-10"> <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> <small class="help-block">0-125000000</small>
</div> </div>
</div> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label> <label class="control-label col-sm-2" for="exclude"><?=$lang['add']['exclude'];?></label>
<div class="col-sm-10"> <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> </div>
<div class="form-group"> <div class="form-group">
@ -127,7 +127,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-2 col-sm-10"> <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>
</div> </div>
</form> </form>
@ -155,13 +155,13 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="user_new_pass"><?=$lang['user']['new_password'];?></label> <label class="control-label col-sm-3" for="user_new_pass"><?=$lang['user']['new_password'];?></label>
<div class="col-sm-5"> <div class="col-sm-5">
<input type="password" data-hibp="true" 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> </div>
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="user_new_pass2"><?=$lang['user']['new_password_repeat'];?></label> <label class="control-label col-sm-3" for="user_new_pass2"><?=$lang['user']['new_password_repeat'];?></label>
<div class="col-sm-5"> <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> <p class="help-block"><?=$lang['user']['new_password_description'];?></p>
</div> </div>
</div> </div>
@ -169,12 +169,12 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<div class="form-group"> <div class="form-group">
<label class="control-label col-sm-3" for="user_old_pass"><?=$lang['user']['password_now'];?></label> <label class="control-label col-sm-3" for="user_old_pass"><?=$lang['user']['password_now'];?></label>
<div class="col-sm-5"> <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> </div>
<div class="form-group"> <div class="form-group">
<div class="col-sm-offset-3 col-sm-9"> <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>
</div> </div>
</form> </form>

View File

@ -22,11 +22,11 @@ $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
<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" 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> <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"> <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 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 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> </ul>
</div> </div>
</div> </div>

View File

@ -10,6 +10,7 @@ if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'doma
$_SESSION['return_to'] = $_SERVER['REQUEST_URI']; $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
$tfa_data = get_tfa(); $tfa_data = get_tfa();
$username = $_SESSION['mailcow_cc_username']; $username = $_SESSION['mailcow_cc_username'];
?> ?>
<div class="container"> <div class="container">
<h3><?=$lang['user']['user_settings'];?></h3> <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; else: echo "Last login: -"; endif;
?> ?>
</small></p> </small></p>
<p>
</div> </div>
</div> </div>
<hr> <hr>
@ -102,6 +104,7 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
<?php endif; ?> <?php endif; ?>
<p><a href="#pwChangeModal" data-toggle="modal">[<?=$lang['user']['change_password'];?>]</a></p> <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 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> <p><small>
<?php <?php
if ($_SESSION['mailcow_cc_last_login']['remote']): if ($_SESSION['mailcow_cc_last_login']['remote']):
@ -114,13 +117,6 @@ elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == '
</div> </div>
</div> </div>
<hr> <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 <?php // Get user information about aliases
$user_get_alias_details = user_get_alias_details($username); $user_get_alias_details = user_get_alias_details($username);
?> ?>

View File

@ -20,6 +20,7 @@ services:
image: mariadb:10.2 image: mariadb:10.2
volumes: volumes:
- mysql-vol-1:/var/lib/mysql/ - mysql-vol-1:/var/lib/mysql/
- mysql-socket-vol-1:/var/run/mysqld/
- ./data/conf/mysql/:/etc/mysql/conf.d/:ro - ./data/conf/mysql/:/etc/mysql/conf.d/:ro
environment: environment:
- TZ=${TZ} - TZ=${TZ}
@ -71,7 +72,7 @@ services:
- clamd - clamd
rspamd-mailcow: rspamd-mailcow:
image: mailcow/rspamd:1.24 image: mailcow/rspamd:1.27
build: ./data/Dockerfiles/rspamd build: ./data/Dockerfiles/rspamd
stop_grace_period: 30s stop_grace_period: 30s
depends_on: depends_on:
@ -79,9 +80,9 @@ services:
environment: environment:
- TZ=${TZ} - TZ=${TZ}
volumes: volumes:
- ./data/conf/rspamd/custom/:/etc/rspamd/custom:ro - ./data/conf/rspamd/custom/:/etc/rspamd/custom
- ./data/conf/rspamd/override.d/:/etc/rspamd/override.d:rw - ./data/conf/rspamd/override.d/:/etc/rspamd/override.d
- ./data/conf/rspamd/local.d/:/etc/rspamd/local.d:ro - ./data/conf/rspamd/local.d/:/etc/rspamd/local.d
- ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro - ./data/conf/rspamd/lua/:/etc/rspamd/lua/:ro
- rspamd-sock:/rspamd-sock - rspamd-sock:/rspamd-sock
- rspamd-vol-1:/var/lib/rspamd - rspamd-vol-1:/var/lib/rspamd
@ -95,7 +96,7 @@ services:
- rspamd - rspamd
php-fpm-mailcow: php-fpm-mailcow:
image: mailcow/phpfpm:1.18 image: mailcow/phpfpm:1.21
build: ./data/Dockerfiles/phpfpm build: ./data/Dockerfiles/phpfpm
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
depends_on: depends_on:
@ -104,6 +105,7 @@ services:
- ./data/web:/web:rw - ./data/web:/web:rw
- ./data/conf/rspamd/dynmaps:/dynmaps:ro - ./data/conf/rspamd/dynmaps:/dynmaps:ro
- rspamd-sock:/rspamd-sock - rspamd-sock:/rspamd-sock
- mysql-socket-vol-1:/var/run/mysqld/
- ./data/conf/rspamd/meta_exporter:/meta_exporter:ro - ./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-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 - ./data/conf/phpfpm/php-conf.d/opcache-recommended.ini:/usr/local/etc/php/conf.d/opcache-recommended.ini
@ -136,7 +138,7 @@ services:
- phpfpm - phpfpm
sogo-mailcow: sogo-mailcow:
image: mailcow/sogo:1.36 image: mailcow/sogo:1.38
build: ./data/Dockerfiles/sogo build: ./data/Dockerfiles/sogo
environment: environment:
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
@ -147,6 +149,7 @@ services:
- MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME} - MAILCOW_HOSTNAME=${MAILCOW_HOSTNAME}
volumes: volumes:
- ./data/conf/sogo/:/etc/sogo/ - ./data/conf/sogo/:/etc/sogo/
- mysql-socket-vol-1:/var/run/mysqld/
restart: always restart: always
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
@ -157,7 +160,7 @@ services:
- sogo - sogo
dovecot-mailcow: dovecot-mailcow:
image: mailcow/dovecot:1.33 image: mailcow/dovecot:1.36
build: ./data/Dockerfiles/dovecot build: ./data/Dockerfiles/dovecot
cap_add: cap_add:
- NET_BIND_SERVICE - NET_BIND_SERVICE
@ -167,13 +170,16 @@ services:
- ./data/conf/sogo/:/etc/sogo/ - ./data/conf/sogo/:/etc/sogo/
- vmail-vol-1:/var/vmail - vmail-vol-1:/var/vmail
- crypt-vol-1:/mail_crypt/ - crypt-vol-1:/mail_crypt/
- ./data/conf/rspamd/custom/:/etc/rspamd/custom
- rspamd-sock:/rspamd-sock - rspamd-sock:/rspamd-sock
- mysql-socket-vol-1:/var/run/mysqld/
environment: environment:
- LOG_LINES=${LOG_LINES:-9999} - LOG_LINES=${LOG_LINES:-9999}
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
- DBPASS=${DBPASS} - DBPASS=${DBPASS}
- TZ=${TZ} - TZ=${TZ}
- MAILDIR_GC_TIME=${MAILDIR_GC_TIME:-1440}
ports: ports:
- "${DOVEADM_PORT:-127.0.0.1:19991}:12345" - "${DOVEADM_PORT:-127.0.0.1:19991}:12345"
- "${IMAP_PORT:-143}:143" - "${IMAP_PORT:-143}:143"
@ -196,7 +202,7 @@ services:
- dovecot - dovecot
postfix-mailcow: postfix-mailcow:
image: mailcow/postfix:1.21 image: mailcow/postfix:1.22
build: ./data/Dockerfiles/postfix build: ./data/Dockerfiles/postfix
volumes: volumes:
- ./data/conf/postfix:/opt/postfix/conf - ./data/conf/postfix:/opt/postfix/conf
@ -204,6 +210,7 @@ services:
- postfix-vol-1:/var/spool/postfix - postfix-vol-1:/var/spool/postfix
- crypt-vol-1:/var/lib/zeyple - crypt-vol-1:/var/lib/zeyple
- rspamd-sock:/rspamd-sock - rspamd-sock:/rspamd-sock
- mysql-socket-vol-1:/var/run/mysqld/
environment: environment:
- LOG_LINES=${LOG_LINES:-9999} - LOG_LINES=${LOG_LINES:-9999}
- TZ=${TZ} - TZ=${TZ}
@ -280,8 +287,7 @@ services:
acme-mailcow: acme-mailcow:
depends_on: depends_on:
- nginx-mailcow - nginx-mailcow
- mysql-mailcow image: mailcow/acme:1.38
image: mailcow/acme:1.37
build: ./data/Dockerfiles/acme build: ./data/Dockerfiles/acme
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
@ -299,6 +305,7 @@ services:
- ./data/web/.well-known/acme-challenge:/var/www/acme:rw - ./data/web/.well-known/acme-challenge:/var/www/acme:rw
- ./data/assets/ssl:/var/lib/acme/:rw - ./data/assets/ssl:/var/lib/acme/:rw
- ./data/assets/ssl-example:/var/lib/ssl-example/:ro - ./data/assets/ssl-example:/var/lib/ssl-example/:ro
- mysql-socket-vol-1:/var/run/mysqld/
restart: always restart: always
networks: networks:
mailcow-network: mailcow-network:
@ -330,13 +337,14 @@ services:
- /lib/modules:/lib/modules:ro - /lib/modules:/lib/modules:ro
watchdog-mailcow: watchdog-mailcow:
image: mailcow/watchdog:1.22 image: mailcow/watchdog:1.24
# Debug # Debug
#command: /watchdog.sh #command: /watchdog.sh
build: ./data/Dockerfiles/watchdog build: ./data/Dockerfiles/watchdog
oom_kill_disable: true oom_kill_disable: true
volumes: volumes:
- rspamd-sock:/rspamd-sock - rspamd-sock:/rspamd-sock
- mysql-socket-vol-1:/var/run/mysqld/
restart: always restart: always
environment: environment:
- LOG_LINES=${LOG_LINES:-9999} - LOG_LINES=${LOG_LINES:-9999}
@ -356,7 +364,7 @@ services:
- watchdog - watchdog
dockerapi-mailcow: dockerapi-mailcow:
image: mailcow/dockerapi:1.14 image: mailcow/dockerapi:1.17
restart: always restart: always
build: ./data/Dockerfiles/dockerapi build: ./data/Dockerfiles/dockerapi
oom_kill_disable: true oom_kill_disable: true
@ -365,6 +373,7 @@ services:
volumes: volumes:
- /var/run/docker.sock:/var/run/docker.sock:ro - /var/run/docker.sock:/var/run/docker.sock:ro
- ./data/conf/rspamd/override.d/worker-controller-password.inc:/access.inc:rw - ./data/conf/rspamd/override.d/worker-controller-password.inc:/access.inc:rw
- vmail-vol-1:/var/vmail:ro
networks: networks:
mailcow-network: mailcow-network:
aliases: aliases:
@ -392,6 +401,7 @@ networks:
volumes: volumes:
vmail-vol-1: vmail-vol-1:
mysql-vol-1: mysql-vol-1:
mysql-socket-vol-1:
redis-vol-1: redis-vol-1:
rspamd-vol-1: rspamd-vol-1:
postfix-vol-1: postfix-vol-1:

View File

@ -104,6 +104,11 @@ TZ=${MAILCOW_TZ}
# Fixed project name # Fixed project name
COMPOSE_PROJECT_NAME=mailcowdockerized 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)
MAILDIR_GC_TIME=1440
# Additional SAN for the certificate # Additional SAN for the certificate
ADDITIONAL_SAN= ADDITIONAL_SAN=

View File

@ -5,8 +5,8 @@ if [[ ! ${1} =~ (backup|restore) ]]; then
exit 1 exit 1
fi fi
if [[ ${1} == "backup" && ! ${2} =~ (vmail|redis|rspamd|postfix|mysql|all) ]]; then if [[ ${1} == "backup" && ! ${2} =~ (crypt|vmail|redis|rspamd|postfix|mysql|all) ]]; then
echo "Second parameter needs to be 'vmail', 'redis', 'rspamd', 'postfix', 'mysql' or 'all'" echo "Second parameter needs to be 'vmail', 'crypt', 'redis', 'rspamd', 'postfix', 'mysql' or 'all'"
exit 1 exit 1
fi fi
@ -62,6 +62,12 @@ function backup() {
-v $(docker volume ls -qf name=${CMPS_PRJ}_vmail-vol-1):/vmail \ -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 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) redis|all)
docker exec $(docker ps -qf name=redis-mailcow) redis-cli save docker exec $(docker ps -qf name=redis-mailcow) redis-cli save
docker run --rm \ docker run --rm \
@ -128,6 +134,14 @@ function restore() {
debian:stretch-slim /bin/tar -Pxvzf /backup/backup_redis.tar.gz debian:stretch-slim /bin/tar -Pxvzf /backup/backup_redis.tar.gz
docker start $(docker ps -aqf name=redis-mailcow) 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) rspamd)
docker stop $(docker ps -qf name=rspamd-mailcow) docker stop $(docker ps -qf name=rspamd-mailcow)
docker run -it --rm \ docker run -it --rm \
@ -189,7 +203,7 @@ elif [[ ${1} == "restore" ]]; then
echo echo
declare -A FILE_SELECTION declare -A FILE_SELECTION
RESTORE_POINT="${FOLDER_SELECTION[${input_sel}]}" 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" echo "No datasets found"
exit 1 exit 1
fi fi
@ -198,6 +212,10 @@ elif [[ ${1} == "restore" ]]; then
echo "[ ${i} ] - Mail directory (/var/vmail)" echo "[ ${i} ] - Mail directory (/var/vmail)"
FILE_SELECTION[${i}]="vmail" FILE_SELECTION[${i}]="vmail"
((i++)) ((i++))
elif [[ ${file} =~ crypt ]]; then
echo "[ ${i} ] - Crypt data"
FILE_SELECTION[${i}]="crypt"
((i++))
elif [[ ${file} =~ redis ]]; then elif [[ ${file} =~ redis ]]; then
echo "[ ${i} ] - Redis DB" echo "[ ${i} ] - Redis DB"
FILE_SELECTION[${i}]="redis" FILE_SELECTION[${i}]="redis"

View File

@ -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"