diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 08de0e88..2e637206 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -7,7 +7,7 @@ COPY requirements-prod.txt requirements.txt RUN apk add --no-cache openssl \ && apk add --no-cache --virtual build-dep openssl-dev libffi-dev python-dev build-base \ && pip install -r requirements.txt \ - && apk del build-dep + && apk del --no-cache build-dep COPY mailu ./mailu COPY migrations ./migrations diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index a3f0353c..167f04ae 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -11,7 +11,6 @@ import os import docker import socket import uuid -import redis from werkzeug.contrib import fixers @@ -58,7 +57,7 @@ default_config = { 'RECAPTCHA_PUBLIC_KEY': '', 'RECAPTCHA_PRIVATE_KEY': '', # Advanced settings - 'PASSWORD_SCHEME': 'SHA512-CRYPT', + 'PASSWORD_SCHEME': 'BLF-CRYPT', # Host settings 'HOST_IMAP': 'imap', 'HOST_POP3': 'imap', @@ -89,9 +88,6 @@ manager.add_command('db', flask_migrate.MigrateCommand) babel = flask_babel.Babel(app) translations = list(map(str, babel.list_translations())) -# Quota manager -quota = redis.Redis.from_url(app.config.get("QUOTA_STORAGE_URL")) - @babel.localeselector def get_locale(): return flask.request.accept_languages.best_match(translations) diff --git a/core/admin/mailu/internal/__init__.py b/core/admin/mailu/internal/__init__.py index 6419ad10..80a3c754 100644 --- a/core/admin/mailu/internal/__init__.py +++ b/core/admin/mailu/internal/__init__.py @@ -6,7 +6,8 @@ import socket import flask -internal = flask.Blueprint('internal', __name__) +internal = flask.Blueprint('internal', __name__, template_folder='templates') + @internal.app_errorhandler(RateLimitExceeded) def rate_limit_handler(e): @@ -17,6 +18,7 @@ def rate_limit_handler(e): response.headers['Auth-Wait'] = '3' return response + @limiter.request_filter def whitelist_webmail(): try: @@ -26,4 +28,4 @@ def whitelist_webmail(): return False -from mailu.internal import views +from mailu.internal.views import * diff --git a/core/dovecot/sieve/before.sieve b/core/admin/mailu/internal/templates/default.sieve similarity index 55% rename from core/dovecot/sieve/before.sieve rename to core/admin/mailu/internal/templates/default.sieve index 6ebc20c5..5a80a181 100644 --- a/core/dovecot/sieve/before.sieve +++ b/core/admin/mailu/internal/templates/default.sieve @@ -8,8 +8,6 @@ require "regex"; require "relational"; require "date"; require "comparator-i;ascii-numeric"; -require "vnd.dovecot.extdata"; -require "vnd.dovecot.execute"; require "spamtestplus"; require "editheader"; require "index"; @@ -20,21 +18,23 @@ if header :index 2 :matches "Received" "from * by * for <*>; *" addheader "Delivered-To" "<${3}>"; } -if allof (string :is "${extdata.spam_enabled}" "1", - spamtest :percent :value "gt" :comparator "i;ascii-numeric" "${extdata.spam_threshold}") +{% if user.spam_enabled %} +if spamtest :percent :value "gt" :comparator "i;ascii-numeric" "{{ user.spam_threshold }}" { setflag "\\seen"; fileinto :create "Junk"; stop; } +{% endif %} if exists "X-Virus" { discard; stop; } -if allof (string :is "${extdata.reply_enabled}" "1", - currentdate :value "le" "date" "${extdata.reply_enddate}") +{% if user.reply_enabled %} +if currentdate :value "le" "date" "{{ user.reply_enddate }}" { - vacation :days 1 :subject "${extdata.reply_subject}" "${extdata.reply_body}"; + vacation :days 1 :subject "{{ user.reply_subject }}" "{{ user.reply_body }}"; } +{% endif %} diff --git a/core/admin/mailu/internal/views/__init__.py b/core/admin/mailu/internal/views/__init__.py new file mode 100644 index 00000000..a32106c0 --- /dev/null +++ b/core/admin/mailu/internal/views/__init__.py @@ -0,0 +1,3 @@ +__all__ = [ + 'auth', 'postfix', 'dovecot', 'fetch' +] diff --git a/core/admin/mailu/internal/views.py b/core/admin/mailu/internal/views/auth.py similarity index 99% rename from core/admin/mailu/internal/views.py rename to core/admin/mailu/internal/views/auth.py index b97d329e..823fbd40 100644 --- a/core/admin/mailu/internal/views.py +++ b/core/admin/mailu/internal/views/auth.py @@ -4,7 +4,6 @@ from mailu.internal import internal, nginx import flask import flask_login import base64 -import urllib @internal.route("/auth/email") diff --git a/core/admin/mailu/internal/views/dovecot.py b/core/admin/mailu/internal/views/dovecot.py new file mode 100644 index 00000000..c2f53794 --- /dev/null +++ b/core/admin/mailu/internal/views/dovecot.py @@ -0,0 +1,40 @@ +from mailu import db, models +from mailu.internal import internal + +import flask + + +@internal.route("/dovecot/passdb/") +def dovecot_passdb_dict(user_email): + user = models.User.query.get(user_email) or flask.abort(404) + return flask.jsonify({ + "password": user.password, + }) + + +@internal.route("/dovecot/userdb/") +def dovecot_userdb_dict(user_email): + user = models.User.query.get(user_email) or flask.abort(404) + return flask.jsonify({ + "quota_rule": "*:bytes={}".format(user.quota_bytes) + }) + + +@internal.route("/dovecot/quota//", methods=["POST"]) +def dovecot_quota(ns, user_email): + user = models.User.query.get(user_email) or flask.abort(404) + if ns == "storage": + user.quota_bytes_used = flask.request.get_json() + db.session.commit() + return flask.jsonify(None) + + +@internal.route("/dovecot/sieve/name/