From 9b43974c96cbfae5c7ecba758f2e76fb5a959747 Mon Sep 17 00:00:00 2001 From: zekeriya Date: Fri, 1 Mar 2019 10:42:11 +0300 Subject: [PATCH 1/7] [Policyd] Added policyd Dockerfile [Compose] Added policyd Service [Postfix] Added policyd for check_policy_service to main.cf --- data/Dockerfiles/policyd/Dockerfile | 19 ++ .../etc/supervisor/conf.d/apache-2.4.conf | 12 ++ .../etc/supervisor/conf.d/cbpolicyd.conf | 12 ++ .../50_install_cluebringer_db | 48 +++++ .../supervisord-pre.d/51_configure_policyd | 14 ++ .../tmpl/cluebringer/cluebringer-webui.conf | 16 ++ .../files/tmpl/cluebringer/cluebringer.conf | 192 ++++++++++++++++++ .../policyd/files/var/www/html/.htaccess | 4 + data/conf/postfix/main.cf | 2 +- docker-compose.yml | 27 +++ generate_config.sh | 12 ++ 11 files changed, 357 insertions(+), 1 deletion(-) create mode 100644 data/Dockerfiles/policyd/Dockerfile create mode 100644 data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf create mode 100644 data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf create mode 100644 data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db create mode 100644 data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd create mode 100644 data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf create mode 100644 data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf create mode 100644 data/Dockerfiles/policyd/files/var/www/html/.htaccess diff --git a/data/Dockerfiles/policyd/Dockerfile b/data/Dockerfiles/policyd/Dockerfile new file mode 100644 index 00000000..3990f9f2 --- /dev/null +++ b/data/Dockerfiles/policyd/Dockerfile @@ -0,0 +1,19 @@ +FROM docker.io/1and1internet/ubuntu-16-apache-php-7.1:latest +ARG DEBIAN_FRONTEND=noninteractive +COPY files / +RUN \ + groupadd cbpolicyd && \ + useradd -g cbpolicyd cbpolicyd && \ + apt-get update && \ + apt-get -o Dpkg::Options::=--force-confdef -y install gettext-base postfix-cluebringer postfix-cluebringer-mysql postfix-cluebringer-webui -y && \ + apt-get -y clean && \ + rm -rf /var/lib/apt/lists/* /etc/cluebringer && \ + mkdir --mode=0775 /etc/cluebringer && \ + cp /usr/share/doc/postfix-cluebringer/database/policyd-db.mysql.gz /tmp/ && \ + cp -r /usr/share/postfix-cluebringer-webui/webui/* /var/www/html/ && \ + gunzip /tmp/policyd-db.mysql.gz && \ + sed -i -e 's/TYPE=InnoDB/ENGINE=InnoDB/g' /tmp/policyd-db.mysql && \ + chmod -R 0755 /hooks && \ + chmod -R 0777 /var/www/html && \ + chmod 0666 /var/log/cbpolicyd.log +EXPOSE 10031 8080 8443 diff --git a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf new file mode 100644 index 00000000..d5409158 --- /dev/null +++ b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf @@ -0,0 +1,12 @@ +[program:apache-2.4] +command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" +autostart=true +autorestart=true +startretries=3 + +# Redirect output so we can see it using "docker logs" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + diff --git a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf new file mode 100644 index 00000000..53f78cf7 --- /dev/null +++ b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf @@ -0,0 +1,12 @@ +[program:cbpolicyd] +command=/usr/sbin/cbpolicyd --fg --config=/etc/cluebringer/cluebringer.conf +autostart=true +autorestart=true +startretries=3 + +# Redirect output so we can see it using "docker logs" +stdout_logfile=/dev/stdout +stdout_logfile_maxbytes=0 +stderr_logfile=/dev/stderr +stderr_logfile_maxbytes=0 + diff --git a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db new file mode 100644 index 00000000..4c53f15b --- /dev/null +++ b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db @@ -0,0 +1,48 @@ +#!/bin/bash +set -eo pipefail + +# Password protect webui +echo Creating webui user +echo $WEBUI_PASSWORD | htpasswd -ci /var/www/html/.htpasswd webui + +# Checking for DB liveness before continuing with DB set up. +count=0 +while [ $count -lt 4 ]; do + if [[ $(mysql -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "select 1" &>/dev/null ; echo $?) -ne 0 ]]; then + echo "Waiting for DB to be ready." + sleep 15 + let count+=1 + else + echo "DB appears to be ready." + break + fi +done +# Die if DB doesn't come up in time. +if [ $count -eq 4 ]; then + echo "!!!WARNING!!! DB didn't come up in time." + exit 0 +fi + +# Set up DB if it's empty. +if [[ $(mysql -N -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$MYSQL_DATABASE';") == 0 ]]; then + echo "Setting up cluebringer DB." + + # Set up DB and User + if [[ $(mysql -N -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "create database $MYSQL_DATABASE;use $MYSQL_DATABASE;CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';GRANT ALL PRIVILEGES ON $MYSQL_DATABASE.* TO '$MYSQL_USER'@'%';") -ne 0 ]]; then + echo "Can't create DB and Policyd DB user!" + exit 0 + fi + + # Add our policys from sql if they exist. + if [[ -e /tmpl/cluebringer/import/policy.sql ]]; then + echo "Importing our configuration." + mysql -h$CLUEBRINGER_DB_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /tmpl/cluebringer/import/policy.sql + echo "Done." + else + echo "Additional sql configuration no found importing standart configuration." + mysql -h$CLUEBRINGER_DB_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /tmp/policyd-db.mysql + fi +else + echo "Cluebringer DB not empty, exiting." + exit 0 +fi diff --git a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd new file mode 100644 index 00000000..1983b4a5 --- /dev/null +++ b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd @@ -0,0 +1,14 @@ +#!/bin/bash + +set -eu + +export DOLLAR=$ +export MYSQL_DATABASE=${MYSQL_DATABASE} +export MYSQL_USER=${MYSQL_USER} +export MYSQL_PASSWORD=${MYSQL_PASSWORD} +export CLUEBRINGER_DB_BACKEND=${CLUEBRINGER_DB_BACKEND} +export CLUEBRINGER_DB_PORT=${CLUEBRINGER_DB_PORT} +export CLUEBRINGER_DB_HOST=${CLUEBRINGER_DB_HOST} + +envsubst < /tmpl/cluebringer/cluebringer.conf > /etc/cluebringer/cluebringer.conf +envsubst < /tmpl/cluebringer/cluebringer-webui.conf > /etc/cluebringer/cluebringer-webui.conf diff --git a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf new file mode 100644 index 00000000..a68f5a61 --- /dev/null +++ b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf @@ -0,0 +1,16 @@ + diff --git a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf new file mode 100644 index 00000000..4686f1e2 --- /dev/null +++ b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf @@ -0,0 +1,192 @@ +# +# Server configuration +# +[server] + +# Protocols to load +protocols=< Date: Fri, 13 Sep 2019 20:12:50 +0300 Subject: [PATCH 2/7] removed policyd --- data/Dockerfiles/policyd/Dockerfile | 19 -- .../etc/supervisor/conf.d/apache-2.4.conf | 12 -- .../etc/supervisor/conf.d/cbpolicyd.conf | 12 -- .../50_install_cluebringer_db | 48 ----- .../supervisord-pre.d/51_configure_policyd | 14 -- .../tmpl/cluebringer/cluebringer-webui.conf | 16 -- .../files/tmpl/cluebringer/cluebringer.conf | 192 ------------------ .../policyd/files/var/www/html/.htaccess | 4 - data/conf/postfix/main.cf | 2 +- docker-compose.yml | 27 --- generate_config.sh | 12 -- 11 files changed, 1 insertion(+), 357 deletions(-) delete mode 100644 data/Dockerfiles/policyd/Dockerfile delete mode 100644 data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf delete mode 100644 data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf delete mode 100644 data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db delete mode 100644 data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd delete mode 100644 data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf delete mode 100644 data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf delete mode 100644 data/Dockerfiles/policyd/files/var/www/html/.htaccess diff --git a/data/Dockerfiles/policyd/Dockerfile b/data/Dockerfiles/policyd/Dockerfile deleted file mode 100644 index 3990f9f2..00000000 --- a/data/Dockerfiles/policyd/Dockerfile +++ /dev/null @@ -1,19 +0,0 @@ -FROM docker.io/1and1internet/ubuntu-16-apache-php-7.1:latest -ARG DEBIAN_FRONTEND=noninteractive -COPY files / -RUN \ - groupadd cbpolicyd && \ - useradd -g cbpolicyd cbpolicyd && \ - apt-get update && \ - apt-get -o Dpkg::Options::=--force-confdef -y install gettext-base postfix-cluebringer postfix-cluebringer-mysql postfix-cluebringer-webui -y && \ - apt-get -y clean && \ - rm -rf /var/lib/apt/lists/* /etc/cluebringer && \ - mkdir --mode=0775 /etc/cluebringer && \ - cp /usr/share/doc/postfix-cluebringer/database/policyd-db.mysql.gz /tmp/ && \ - cp -r /usr/share/postfix-cluebringer-webui/webui/* /var/www/html/ && \ - gunzip /tmp/policyd-db.mysql.gz && \ - sed -i -e 's/TYPE=InnoDB/ENGINE=InnoDB/g' /tmp/policyd-db.mysql && \ - chmod -R 0755 /hooks && \ - chmod -R 0777 /var/www/html && \ - chmod 0666 /var/log/cbpolicyd.log -EXPOSE 10031 8080 8443 diff --git a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf deleted file mode 100644 index d5409158..00000000 --- a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/apache-2.4.conf +++ /dev/null @@ -1,12 +0,0 @@ -[program:apache-2.4] -command=/bin/bash -c "source /etc/apache2/envvars && exec /usr/sbin/apache2 -DFOREGROUND" -autostart=true -autorestart=true -startretries=3 - -# Redirect output so we can see it using "docker logs" -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - diff --git a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf b/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf deleted file mode 100644 index 53f78cf7..00000000 --- a/data/Dockerfiles/policyd/files/etc/supervisor/conf.d/cbpolicyd.conf +++ /dev/null @@ -1,12 +0,0 @@ -[program:cbpolicyd] -command=/usr/sbin/cbpolicyd --fg --config=/etc/cluebringer/cluebringer.conf -autostart=true -autorestart=true -startretries=3 - -# Redirect output so we can see it using "docker logs" -stdout_logfile=/dev/stdout -stdout_logfile_maxbytes=0 -stderr_logfile=/dev/stderr -stderr_logfile_maxbytes=0 - diff --git a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db deleted file mode 100644 index 4c53f15b..00000000 --- a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/50_install_cluebringer_db +++ /dev/null @@ -1,48 +0,0 @@ -#!/bin/bash -set -eo pipefail - -# Password protect webui -echo Creating webui user -echo $WEBUI_PASSWORD | htpasswd -ci /var/www/html/.htpasswd webui - -# Checking for DB liveness before continuing with DB set up. -count=0 -while [ $count -lt 4 ]; do - if [[ $(mysql -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "select 1" &>/dev/null ; echo $?) -ne 0 ]]; then - echo "Waiting for DB to be ready." - sleep 15 - let count+=1 - else - echo "DB appears to be ready." - break - fi -done -# Die if DB doesn't come up in time. -if [ $count -eq 4 ]; then - echo "!!!WARNING!!! DB didn't come up in time." - exit 0 -fi - -# Set up DB if it's empty. -if [[ $(mysql -N -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "SELECT COUNT(*) FROM information_schema.tables WHERE table_schema = '$MYSQL_DATABASE';") == 0 ]]; then - echo "Setting up cluebringer DB." - - # Set up DB and User - if [[ $(mysql -N -h$CLUEBRINGER_DB_HOST -uroot -p$MYSQL_ROOT_PASSWORD -e "create database $MYSQL_DATABASE;use $MYSQL_DATABASE;CREATE USER '$MYSQL_USER'@'%' IDENTIFIED BY '$MYSQL_PASSWORD';GRANT ALL PRIVILEGES ON $MYSQL_DATABASE.* TO '$MYSQL_USER'@'%';") -ne 0 ]]; then - echo "Can't create DB and Policyd DB user!" - exit 0 - fi - - # Add our policys from sql if they exist. - if [[ -e /tmpl/cluebringer/import/policy.sql ]]; then - echo "Importing our configuration." - mysql -h$CLUEBRINGER_DB_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /tmpl/cluebringer/import/policy.sql - echo "Done." - else - echo "Additional sql configuration no found importing standart configuration." - mysql -h$CLUEBRINGER_DB_HOST -u$MYSQL_USER -p$MYSQL_PASSWORD $MYSQL_DATABASE < /tmp/policyd-db.mysql - fi -else - echo "Cluebringer DB not empty, exiting." - exit 0 -fi diff --git a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd b/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd deleted file mode 100644 index 1983b4a5..00000000 --- a/data/Dockerfiles/policyd/files/hooks/supervisord-pre.d/51_configure_policyd +++ /dev/null @@ -1,14 +0,0 @@ -#!/bin/bash - -set -eu - -export DOLLAR=$ -export MYSQL_DATABASE=${MYSQL_DATABASE} -export MYSQL_USER=${MYSQL_USER} -export MYSQL_PASSWORD=${MYSQL_PASSWORD} -export CLUEBRINGER_DB_BACKEND=${CLUEBRINGER_DB_BACKEND} -export CLUEBRINGER_DB_PORT=${CLUEBRINGER_DB_PORT} -export CLUEBRINGER_DB_HOST=${CLUEBRINGER_DB_HOST} - -envsubst < /tmpl/cluebringer/cluebringer.conf > /etc/cluebringer/cluebringer.conf -envsubst < /tmpl/cluebringer/cluebringer-webui.conf > /etc/cluebringer/cluebringer-webui.conf diff --git a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf deleted file mode 100644 index a68f5a61..00000000 --- a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer-webui.conf +++ /dev/null @@ -1,16 +0,0 @@ - diff --git a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf b/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf deleted file mode 100644 index 4686f1e2..00000000 --- a/data/Dockerfiles/policyd/files/tmpl/cluebringer/cluebringer.conf +++ /dev/null @@ -1,192 +0,0 @@ -# -# Server configuration -# -[server] - -# Protocols to load -protocols=< Date: Fri, 13 Sep 2019 21:14:30 +0300 Subject: [PATCH 3/7] [Dovecot] notify scripts migrated to python3 --- data/Dockerfiles/dovecot/Dockerfile | 9 ++--- data/Dockerfiles/dovecot/quarantine_notify.py | 33 +++++++++---------- data/Dockerfiles/dovecot/quota_notify.py | 18 +++++----- 3 files changed, 30 insertions(+), 30 deletions(-) diff --git a/data/Dockerfiles/dovecot/Dockerfile b/data/Dockerfiles/dovecot/Dockerfile index 8bc60d9f..6c9afb29 100644 --- a/data/Dockerfiles/dovecot/Dockerfile +++ b/data/Dockerfiles/dovecot/Dockerfile @@ -71,10 +71,11 @@ RUN groupadd -g 5000 vmail \ libwww-perl \ mysql-client \ procps \ - python-html2text \ - python-jinja2 \ - python-mysql.connector \ - python-redis \ + python3 \ + python3-html2text \ + python3-jinja2 \ + python3-mysql.connector \ + python3-redis \ redis-server \ supervisor \ syslog-ng \ diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index b1af332a..87ef1e01 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -1,11 +1,10 @@ -#!/usr/bin/python import smtplib import os import mysql.connector -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.Utils import COMMASPACE, formatdate +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.utils import COMMASPACE, formatdate import cgi import jinja2 from jinja2 import Template @@ -20,7 +19,7 @@ while True: r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0) r.ping() except Exception as ex: - print '%s - trying again...' % (ex) + print('%s - trying again...' % (ex)) time.sleep(3) else: break @@ -30,9 +29,9 @@ time_now = int(time.time()) def query_mysql(query, headers = True, update = False): while True: try: - cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user='__DBUSER__', passwd='__DBPASS__', database='__DBNAME__', charset="utf8") + cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user='mailcow', passwd='sdvZ39iWd86UnVI772spU48VO1T8', database='mailcow', charset="utf8") except Exception as ex: - print '%s - trying again...' % (ex) + print('%s - trying again...' % (ex)) time.sleep(3) else: break @@ -40,10 +39,10 @@ def query_mysql(query, headers = True, update = False): cur.execute(query) if not update: result = [] - columns = tuple( [d[0].decode('utf8') for d in cur.description] ) + columns = tuple( [d[0] for d in cur.description] ) for row in cur: if headers: - result.append(dict(zip(columns, row))) + result.append(dict(list(zip(columns, row)))) else: result.append(row) cur.close() @@ -60,7 +59,7 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl): try: template = Template(r.get('Q_HTML')) except: - print "Error: Cannot parse quarantine template, falling back to default template." + print("Error: Cannot parse quarantine template, falling back to default template.") with open('/templates/quarantine.tpl') as file_: template = Template(file_.read()) else: @@ -91,7 +90,7 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl): break except Exception as ex: server.quit() - print '%s' % (ex) + print('%s' % (ex)) time.sleep(3) records = query_mysql('SELECT IFNULL(user_acl.quarantine, 0) AS quarantine_acl, count(id) AS counter, rcpt FROM quarantine LEFT OUTER JOIN user_acl ON user_acl.username = rcpt WHERE notified = 0 AND rcpt in (SELECT username FROM mailbox) GROUP BY rcpt') @@ -102,25 +101,25 @@ for record in records: try: last_notification = int(r.hget('Q_LAST_NOTIFIED', record['rcpt'])) if last_notification > time_now: - print 'Last notification is > time now, assuming never' + print('Last notification is > time now, assuming never') last_notification = 0 except Exception as ex: - print 'Could not determine last notification for %s, assuming never' % (record['rcpt']) + print('Could not determine last notification for %s, assuming never' % (record['rcpt'])) last_notification = 0 attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt'])) attrs = json.loads(str(attrs_json[0]['attributes'])) if attrs['quarantine_notification'] not in ('hourly', 'daily', 'weekly', 'never'): - print 'Abnormal quarantine_notification value' + print('Abnormal quarantine_notification value') continue if attrs['quarantine_notification'] == 'hourly': if last_notification == 0 or (last_notification + 3600) < time_now: - print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + print("Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter'])) notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) elif attrs['quarantine_notification'] == 'daily': if last_notification == 0 or (last_notification + 86400) < time_now: - print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + print("Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter'])) notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) elif attrs['quarantine_notification'] == 'weekly': if last_notification == 0 or (last_notification + 604800) < time_now: - print "Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter']) + print("Notifying %s about %d new items in quarantine" % (record['rcpt'], record['counter'])) notify_rcpt(record['rcpt'], record['counter'], record['quarantine_acl']) diff --git a/data/Dockerfiles/dovecot/quota_notify.py b/data/Dockerfiles/dovecot/quota_notify.py index 669adec2..fdfda304 100755 --- a/data/Dockerfiles/dovecot/quota_notify.py +++ b/data/Dockerfiles/dovecot/quota_notify.py @@ -1,10 +1,10 @@ -#!/usr/bin/python +#!/usr/bin/python3 import smtplib import os -from email.MIMEMultipart import MIMEMultipart -from email.MIMEText import MIMEText -from email.Utils import COMMASPACE, formatdate +from email.mime.multipart import MIMEMultipart +from email.mime.text import MIMEText +from email.utils import COMMASPACE, formatdate import jinja2 from jinja2 import Template import redis @@ -17,7 +17,7 @@ if len(sys.argv) > 2: percent = int(sys.argv[1]) username = str(sys.argv[2]) else: - print "Args missing" + print("Args missing") sys.exit(1) while True: @@ -25,7 +25,7 @@ while True: r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0) r.ping() except Exception as ex: - print '%s - trying again...' % (ex) + print('%s - trying again...' % (ex)) time.sleep(3) else: break @@ -34,7 +34,7 @@ if r.get('QW_HTML'): try: template = Template(r.get('QW_HTML')) except: - print "Error: Cannot parse quarantine template, falling back to default template." + print("Error: Cannot parse quarantine template, falling back to default template.") with open('/templates/quota.tpl') as file_: template = Template(file_.read()) else: @@ -55,10 +55,10 @@ try: msg.attach(html_part) msg['To'] = username p = Popen(['/usr/lib/dovecot/dovecot-lda', '-d', username, '-o', '"plugin/quota=maildir:User quota:noenforcing"'], stdout=PIPE, stdin=PIPE, stderr=STDOUT) - p.communicate(input=msg.as_string()) + p.communicate(input=bytes(msg.as_string(), 'utf-8')) except Exception as ex: - print 'Failed to send quota notification: %s' % (ex) + print('Failed to send quota notification: %s' % (ex)) sys.exit(1) try: From 8af9b5b6d162adaa98c2b0e44e3b8213c3927088 Mon Sep 17 00:00:00 2001 From: zekeriya Date: Sat, 14 Sep 2019 21:01:53 +0300 Subject: [PATCH 4/7] [Dovecot] Fixed quarantine_notify.py json decode error --- data/Dockerfiles/dovecot/quarantine_notify.py | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 87ef1e01..8866d905 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -1,3 +1,4 @@ +#!/usr/bin/python3 import smtplib import os @@ -82,7 +83,7 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl): msg.attach(html_part) msg['To'] = str(rcpt) text = msg.as_string() - server.sendmail(msg['From'].encode("ascii", errors="ignore"), msg['To'], text) + server.sendmail(msg['From'], msg['To'], text) server.quit() for res in meta_query: query_mysql('UPDATE quarantine SET notified = 1 WHERE id = "%d"' % (res['id']), update = True) @@ -107,7 +108,8 @@ for record in records: print('Could not determine last notification for %s, assuming never' % (record['rcpt'])) last_notification = 0 attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt'])) - attrs = json.loads(str(attrs_json[0]['attributes'])) + print("\n\n\n\n",attrs_json,"\n\n\n\n") + attrs = json.loads(str(attrs_json[0]['attributes'].decode('utf-8'))) if attrs['quarantine_notification'] not in ('hourly', 'daily', 'weekly', 'never'): print('Abnormal quarantine_notification value') continue From adbecef56fc777ea62785a85e8ed461c8048fb8d Mon Sep 17 00:00:00 2001 From: zekeriya Date: Sat, 14 Sep 2019 21:07:18 +0300 Subject: [PATCH 5/7] [Dovecot] Fixed variable names for DB connection. --- data/Dockerfiles/dovecot/quarantine_notify.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 8866d905..8a33c4e3 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -30,7 +30,7 @@ time_now = int(time.time()) def query_mysql(query, headers = True, update = False): while True: try: - cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user='mailcow', passwd='sdvZ39iWd86UnVI772spU48VO1T8', database='mailcow', charset="utf8") + cnx = mysql.connector.connect(unix_socket = '/var/run/mysqld/mysqld.sock', user='__DBUSER__', passwd='__DBPASS__', database='__DBNAME__', charset="utf8") except Exception as ex: print('%s - trying again...' % (ex)) time.sleep(3) From 96042bdab81cca42fe235240ee302e87d4e1ca1d Mon Sep 17 00:00:00 2001 From: zekeriya Date: Sat, 14 Sep 2019 21:48:13 +0300 Subject: [PATCH 6/7] [Dovecot] removed non-ascii chars from 'from' field before send --- data/Dockerfiles/dovecot/quarantine_notify.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 8a33c4e3..8d0d1201 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -74,7 +74,9 @@ def notify_rcpt(rcpt, msg_count, quarantine_acl): server = smtplib.SMTP('postfix', 590, 'quarantine') server.ehlo() msg = MIMEMultipart('alternative') - msg['From'] = r.get('Q_SENDER') or "quarantine@localhost" + msg_from = r.get('Q_SENDER') or "quarantine@localhost" + # Remove non-ascii chars from field + msg['From'] = ''.join([i if ord(i) < 128 else '' for i in msg_from]) msg['Subject'] = r.get('Q_SUBJ') or "Spam Quarantine Notification" msg['Date'] = formatdate(localtime = True) text_part = MIMEText(text, 'plain', 'utf-8') From d62ec4498ab036bd46dbf63ceff8e0200c4d9eed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Zekeriya=20Akg=C3=BCl?= Date: Sun, 15 Sep 2019 10:36:01 +0300 Subject: [PATCH 7/7] Removed unnecessary print --- data/Dockerfiles/dovecot/quarantine_notify.py | 1 - 1 file changed, 1 deletion(-) diff --git a/data/Dockerfiles/dovecot/quarantine_notify.py b/data/Dockerfiles/dovecot/quarantine_notify.py index 8d0d1201..ee9a25dc 100755 --- a/data/Dockerfiles/dovecot/quarantine_notify.py +++ b/data/Dockerfiles/dovecot/quarantine_notify.py @@ -110,7 +110,6 @@ for record in records: print('Could not determine last notification for %s, assuming never' % (record['rcpt'])) last_notification = 0 attrs_json = query_mysql('SELECT attributes FROM mailbox WHERE username = "%s"' % (record['rcpt'])) - print("\n\n\n\n",attrs_json,"\n\n\n\n") attrs = json.loads(str(attrs_json[0]['attributes'].decode('utf-8'))) if attrs['quarantine_notification'] not in ('hourly', 'daily', 'weekly', 'never'): print('Abnormal quarantine_notification value')