From e7caff9811512dc47bddcd9aa11ce983254e7c40 Mon Sep 17 00:00:00 2001 From: David Fairbrother Date: Mon, 5 Oct 2020 15:13:07 +0100 Subject: [PATCH 001/163] Add ability to set no WEBROOT_REDIRECT to Nginx Adds a 'none' env option to WEBROOT_REDIRECT so that no `location /` configuration is written to nginx.conf. This is useful for setting up Mailu and Mailman where we override the root to proxy to the mailing list server instead. Without this change the nginx container will not start, or for 1.7 users can set their WEBMAIL_PATH to / with no webmail to get the same results. This fix means that future users don't have to choose between webmail and a root override and makes the configuration intention clear. --- core/nginx/conf/nginx.conf | 2 +- docs/configuration.rst | 15 ++++++++++----- docs/faq.rst | 2 ++ 3 files changed, 13 insertions(+), 6 deletions(-) diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 8f6eaa0d..f672c7a3 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -115,7 +115,7 @@ http { include /overrides/*.conf; # Actual logic - {% if WEB_WEBMAIL != '/' %} + {% if WEB_WEBMAIL != '/' and WEBROOT_REDIRECT != 'none' %} location / { {% if WEBROOT_REDIRECT %} try_files $uri {{ WEBROOT_REDIRECT }}; diff --git a/docs/configuration.rst b/docs/configuration.rst index 5ff3546a..c2c55190 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -92,14 +92,19 @@ the localpart for DMARC rua and ruf email addresses. Full-text search is enabled for IMAP is enabled by default. This feature can be disabled (e.g. for performance reasons) by setting the optional variable ``FULL_TEXT_SEARCH`` to ``off``. +.. _web_settings: + Web settings ------------ -The ``WEB_ADMIN`` contains the path to the main admin interface, while -``WEB_WEBMAIL`` contains the path to the Web email client. -The ``WEBROOT_REDIRECT`` redirects all non-found queries to the set path. -An empty ``WEBROOT_REDIRECT`` value disables redirecting and enables classic -behavior of a 404 result when not found. +- ``WEB_ADMIN`` contains the path to the main admin interface + +- ``WEB_WEBMAIL`` contains the path to the Web email client. + +- ``WEBROOT_REDIRECT`` redirects all non-found queries to the set path. + An empty ``WEBROOT_REDIRECT`` value disables redirecting and enables classic behavior of a 404 result when not found. + Alternatively, ``WEBROOT_REDIRECT`` can be set to ``none`` if you are using an Nginx override for ``location /``. + All three options need a leading slash (``/``) to work. .. note:: ``WEBROOT_REDIRECT`` has to point to a valid path on the webserver. diff --git a/docs/faq.rst b/docs/faq.rst index b292cd05..296cd59f 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -262,6 +262,8 @@ correct syntax. The following file names will be taken as override configuration - `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory; - `Rspamd`_ - All files in the ``rspamd`` sub-directory. +To override the root location (``/``) in Nginx ``WEBROOT_REDIRECT`` needs to be set to ``none`` in the env file (see :ref:`web settings `). + *Issue reference:* `206`_, `1368`_. I want to integrate Nextcloud 15 (and newer) with Mailu From e46d9e1fc9f5b50a40f785628beb63850e0a6d8a Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 11:26:37 +0200 Subject: [PATCH 002/163] Update admin-lte version in package.json --- core/admin/package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/package.json b/core/admin/package.json index a1107c69..ac18f61e 100644 --- a/core/admin/package.json +++ b/core/admin/package.json @@ -11,7 +11,7 @@ "dependencies": { "@babel/core": "^7.4.4", "@babel/preset-env": "^7.4.4", - "admin-lte": "^2.4.10", + "admin-lte": "^3.1.0", "babel-loader": "^8.0.5", "bootstrap": "^3.4.1", "css-loader": "^2.1.1", From c97728289bbe0e466454832f060276e0fb29702e Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 11:34:03 +0200 Subject: [PATCH 003/163] Update node version for building the image (AdminLTE requires node 10 or higher) --- core/admin/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index f3b8643c..81ffd147 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -1,7 +1,7 @@ # First stage to build assets ARG DISTRO=alpine:3.12 ARG ARCH="" -FROM ${ARCH}node:8 as assets +FROM ${ARCH}node:15 as assets COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static COPY package.json ./ From 6b3170cb4c1f9bcda28c25b7c27849cc1de06f7f Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 14:42:15 +0200 Subject: [PATCH 004/163] Update side menu --- core/admin/assets/vendor.js | 18 +- core/admin/mailu/ui/templates/base.html | 48 ++-- core/admin/mailu/ui/templates/sidebar.html | 254 +++++++++++---------- 3 files changed, 176 insertions(+), 144 deletions(-) diff --git a/core/admin/assets/vendor.js b/core/admin/assets/vendor.js index f7ed03c8..a5ff7a3c 100644 --- a/core/admin/assets/vendor.js +++ b/core/admin/assets/vendor.js @@ -3,17 +3,21 @@ import jQuery from 'jquery'; import 'select2/dist/css/select2.css'; // bootstrap -import 'bootstrap/less/bootstrap.less'; -import 'bootstrap'; +// import 'bootstrap/less/bootstrap.less'; +// import 'bootstrap'; // FA -import 'font-awesome/scss/font-awesome.scss'; +// import 'font-awesome/scss/font-awesome.scss'; // FA is included with AdminLTE +import 'admin-lte/plugins/fontawesome-free/css/fontawesome.css'; +import 'admin-lte/plugins/fontawesome-free/css/regular.css'; +import 'admin-lte/plugins/fontawesome-free/css/solid.css'; // AdminLTE -import 'admin-lte/build/less/AdminLTE-without-plugins.less'; -import 'admin-lte/build/less/select2.less'; -import 'admin-lte/build/less/skins/skin-blue.less'; +import 'admin-lte/build/scss/adminlte.scss'; +// import 'admin-lte/build/less/AdminLTE-without-plugins.less'; // doesn't exist +// import 'admin-lte/build/less/select2.less'; // doesn't exist +// import 'admin-lte/build/less/skins/skin-blue.less'; // doesn't exist import 'admin-lte/build/js/Layout.js'; import 'admin-lte/build/js/ControlSidebar.js'; import 'admin-lte/build/js/PushMenu.js'; -import 'admin-lte/build/js/BoxRefresh.js'; +// import 'admin-lte/build/js/BoxRefresh.js'; // doesn't exist diff --git a/core/admin/mailu/ui/templates/base.html b/core/admin/mailu/ui/templates/base.html index 74d5653c..c5b09159 100644 --- a/core/admin/mailu/ui/templates/base.html +++ b/core/admin/mailu/ui/templates/base.html @@ -8,43 +8,47 @@ Mailu-Admin - {{ config["SITENAME"] }} - +
-
- -
-
diff --git a/core/admin/mailu/ui/templates/sidebar.html b/core/admin/mailu/ui/templates/sidebar.html index 78be75d5..7c86378d 100644 --- a/core/admin/mailu/ui/templates/sidebar.html +++ b/core/admin/mailu/ui/templates/sidebar.html @@ -1,120 +1,144 @@ - + + {% if config["WEBMAIL"] != "none" %} + + {% endif %} + + + + {% if config['DOMAIN_REGISTRATION'] %} + + {% endif %} + {% if current_user.is_authenticated %} + + {% else %} + + {% if signup_domains %} + + {% endif %} + {% endif %} + + + From deca6e0c4a311d9156555ab65fb08f850cd4094e Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 14:45:12 +0200 Subject: [PATCH 005/163] update user/settings --- core/admin/mailu/ui/templates/macros.html | 10 +++++----- core/admin/mailu/ui/templates/user/settings.html | 6 +++--- 2 files changed, 8 insertions(+), 8 deletions(-) diff --git a/core/admin/mailu/ui/templates/macros.html b/core/admin/mailu/ui/templates/macros.html index ec4cf6e4..a1fc2919 100644 --- a/core/admin/mailu/ui/templates/macros.html +++ b/core/admin/mailu/ui/templates/macros.html @@ -64,18 +64,18 @@ {% endmacro %} -{% macro box(title=None, theme="primary", header=True) %} +{% macro card(title=None, theme="primary", header=True) %}
-
+
{% if header %} -
+
{% if title %} -

{{ title }}

+

{{ title }}

{% endif %}
{% endif %} -
+
{{ caller() }}
diff --git a/core/admin/mailu/ui/templates/user/settings.html b/core/admin/mailu/ui/templates/user/settings.html index b6ade695..e58cc89a 100644 --- a/core/admin/mailu/ui/templates/user/settings.html +++ b/core/admin/mailu/ui/templates/user/settings.html @@ -12,18 +12,18 @@
{{ form.hidden_tag() }} - {% call macros.box(title=_("Displayed name")) %} + {% call macros.card(title=_("Displayed name")) %} {{ macros.form_field(form.displayed_name) }} {% endcall %} - {% call macros.box(title=_("Antispam")) %} + {% call macros.card(title=_("Antispam")) %} {{ macros.form_field(form.spam_enabled) }} {{ macros.form_field(form.spam_threshold, step=1, max=100, prepend=''+form.spam_threshold.data.__str__()+' / 100', oninput='$("#threshold").text(this.value);') }} {% endcall %} - {% call macros.box(title=_("Auto-forward")) %} + {% call macros.card(title=_("Auto-forward")) %} {{ macros.form_field(form.forward_enabled, onchange="if(this.checked){$('#forward_destination,#forward_keep').removeAttr('disabled')} else{$('#forward_destination,#forward_keep').attr('disabled', '')}") }} From 0c5fda3fca6930d2ba1f6a34df7c223e097d8d12 Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 14:47:41 +0200 Subject: [PATCH 006/163] Change macros.box to macros.card --- core/admin/mailu/ui/templates/admin/create.html | 2 +- core/admin/mailu/ui/templates/alias/create.html | 2 +- core/admin/mailu/ui/templates/announcement.html | 2 +- core/admin/mailu/ui/templates/client.html | 4 ++-- core/admin/mailu/ui/templates/confirm.html | 2 +- core/admin/mailu/ui/templates/domain/create.html | 2 +- core/admin/mailu/ui/templates/domain/signup.html | 4 ++-- core/admin/mailu/ui/templates/fetch/create.html | 4 ++-- core/admin/mailu/ui/templates/form.html | 2 +- core/admin/mailu/ui/templates/manager/create.html | 2 +- core/admin/mailu/ui/templates/user/create.html | 4 ++-- core/admin/mailu/ui/templates/user/forward.html | 2 +- core/admin/mailu/ui/templates/user/reply.html | 2 +- core/admin/mailu/ui/templates/user/signup.html | 2 +- 14 files changed, 18 insertions(+), 18 deletions(-) diff --git a/core/admin/mailu/ui/templates/admin/create.html b/core/admin/mailu/ui/templates/admin/create.html index 8d3a7b58..6c2413bc 100644 --- a/core/admin/mailu/ui/templates/admin/create.html +++ b/core/admin/mailu/ui/templates/admin/create.html @@ -5,7 +5,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.admin, class_='mailselect') }} diff --git a/core/admin/mailu/ui/templates/alias/create.html b/core/admin/mailu/ui/templates/alias/create.html index 38d7e7e5..4b0ea3e2 100644 --- a/core/admin/mailu/ui/templates/alias/create.html +++ b/core/admin/mailu/ui/templates/alias/create.html @@ -9,7 +9,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.localpart, append='@'+domain.name+'') }} diff --git a/core/admin/mailu/ui/templates/announcement.html b/core/admin/mailu/ui/templates/announcement.html index 7dd34d3f..acdbde1a 100644 --- a/core/admin/mailu/ui/templates/announcement.html +++ b/core/admin/mailu/ui/templates/announcement.html @@ -5,7 +5,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.announcement_subject) }} diff --git a/core/admin/mailu/ui/templates/client.html b/core/admin/mailu/ui/templates/client.html index 81bee135..ee1b1c28 100644 --- a/core/admin/mailu/ui/templates/client.html +++ b/core/admin/mailu/ui/templates/client.html @@ -9,7 +9,7 @@ configure your email client {% endblock %} {% block content %} -{% call macros.box(title="Incoming mail") %} +{% call macros.card(title="Incoming mail") %} @@ -36,7 +36,7 @@ configure your email client
{% endcall %} -{% call macros.box(title="Outgoing mail") %} +{% call macros.card(title="Outgoing mail") %} diff --git a/core/admin/mailu/ui/templates/confirm.html b/core/admin/mailu/ui/templates/confirm.html index 3b8a451f..d0f6acf3 100644 --- a/core/admin/mailu/ui/templates/confirm.html +++ b/core/admin/mailu/ui/templates/confirm.html @@ -9,7 +9,7 @@ {% endblock %} {% block content %} -{% call macros.box(theme="warning") %} +{% call macros.card(theme="warning") %}

{% trans action %}You are about to {{ action }}. Please confirm your action.{% endtrans %}

{{ macros.form(form) }} {% endcall %} diff --git a/core/admin/mailu/ui/templates/domain/create.html b/core/admin/mailu/ui/templates/domain/create.html index d67e3e89..d84159b1 100644 --- a/core/admin/mailu/ui/templates/domain/create.html +++ b/core/admin/mailu/ui/templates/domain/create.html @@ -5,7 +5,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.name) }} diff --git a/core/admin/mailu/ui/templates/domain/signup.html b/core/admin/mailu/ui/templates/domain/signup.html index c8a52f6c..77b7fec9 100644 --- a/core/admin/mailu/ui/templates/domain/signup.html +++ b/core/admin/mailu/ui/templates/domain/signup.html @@ -9,7 +9,7 @@ {{ form.hidden_tag() }} - {% call macros.box(title="Requirements") %} + {% call macros.card(title="Requirements") %}

{% trans %}In order to register a new domain, you must first setup the domain zone so that the domain MX points to this server{% endtrans %} ({{ config["HOSTNAMES"].split(",")[0] }}). @@ -22,7 +22,7 @@

{% endcall %} - {% call macros.box() %} + {% call macros.card() %} {% if form.localpart %} {{ macros.form_fields((form.localpart, form.name), append='@') }} {{ macros.form_fields((form.pw, form.pw2)) }} diff --git a/core/admin/mailu/ui/templates/fetch/create.html b/core/admin/mailu/ui/templates/fetch/create.html index bc69fc44..ed190961 100644 --- a/core/admin/mailu/ui/templates/fetch/create.html +++ b/core/admin/mailu/ui/templates/fetch/create.html @@ -11,7 +11,7 @@ {% block content %} {{ form.hidden_tag() }} - {% call macros.box(title="Remote server") %} + {% call macros.card(title="Remote server") %} {{ macros.form_field(form.protocol) }} {{ macros.form_fields((form.host, form.port)) }} {{ macros.form_field(form.tls) }} @@ -22,7 +22,7 @@ {{ macros.form_field(form.password) }} {% endcall %} - {% call macros.box(title="Settings") %} + {% call macros.card(title="Settings") %} {{ macros.form_field(form.keep) }} {% endcall %} diff --git a/core/admin/mailu/ui/templates/form.html b/core/admin/mailu/ui/templates/form.html index 25d7e83c..0e65ce33 100644 --- a/core/admin/mailu/ui/templates/form.html +++ b/core/admin/mailu/ui/templates/form.html @@ -1,7 +1,7 @@ {% extends "base.html" %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ macros.form(form) }} {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/manager/create.html b/core/admin/mailu/ui/templates/manager/create.html index e3911642..bc5e6ca9 100644 --- a/core/admin/mailu/ui/templates/manager/create.html +++ b/core/admin/mailu/ui/templates/manager/create.html @@ -9,7 +9,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.manager, class_='mailselect') }} diff --git a/core/admin/mailu/ui/templates/user/create.html b/core/admin/mailu/ui/templates/user/create.html index ed7b9884..a28c7048 100644 --- a/core/admin/mailu/ui/templates/user/create.html +++ b/core/admin/mailu/ui/templates/user/create.html @@ -12,7 +12,7 @@ {{ form.hidden_tag() }} - {% call macros.box(_("General")) %} + {% call macros.card(_("General")) %} {{ macros.form_field(form.localpart, append='@'+domain.name+'') }} {{ macros.form_fields((form.pw, form.pw2)) }} {{ macros.form_field(form.displayed_name) }} @@ -20,7 +20,7 @@ {{ macros.form_field(form.enabled) }} {% endcall %} - {% call macros.box(_("Features and quotas"), theme="success") %} + {% call macros.card(_("Features and quotas"), theme="success") %} {{ macros.form_field(form.quota_bytes, step=1000000000, max=(max_quota_bytes or domain.max_quota_bytes or 50000000000), prepend=''+((form.quota_bytes.data//1000000000).__str__() if form.quota_bytes.data else '∞')+' GiB', oninput='$("#quota").text(this.value == 0 ? "∞" : this.value/1000000000);') }} diff --git a/core/admin/mailu/ui/templates/user/forward.html b/core/admin/mailu/ui/templates/user/forward.html index 769d439d..6059f0ed 100644 --- a/core/admin/mailu/ui/templates/user/forward.html +++ b/core/admin/mailu/ui/templates/user/forward.html @@ -9,7 +9,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.forward_enabled, diff --git a/core/admin/mailu/ui/templates/user/reply.html b/core/admin/mailu/ui/templates/user/reply.html index 7225a178..7a6b7fa8 100644 --- a/core/admin/mailu/ui/templates/user/reply.html +++ b/core/admin/mailu/ui/templates/user/reply.html @@ -9,7 +9,7 @@ {% endblock %} {% block content %} -{% call macros.box() %} +{% call macros.card() %} {{ form.hidden_tag() }} {{ macros.form_field(form.reply_enabled, diff --git a/core/admin/mailu/ui/templates/user/signup.html b/core/admin/mailu/ui/templates/user/signup.html index f540d660..2b20bde9 100644 --- a/core/admin/mailu/ui/templates/user/signup.html +++ b/core/admin/mailu/ui/templates/user/signup.html @@ -11,7 +11,7 @@ {% block content %} {{ form.hidden_tag() }} - {% call macros.box() %} + {% call macros.card() %} {{ macros.form_field(form.localpart, append='@'+domain.name+'') }} {{ macros.form_fields((form.pw, form.pw2)) }} {% if form.captcha %} From cdfa94c2430ca43a43ba538ae7e538e8d71c33da Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 14:59:12 +0200 Subject: [PATCH 007/163] Make main action float right --- core/admin/mailu/ui/templates/admin/list.html | 2 +- core/admin/mailu/ui/templates/alias/list.html | 2 +- core/admin/mailu/ui/templates/alternative/list.html | 2 +- core/admin/mailu/ui/templates/domain/details.html | 2 +- core/admin/mailu/ui/templates/domain/list.html | 2 +- core/admin/mailu/ui/templates/fetch/list.html | 2 +- core/admin/mailu/ui/templates/manager/list.html | 2 +- core/admin/mailu/ui/templates/relay/list.html | 2 +- core/admin/mailu/ui/templates/token/list.html | 2 +- core/admin/mailu/ui/templates/user/list.html | 2 +- 10 files changed, 10 insertions(+), 10 deletions(-) diff --git a/core/admin/mailu/ui/templates/admin/list.html b/core/admin/mailu/ui/templates/admin/list.html index 72b5a1fa..856f6830 100644 --- a/core/admin/mailu/ui/templates/admin/list.html +++ b/core/admin/mailu/ui/templates/admin/list.html @@ -5,7 +5,7 @@ {% endblock %} {% block main_action %} - + {% trans %}Add administrator{% endtrans %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/alias/list.html b/core/admin/mailu/ui/templates/alias/list.html index 29766b25..4bb69169 100644 --- a/core/admin/mailu/ui/templates/alias/list.html +++ b/core/admin/mailu/ui/templates/alias/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}Add alias{% endtrans %} +{% trans %}Add alias{% endtrans %} {% endblock %} {% block content %} diff --git a/core/admin/mailu/ui/templates/alternative/list.html b/core/admin/mailu/ui/templates/alternative/list.html index 56e7565b..dc981ef6 100644 --- a/core/admin/mailu/ui/templates/alternative/list.html +++ b/core/admin/mailu/ui/templates/alternative/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}Add alternative{% endtrans %} +{% trans %}Add alternative{% endtrans %} {% endblock %} {% block content %} diff --git a/core/admin/mailu/ui/templates/domain/details.html b/core/admin/mailu/ui/templates/domain/details.html index 65c6ec1a..8aa35f22 100644 --- a/core/admin/mailu/ui/templates/domain/details.html +++ b/core/admin/mailu/ui/templates/domain/details.html @@ -10,7 +10,7 @@ {% block main_action %} {% if current_user.global_admin %} - + {% if domain.dkim_publickey %} {% trans %}Regenerate keys{% endtrans %} {% else %} diff --git a/core/admin/mailu/ui/templates/domain/list.html b/core/admin/mailu/ui/templates/domain/list.html index 2431faa5..fcc3a72c 100644 --- a/core/admin/mailu/ui/templates/domain/list.html +++ b/core/admin/mailu/ui/templates/domain/list.html @@ -6,7 +6,7 @@ {% block main_action %} {% if current_user.global_admin %} -{% trans %}New domain{% endtrans %} +{% trans %}New domain{% endtrans %} {% endif %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/fetch/list.html b/core/admin/mailu/ui/templates/fetch/list.html index 07ab5ad8..09253a21 100644 --- a/core/admin/mailu/ui/templates/fetch/list.html +++ b/core/admin/mailu/ui/templates/fetch/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}Add an account{% endtrans %} +{% trans %}Add an account{% endtrans %} {% endblock %} {% block content %} diff --git a/core/admin/mailu/ui/templates/manager/list.html b/core/admin/mailu/ui/templates/manager/list.html index d818a876..b660bf6d 100644 --- a/core/admin/mailu/ui/templates/manager/list.html +++ b/core/admin/mailu/ui/templates/manager/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}Add manager{% endtrans %} +{% trans %}Add manager{% endtrans %} {% endblock %} {% block content %} diff --git a/core/admin/mailu/ui/templates/relay/list.html b/core/admin/mailu/ui/templates/relay/list.html index bb00b1d9..aef189ad 100644 --- a/core/admin/mailu/ui/templates/relay/list.html +++ b/core/admin/mailu/ui/templates/relay/list.html @@ -6,7 +6,7 @@ {% block main_action %} {% if current_user.global_admin %} -{% trans %}New relayed domain{% endtrans %} +{% trans %}New relayed domain{% endtrans %} {% endif %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/token/list.html b/core/admin/mailu/ui/templates/token/list.html index ad560e6a..99f67383 100644 --- a/core/admin/mailu/ui/templates/token/list.html +++ b/core/admin/mailu/ui/templates/token/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}New token{% endtrans %} +{% trans %}New token{% endtrans %} {% endblock %} {% block content %} diff --git a/core/admin/mailu/ui/templates/user/list.html b/core/admin/mailu/ui/templates/user/list.html index 2aff662f..ab896ee6 100644 --- a/core/admin/mailu/ui/templates/user/list.html +++ b/core/admin/mailu/ui/templates/user/list.html @@ -9,7 +9,7 @@ {% endblock %} {% block main_action %} -{% trans %}Add user{% endtrans %} +{% trans %}Add user{% endtrans %} {% endblock %} {% block content %} From 7d3c9d412d430d7fbd578df1cb738126f7e1c53e Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 16:05:30 +0200 Subject: [PATCH 008/163] Change tables to datatables --- core/admin/assets/app.js | 11 ++- core/admin/assets/vendor.js | 2 + core/admin/mailu/ui/templates/admin/list.html | 28 ++++--- core/admin/mailu/ui/templates/alias/list.html | 46 ++++++------ .../mailu/ui/templates/alternative/list.html | 32 ++++---- .../admin/mailu/ui/templates/domain/list.html | 74 ++++++++++--------- core/admin/mailu/ui/templates/fetch/list.html | 54 +++++++------- core/admin/mailu/ui/templates/macros.html | 4 +- .../mailu/ui/templates/manager/list.html | 12 ++- core/admin/mailu/ui/templates/relay/list.html | 46 ++++++------ core/admin/mailu/ui/templates/token/list.html | 36 +++++---- core/admin/mailu/ui/templates/user/list.html | 68 +++++++++-------- 12 files changed, 228 insertions(+), 185 deletions(-) diff --git a/core/admin/assets/app.js b/core/admin/assets/app.js index dc981081..d87832a6 100644 --- a/core/admin/assets/app.js +++ b/core/admin/assets/app.js @@ -1,10 +1,17 @@ require('./app.css'); import 'select2'; +import 'admin-lte/plugins/datatables/jquery.dataTables.js'; +import 'admin-lte/plugins/datatables-bs4/js/dataTables.bootstrap4.js'; +import 'admin-lte/plugins/datatables-responsive/js/dataTables.responsive.js'; +import 'admin-lte/plugins/datatables-responsive/js/responsive.bootstrap4.js'; + jQuery("document").ready(function() { jQuery(".mailselect").select2({ tags: true, tokenSeparators: [',', ' '] - }) + }); + jQuery(".table").DataTable({ + "responsive": true, + }); }); - diff --git a/core/admin/assets/vendor.js b/core/admin/assets/vendor.js index a5ff7a3c..65bee27f 100644 --- a/core/admin/assets/vendor.js +++ b/core/admin/assets/vendor.js @@ -14,6 +14,8 @@ import 'admin-lte/plugins/fontawesome-free/css/solid.css'; // AdminLTE import 'admin-lte/build/scss/adminlte.scss'; +import 'admin-lte/plugins/datatables-bs4/css/dataTables.bootstrap4.css'; +import 'admin-lte/plugins/datatables-responsive/css/responsive.bootstrap4.css'; // import 'admin-lte/build/less/AdminLTE-without-plugins.less'; // doesn't exist // import 'admin-lte/build/less/select2.less'; // doesn't exist // import 'admin-lte/build/less/skins/skin-blue.less'; // doesn't exist diff --git a/core/admin/mailu/ui/templates/admin/list.html b/core/admin/mailu/ui/templates/admin/list.html index 856f6830..f2f5d229 100644 --- a/core/admin/mailu/ui/templates/admin/list.html +++ b/core/admin/mailu/ui/templates/admin/list.html @@ -12,17 +12,21 @@ {% block content %} {% call macros.table() %} - - - - -{% for admin in admins %} - - - - -{% endfor %} + + + + + + + + {% for admin in admins %} + + + + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/alias/list.html b/core/admin/mailu/ui/templates/alias/list.html index 4bb69169..e8ddc862 100644 --- a/core/admin/mailu/ui/templates/alias/list.html +++ b/core/admin/mailu/ui/templates/alias/list.html @@ -14,26 +14,30 @@ {% block content %} {% call macros.table() %} - - - - - - - - -{% for alias in domain.aliases %} - - - - - - - - -{% endfor %} + + + + + + + + + + + + {% for alias in domain.aliases %} + + + + + + + + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/alternative/list.html b/core/admin/mailu/ui/templates/alternative/list.html index dc981ef6..f123eb9f 100644 --- a/core/admin/mailu/ui/templates/alternative/list.html +++ b/core/admin/mailu/ui/templates/alternative/list.html @@ -14,19 +14,23 @@ {% block content %} {% call macros.table() %} - - - - - -{% for alternative in domain.alternatives %} - - - - - -{% endfor %} + + + + + + + + + {% for alternative in domain.alternatives %} + + + + + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/domain/list.html b/core/admin/mailu/ui/templates/domain/list.html index fcc3a72c..c82647df 100644 --- a/core/admin/mailu/ui/templates/domain/list.html +++ b/core/admin/mailu/ui/templates/domain/list.html @@ -12,40 +12,44 @@ {% block content %} {% call macros.table() %} - - - - - - - - - - -{% for domain in current_user.get_managed_domains() %} - - - - - - - - - - -{% endfor %} + + + + + + + + + + + + + + {% for domain in current_user.get_managed_domains() %} + + + + + + + + + + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/fetch/list.html b/core/admin/mailu/ui/templates/fetch/list.html index 09253a21..77f66bb1 100644 --- a/core/admin/mailu/ui/templates/fetch/list.html +++ b/core/admin/mailu/ui/templates/fetch/list.html @@ -14,30 +14,34 @@ {% block content %} {% call macros.table() %} - - - - - - - - - - -{% for fetch in user.fetches %} - - - - - - - - - - -{% endfor %} + + + + + + + + + + + + + + {% for fetch in user.fetches %} + + + + + + + + + + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/macros.html b/core/admin/mailu/ui/templates/macros.html index a1fc2919..6d821ef8 100644 --- a/core/admin/mailu/ui/templates/macros.html +++ b/core/admin/mailu/ui/templates/macros.html @@ -86,11 +86,9 @@ {% macro table(theme="primary") %}
-
+
{% trans %}Actions{% endtrans %}{% trans %}Email{% endtrans %}
- - {{ admin }}
{% trans %}Actions{% endtrans %}{% trans %}Email{% endtrans %}
+ + {{ admin }}
{% trans %}Actions{% endtrans %}{% trans %}Email{% endtrans %}{% trans %}Destination{% endtrans %}{% trans %}Comment{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
-   - - {{ alias }}{{ alias.destination|join(', ') or '-' }}{{ alias.comment or '' }}{{ alias.created_at }}{{ alias.updated_at or '' }}
{% trans %}Actions{% endtrans %}{% trans %}Email{% endtrans %}{% trans %}Destination{% endtrans %}{% trans %}Comment{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
+   + + {{ alias }}{{ alias.destination|join(', ') or '-' }}{{ alias.comment or '' }}{{ alias.created_at }}{{ alias.updated_at or '' }}
{% trans %}Actions{% endtrans %}{% trans %}Name{% endtrans %}{% trans %}Created{% endtrans %}
- - {{ alternative }}{{ alternative.created_at }}
{% trans %}Actions{% endtrans %}{% trans %}Name{% endtrans %}{% trans %}Created{% endtrans %}
+ + {{ alternative }}{{ alternative.created_at }}
{% trans %}Actions{% endtrans %}{% trans %}Manage{% endtrans %}{% trans %}Domain name{% endtrans %}{% trans %}Mailbox count{% endtrans %}{% trans %}Alias count{% endtrans %}{% trans %}Comment{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
-   - {% if current_user.global_admin %} -   -   - {% endif %} - -   -   -   - {% if current_user.global_admin %} -   - {% endif %} - {{ domain.name }}{{ domain.users | count }} / {{ '∞' if domain.max_users == -1 else domain.max_users }}{{ domain.aliases | count }} / {{ '∞' if domain.max_aliases == -1 else domain.max_aliases }}{{ domain.comment or '' }}{{ domain.created_at }}{{ domain.updated_at or '' }}
{% trans %}Actions{% endtrans %}{% trans %}Manage{% endtrans %}{% trans %}Domain name{% endtrans %}{% trans %}Mailbox count{% endtrans %}{% trans %}Alias count{% endtrans %}{% trans %}Comment{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
+   + {% if current_user.global_admin %} +   +   + {% endif %} + +   +   +   + {% if current_user.global_admin %} +   + {% endif %} + {{ domain.name }}{{ domain.users | count }} / {{ '∞' if domain.max_users == -1 else domain.max_users }}{{ domain.aliases | count }} / {{ '∞' if domain.max_aliases == -1 else domain.max_aliases }}{{ domain.comment or '' }}{{ domain.created_at }}{{ domain.updated_at or '' }}
{% trans %}Actions{% endtrans %}{% trans %}Endpoint{% endtrans %}{% trans %}Username{% endtrans %}{% trans %}Keep emails{% endtrans %}{% trans %}Last check{% endtrans %}{% trans %}Status{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
-   - - {{ fetch.protocol }}{{ 's' if fetch.tls else '' }}://{{ fetch.host }}:{{ fetch.port }}{{ fetch.username }}{% if fetch.keep %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %}{{ fetch.last_check or '-' }}{{ fetch.error or '-' }}{{ fetch.created_at }}{{ fetch.updated_at or '' }}
{% trans %}Actions{% endtrans %}{% trans %}Endpoint{% endtrans %}{% trans %}Username{% endtrans %}{% trans %}Keep emails{% endtrans %}{% trans %}Last check{% endtrans %}{% trans %}Status{% endtrans %}{% trans %}Created{% endtrans %}{% trans %}Last edit{% endtrans %}
+   + + {{ fetch.protocol }}{{ 's' if fetch.tls else '' }}://{{ fetch.host }}:{{ fetch.port }}{{ fetch.username }}{% if fetch.keep %}{% trans %}yes{% endtrans %}{% else %}{% trans %}no{% endtrans %}{% endif %}{{ fetch.last_check or '-' }}{{ fetch.error or '-' }}{{ fetch.created_at }}{{ fetch.updated_at or '' }}
- {{ caller() }} -
diff --git a/core/admin/mailu/ui/templates/manager/list.html b/core/admin/mailu/ui/templates/manager/list.html index b660bf6d..9a78e3ca 100644 --- a/core/admin/mailu/ui/templates/manager/list.html +++ b/core/admin/mailu/ui/templates/manager/list.html @@ -14,10 +14,13 @@ {% block content %} {% call macros.table() %} - - {% trans %}Actions{% endtrans %} - {% trans %}Email{% endtrans %} - + + + {% trans %}Actions{% endtrans %} + {% trans %}Email{% endtrans %} + + + {% for manager in domain.managers %} @@ -26,5 +29,6 @@ {{ manager }} {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/relay/list.html b/core/admin/mailu/ui/templates/relay/list.html index aef189ad..6c8c9196 100644 --- a/core/admin/mailu/ui/templates/relay/list.html +++ b/core/admin/mailu/ui/templates/relay/list.html @@ -12,26 +12,30 @@ {% block content %} {% call macros.table() %} - - {% trans %}Actions{% endtrans %} - {% trans %}Domain name{% endtrans %} - {% trans %}Remote host{% endtrans %} - {% trans %}Comment{% endtrans %} - {% trans %}Created{% endtrans %} - {% trans %}Last edit{% endtrans %} - -{% for relay in relays %} - - -  -   - - {{ relay.name }} - {{ relay.smtp or '-' }} - {{ relay.comment or '' }} - {{ relay.created_at }} - {{ relay.updated_at or '' }} - -{% endfor %} + + + {% trans %}Actions{% endtrans %} + {% trans %}Domain name{% endtrans %} + {% trans %}Remote host{% endtrans %} + {% trans %}Comment{% endtrans %} + {% trans %}Created{% endtrans %} + {% trans %}Last edit{% endtrans %} + + + + {% for relay in relays %} + + +   +   + + {{ relay.name }} + {{ relay.smtp or '-' }} + {{ relay.comment or '' }} + {{ relay.created_at }} + {{ relay.updated_at or '' }} + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/token/list.html b/core/admin/mailu/ui/templates/token/list.html index 99f67383..09d0fe76 100644 --- a/core/admin/mailu/ui/templates/token/list.html +++ b/core/admin/mailu/ui/templates/token/list.html @@ -14,21 +14,25 @@ {% block content %} {% call macros.table() %} - - {% trans %}Actions{% endtrans %} - {% trans %}Comment{% endtrans %} - {% trans %}Authorized IP{% endtrans %} - {% trans %}Created{% endtrans %} - -{% for token in user.tokens %} - - - - - {{ token.comment }} - {{ token.ip or "any" }} - {{ token.created_at }} - -{% endfor %} + + + {% trans %}Actions{% endtrans %} + {% trans %}Comment{% endtrans %} + {% trans %}Authorized IP{% endtrans %} + {% trans %}Created{% endtrans %} + + + + {% for token in user.tokens %} + + + + + {{ token.comment }} + {{ token.ip or "any" }} + {{ token.created_at }} + + {% endfor %} + {% endcall %} {% endblock %} diff --git a/core/admin/mailu/ui/templates/user/list.html b/core/admin/mailu/ui/templates/user/list.html index ab896ee6..3cc724c8 100644 --- a/core/admin/mailu/ui/templates/user/list.html +++ b/core/admin/mailu/ui/templates/user/list.html @@ -14,37 +14,41 @@ {% block content %} {% call macros.table() %} - - {% trans %}Actions{% endtrans %} - {% trans %}User settings{% endtrans %} - {% trans %}Email{% endtrans %} - {% trans %}Features{% endtrans %} - {% trans %}Quota{% endtrans %} - {% trans %}Comment{% endtrans %} - {% trans %}Created{% endtrans %} - {% trans %}Last edit{% endtrans %} - -{% for user in domain.users %} - - -   - - - -   -   -   - - {{ user }} - - {% if user.enable_imap %}imap{% endif %} - {% if user.enable_pop %}pop3{% endif %} - - {{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }} - {{ user.comment or '-' }} - {{ user.created_at }} - {{ user.updated_at or '' }} - -{% endfor %} + + + {% trans %}Actions{% endtrans %} + {% trans %}User settings{% endtrans %} + {% trans %}Email{% endtrans %} + {% trans %}Features{% endtrans %} + {% trans %}Quota{% endtrans %} + {% trans %}Comment{% endtrans %} + {% trans %}Created{% endtrans %} + {% trans %}Last edit{% endtrans %} + + + + {% for user in domain.users %} + + +   + + + +   +   +   + + {{ user }} + + {% if user.enable_imap %}imap{% endif %} + {% if user.enable_pop %}pop3{% endif %} + + {{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }} + {{ user.comment or '-' }} + {{ user.created_at }} + {{ user.updated_at or '' }} + + {% endfor %} + {% endcall %} {% endblock %} From 49d68fa6d10aef4b585ed30a5ea7e7ac08e7c869 Mon Sep 17 00:00:00 2001 From: DjVinnii Date: Thu, 1 Apr 2021 16:51:13 +0200 Subject: [PATCH 009/163] Fix horizontal scrollbar in sidebar --- core/admin/mailu/ui/templates/base.html | 2 +- core/admin/mailu/ui/templates/sidebar.html | 36 +++++++++++----------- 2 files changed, 19 insertions(+), 19 deletions(-) diff --git a/core/admin/mailu/ui/templates/base.html b/core/admin/mailu/ui/templates/base.html index c5b09159..568d0880 100644 --- a/core/admin/mailu/ui/templates/base.html +++ b/core/admin/mailu/ui/templates/base.html @@ -8,7 +8,7 @@ Mailu-Admin - {{ config["SITENAME"] }} - +
- + diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index 29d8dddd..3769a210 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -83,7 +83,7 @@ manage your email domains, users, etc.

- + diff --git a/setup/templates/steps/stack/02_services.html b/setup/templates/steps/stack/02_services.html index 3f5186b0..6fce0ae6 100644 --- a/setup/templates/steps/stack/02_services.html +++ b/setup/templates/steps/stack/02_services.html @@ -55,7 +55,7 @@ the security implications caused by such an increase of attack surface.

Fetchmail allows users to retrieve mail from an external mail-server via IMAP/POP3 and puts it in their inbox.

- + From b0fb9d822bed082ee6630baeaf8526ab75934ff4 Mon Sep 17 00:00:00 2001 From: Dimitri Huisman Date: Thu, 22 Jul 2021 14:44:30 +0000 Subject: [PATCH 050/163] Adapt requirements.txt to use pinned versions. --- setup/requirements.txt | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/setup/requirements.txt b/setup/requirements.txt index b6bf2120..f2eb2157 100644 --- a/setup/requirements.txt +++ b/setup/requirements.txt @@ -1,4 +1,4 @@ -flask -flask-bootstrap -redis -gunicorn +Flask==1.0.2 +Flask-Bootstrap==3.3.7.1 +gunicorn==19.9.0 +redis==3.2.1 From 67e00bb1e77fa3350610e855c1396952ea76ea21 Mon Sep 17 00:00:00 2001 From: Dimitri Huisman Date: Thu, 22 Jul 2021 14:56:30 +0000 Subject: [PATCH 051/163] Add changelog --- towncrier/newsfragments/1880.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1880.feature diff --git a/towncrier/newsfragments/1880.feature b/towncrier/newsfragments/1880.feature new file mode 100644 index 00000000..212dc906 --- /dev/null +++ b/towncrier/newsfragments/1880.feature @@ -0,0 +1 @@ +Update jquery used in setup. Set pinned versions in requirements.txt for setup. This is a security update. From 9d2629a04e7aaa8c9fc199dac8a6a0631a857fac Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sat, 24 Jul 2021 12:40:38 +0200 Subject: [PATCH 052/163] fix 1884: always lookup a FQDN --- core/postfix/start.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/core/postfix/start.py b/core/postfix/start.py index 701efec3..7a2b57a1 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -38,7 +38,11 @@ os.environ["ANTISPAM_MILTER_ADDRESS"] = system.get_host_address_from_environment os.environ["LMTP_ADDRESS"] = system.get_host_address_from_environment("LMTP", "imap:2525") os.environ["OUTCLEAN"] = os.environ["HOSTNAMES"].split(",")[0] try: - os.environ["OUTCLEAN_ADDRESS"] = system.resolve_hostname(os.environ["OUTCLEAN"]) + _to_lookup = os.environ["OUTCLEAN"] + # Ensure we lookup a FQDN: @see #1884 + if not _to_lookup.endswith('.'): + _to_lookup += '.' + os.environ["OUTCLEAN_ADDRESS"] = system.resolve_hostname(_to_lookup) except: os.environ["OUTCLEAN_ADDRESS"] = "10.10.10.10" From fa915d78624114201074b0bbe919cdb708cca568 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sat, 24 Jul 2021 14:39:40 +0200 Subject: [PATCH 053/163] Fix 1294 ensure podop's socket is owned by postfix --- core/postfix/start.py | 3 ++- towncrier/newsfragments/1294.bugfix | 1 + 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 towncrier/newsfragments/1294.bugfix diff --git a/core/postfix/start.py b/core/postfix/start.py index 701efec3..125404f6 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -8,12 +8,13 @@ import logging as log import sys from podop import run_server +from pwd import getpwnam from socrate import system, conf log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) def start_podop(): - os.setuid(100) + os.setuid(getpwnam('postfix').pw_uid) url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/postfix/" # TODO: Remove verbosity setting from Podop? run_server(0, "postfix", "/tmp/podop.socket", [ diff --git a/towncrier/newsfragments/1294.bugfix b/towncrier/newsfragments/1294.bugfix new file mode 100644 index 00000000..68bb7a8a --- /dev/null +++ b/towncrier/newsfragments/1294.bugfix @@ -0,0 +1 @@ +Ensure that the podop socket is always owned by the postfix user (wasn't the case when build using non-standard base images... typically for arm64) From 8235085848e1e8586a7455bf214bd240f06d549e Mon Sep 17 00:00:00 2001 From: networkException Date: Sat, 24 Jul 2021 15:25:59 +0200 Subject: [PATCH 054/163] Docs: Limit fail2ban matches to front container Previously fail2ban matched against all journal entries. This patch adds a tag to the logdriver and fail2ban filter documentation that limits the matches to entries from the front container --- docs/faq.rst | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/faq.rst b/docs/faq.rst index 5d975532..f38fdca2 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -497,6 +497,8 @@ follow these steps: logging: driver: journald + options: + tag: mailu-front 2. Add the /etc/fail2ban/filter.d/bad-auth.conf @@ -506,6 +508,7 @@ follow these steps: [Definition] failregex = .* client login failed: .+ client:\ ignoreregex = + journalmatch = CONTAINER_TAG=mailu-front 3. Add the /etc/fail2ban/jail.d/bad-auth.conf From 8d9f3214cc5663dc29f7dcf3a03bc373a51d010b Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sat, 24 Jul 2021 15:45:25 +0200 Subject: [PATCH 055/163] Use threads in gunicorn rather than processes This ensures that we share the auth-cache... will enable memory savings and may improve performances when a higher number of cores is available "smarter default" --- core/admin/start.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/core/admin/start.py b/core/admin/start.py index 2c925e01..0eff3bbe 100755 --- a/core/admin/start.py +++ b/core/admin/start.py @@ -19,7 +19,8 @@ if account is not None and domain is not None and password is not None: os.system("flask mailu admin %s %s '%s' --mode %s" % (account, domain, password, mode)) start_command="".join([ - "gunicorn -w 4 -b :80 ", + "gunicorn --threads ", str(os.cpu_count()), + " -b :80 ", "--access-logfile - " if (log.root.level<=log.INFO) else "", "--error-logfile - ", "--preload ", From ad1b036f2068f5fe70641e549df34cb0b9cc0b21 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sat, 24 Jul 2021 20:21:38 +0200 Subject: [PATCH 056/163] fix Email class --- core/admin/mailu/models.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index b5ba29c0..fc9fd623 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -371,8 +371,8 @@ class Email(object): @classmethod def __declare_last__(cls): # gets called after mappings are completed - sqlalchemy.event.listen(User.localpart, 'set', cls._update_localpart, propagate=True) - sqlalchemy.event.listen(User.domain_name, 'set', cls._update_domain_name, propagate=True) + sqlalchemy.event.listen(cls.localpart, 'set', cls._update_localpart, propagate=True) + sqlalchemy.event.listen(cls.domain_name, 'set', cls._update_domain_name, propagate=True) def sendmail(self, subject, body): """ send an email to the address """ From 54b46a13c6bc730d5d0faa27d5c540edae9b24d4 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Sun, 25 Jul 2021 15:51:13 +0200 Subject: [PATCH 057/163] save dkim key after creation --- core/admin/mailu/models.py | 2 +- core/admin/mailu/ui/views/domains.py | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index b5ba29c0..7a6eb308 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -272,7 +272,7 @@ class Domain(Base): return dkim.strip_key(dkim_key).decode('utf8') def generate_dkim_key(self): - """ generate and activate new DKIM key """ + """ generate new DKIM key """ self.dkim_key = dkim.gen_key() def has_email(self, localpart): diff --git a/core/admin/mailu/ui/views/domains.py b/core/admin/mailu/ui/views/domains.py index 719d3844..f394ce7d 100644 --- a/core/admin/mailu/ui/views/domains.py +++ b/core/admin/mailu/ui/views/domains.py @@ -74,6 +74,8 @@ def domain_details(domain_name): def domain_genkeys(domain_name): domain = models.Domain.query.get(domain_name) or flask.abort(404) domain.generate_dkim_key() + models.db.session.add(domain) + models.db.session.commit() return flask.redirect( flask.url_for(".domain_details", domain_name=domain_name)) From 6856c2c80f1291771a2faed5b72883e62028fcc6 Mon Sep 17 00:00:00 2001 From: Alexander Graf Date: Fri, 30 Jul 2021 22:26:20 +0200 Subject: [PATCH 058/163] treat localpart case insensitive again by lowercasing it where necessary --- core/admin/mailu/models.py | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index b5ba29c0..4fdf5afb 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -57,10 +57,9 @@ class IdnaEmail(db.TypeDecorator): def process_bind_param(self, value, dialect): """ encode unicode domain part of email address to punycode """ - localpart, domain_name = value.rsplit('@', 1) + localpart, domain_name = value.lower().rsplit('@', 1) if '@' in localpart: raise ValueError('email local part must not contain "@"') - domain_name = domain_name.lower() return f'{localpart}@{idna.encode(domain_name).decode("ascii")}' def process_result_value(self, value, dialect): @@ -277,6 +276,7 @@ class Domain(Base): def has_email(self, localpart): """ checks if localpart is configured for domain """ + localpart = localpart.lower() for email in chain(self.users, self.aliases): if email.localpart == localpart: return True @@ -355,8 +355,8 @@ class Email(object): @email.setter def email(self, value): """ setter for email - sets _email, localpart and domain_name at once """ - self.localpart, self.domain_name = value.rsplit('@', 1) - self._email = value + self._email = value.lower() + self.localpart, self.domain_name = self._email.rsplit('@', 1) @staticmethod def _update_localpart(target, value, *_): @@ -389,8 +389,7 @@ class Email(object): def resolve_domain(cls, email): """ resolves domain alternative to real domain """ localpart, domain_name = email.rsplit('@', 1) if '@' in email else (None, email) - alternative = Alternative.query.get(domain_name) - if alternative: + if alternative := Alternative.query.get(domain_name): domain_name = alternative.domain_name return (localpart, domain_name) @@ -401,12 +400,14 @@ class Email(object): localpart_stripped = None stripped_alias = None - if os.environ.get('RECIPIENT_DELIMITER') in localpart: - localpart_stripped = localpart.rsplit(os.environ.get('RECIPIENT_DELIMITER'), 1)[0] + delim = os.environ.get('RECIPIENT_DELIMITER') + if delim in localpart: + localpart_stripped = localpart.rsplit(delim, 1)[0] user = User.query.get(f'{localpart}@{domain_name}') if not user and localpart_stripped: user = User.query.get(f'{localpart_stripped}@{domain_name}') + if user: email = f'{localpart}@{domain_name}' @@ -416,15 +417,15 @@ class Email(object): destination.append(email) else: destination = [email] + return destination pure_alias = Alias.resolve(localpart, domain_name) - stripped_alias = Alias.resolve(localpart_stripped, domain_name) if pure_alias and not pure_alias.wildcard: return pure_alias.destination - if stripped_alias: + if stripped_alias := Alias.resolve(localpart_stripped, domain_name): return stripped_alias.destination if pure_alias: From 3471ebb2146c210212dc0a7a1d7ed62eb7242ebb Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 2 Aug 2021 19:18:42 +0200 Subject: [PATCH 059/163] Allow specific users to send email from any address --- core/admin/mailu/configuration.py | 1 + core/admin/mailu/internal/views/postfix.py | 5 ++++- docs/configuration.rst | 2 ++ towncrier/newsfragments/1096.feature | 1 + 4 files changed, 8 insertions(+), 1 deletion(-) create mode 100644 towncrier/newsfragments/1096.feature diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 3d1b4fb5..3dd874f3 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -32,6 +32,7 @@ DEFAULT_CONFIG = { 'DOMAIN': 'mailu.io', 'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io', 'POSTMASTER': 'postmaster', + 'WILDCARD_SENDERS': '', 'TLS_FLAVOR': 'cert', 'INBOUND_TLS_ENFORCE': False, 'AUTH_RATELIMIT': '10/minute;1000/hour', diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index c358c37f..d1b53856 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -133,10 +133,13 @@ def postfix_sender_map(sender): @internal.route("/postfix/sender/login/") def postfix_sender_login(sender): + has_wildcard_senders = bool(flask.current_app.config["WILDCARD_SENDERS"]) + wildcard_senders = flask.current_app.config["WILDCARD_SENDERS"].lower().split(',') if has_wildcard_senders else [] localpart, domain_name = models.Email.resolve_domain(sender) if localpart is None: - return flask.abort(404) + return flask.jsonify(",".join(wildcard_senders)) if has_wildcard_senders else flask.abort(404) destination = models.Email.resolve_destination(localpart, domain_name, True) + destination = [*destination, *wildcard_senders] if destination else [*wildcard_senders] return flask.jsonify(",".join(destination)) if destination else flask.abort(404) diff --git a/docs/configuration.rst b/docs/configuration.rst index 16ea23c3..34b14868 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -37,6 +37,8 @@ The ``POSTMASTER`` is the local part of the postmaster email address. It is recommended to setup a generic value and later configure a mail alias for that address. +The ``WILDCARD_SENDERS`` setting is a comma delimited list of user email addresses that are allowed to send emails from any address (spoofing the sender). + The ``AUTH_RATELIMIT`` holds a security setting for fighting attackers that try to guess user passwords. The value is the limit of failed authentication attempts that a single IP address can perform against IMAP, POP and SMTP authentication endpoints. diff --git a/towncrier/newsfragments/1096.feature b/towncrier/newsfragments/1096.feature new file mode 100644 index 00000000..f3abd3dc --- /dev/null +++ b/towncrier/newsfragments/1096.feature @@ -0,0 +1 @@ +Allow specific users to send emails from any address using the WILDCARD_SENDERS setting From f8362d04e4d46c44ab07beffb77cdd041af193c0 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 3 Aug 2021 13:44:56 +0200 Subject: [PATCH 060/163] Switch to openssl to workaround alpine #12763 --- core/admin/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 3153bd9e..a0d3d996 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -24,9 +24,9 @@ RUN mkdir -p /app WORKDIR /app COPY requirements-prod.txt requirements.txt -RUN apk add --no-cache libressl curl postgresql-libs mariadb-connector-c \ +RUN apk add --no-cache openssl curl postgresql-libs mariadb-connector-c \ && apk add --no-cache --virtual build-dep \ - libressl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev \ + openssl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev \ && pip3 install -r requirements.txt \ && apk del --no-cache build-dep From defea3258ddd3faa15563630b7a10625b5ffa4a6 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 3 Aug 2021 13:58:54 +0200 Subject: [PATCH 061/163] update arm builds too --- core/admin/Dockerfile | 2 +- webmails/rainloop/Dockerfile | 2 +- webmails/roundcube/Dockerfile | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index 0a3b8468..97cf1736 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -2,7 +2,7 @@ ARG DISTRO=alpine:3.14 ARG ARCH="" FROM ${ARCH}node:8 as assets -COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static +COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static COPY package.json ./ RUN npm install diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 9c65f277..9814413d 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -3,7 +3,7 @@ ARG QEMU=other # NOTE: only add file if building for arm FROM ${ARCH}php:7.4-apache as build_arm -ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static +ONBUILD COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static FROM ${ARCH}php:7.4-apache as build_other diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index fae02ce0..4d3e36df 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -2,7 +2,7 @@ ARG ARCH="" ARG QEMU=other FROM ${ARCH}php:7.4-apache as build_arm -ONBUILD COPY --from=balenalib/rpi-alpine:3.10 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static +ONBUILD COPY --from=balenalib/rpi-alpine:3.14 /usr/bin/qemu-arm-static /usr/bin/qemu-arm-static FROM ${ARCH}php:7.4-apache as build_other From ccb3631622e535c902d22c7ced649cd374d1ac97 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 3 Aug 2021 14:01:44 +0200 Subject: [PATCH 062/163] still need pip3 --- docs/Dockerfile | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 11f66b49..29234b19 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -6,7 +6,7 @@ COPY requirements.txt /requirements.txt ARG version=master ENV VERSION=$version -RUN apk add --no-cache nginx curl python3 \ +RUN apk add --no-cache nginx curl python3 py3-pip \ && pip3 install -r /requirements.txt \ && mkdir /run/nginx From 2b63280f59658ca05fd5fb3870126556d6c29004 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 3 Aug 2021 14:16:14 +0200 Subject: [PATCH 063/163] doh --- docs/Dockerfile | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 29234b19..253c8420 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,4 +1,4 @@ -ARG DISTRO=alpine:3.14 +ARG DISTRO=python:3.8-alpine3.14 FROM $DISTRO COPY requirements.txt /requirements.txt @@ -6,9 +6,8 @@ COPY requirements.txt /requirements.txt ARG version=master ENV VERSION=$version -RUN apk add --no-cache nginx curl python3 py3-pip \ - && pip3 install -r /requirements.txt \ - && mkdir /run/nginx +RUN apk add --no-cache nginx curl \ + && pip3 install -r /requirements.txt COPY ./nginx.conf /etc/nginx/conf.d/default.conf COPY . /docs From 609e0f9f7c5b60e5db498d3b3817b41e65c116c5 Mon Sep 17 00:00:00 2001 From: Dimitri Huisman <52963853+Diman0@users.noreply.github.com> Date: Thu, 5 Aug 2021 00:12:37 +0200 Subject: [PATCH 064/163] Env vars are not shared between jobs --- .github/workflows/CI.yml | 84 ++++++++++++++++++++++++++++++++++++++++ 1 file changed, 84 insertions(+) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 55595838..19a445b4 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -91,6 +91,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -124,6 +138,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -157,6 +185,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -190,6 +232,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -223,6 +279,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -256,6 +326,20 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images From 98933f9478aab9f8d04cb0afba5eeac2c4dee9ef Mon Sep 17 00:00:00 2001 From: Erriez Date: Thu, 5 Aug 2021 19:37:06 +0200 Subject: [PATCH 065/163] Optimize docs/Dockerfile - Convert .rst to .html in temporary python:3.8-alpine3.14 build image - Remove all unused packages - Use nginx:1.21-alpine deployment image --- docs/Dockerfile | 30 +++++++++++++++++++----------- 1 file changed, 19 insertions(+), 11 deletions(-) diff --git a/docs/Dockerfile b/docs/Dockerfile index 70c9c3c4..289697da 100644 --- a/docs/Dockerfile +++ b/docs/Dockerfile @@ -1,20 +1,28 @@ -ARG DISTRO=alpine:3.8 -FROM $DISTRO - -COPY requirements.txt /requirements.txt +# Convert .rst files to .html in temporary build container +FROM python:3.8-alpine3.14 AS build ARG version=master ENV VERSION=$version -RUN apk add --no-cache nginx curl python3 \ - && pip3 install -r /requirements.txt \ - && mkdir /run/nginx - -COPY ./nginx.conf /etc/nginx/conf.d/default.conf +COPY requirements.txt /requirements.txt COPY . /docs -RUN mkdir -p /build/$VERSION \ - && sphinx-build -W /docs /build/$VERSION +RUN apk add --no-cache --virtual .build-deps \ + gcc musl-dev \ + && pip3 install -r /requirements.txt \ + && mkdir -p /build/$VERSION \ + && sphinx-build -W /docs /build/$VERSION \ + && apk del .build-deps + + +# Build nginx deployment image including generated html +FROM nginx:1.21-alpine + +ARG version=master +ENV VERSION=$version + +COPY ./nginx.conf /etc/nginx/conf.d/default.conf +COPY --from=build /build/$VERSION /build/$VERSION EXPOSE 80/tcp From 588904078edd04ed08db309ceb7dd11e751c37b9 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Fri, 6 Aug 2021 16:27:07 +0200 Subject: [PATCH 066/163] Set default of AUTH_RATELIMIT_SUBNET to False. Increase default AUTH_RATELIMIT value. --- core/admin/mailu/configuration.py | 4 ++-- docs/configuration.rst | 2 +- setup/templates/steps/config.html | 2 +- towncrier/newsfragments/1867.feature | 1 + 4 files changed, 5 insertions(+), 4 deletions(-) create mode 100644 towncrier/newsfragments/1867.feature diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 3d1b4fb5..d2d34d88 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -34,8 +34,8 @@ DEFAULT_CONFIG = { 'POSTMASTER': 'postmaster', 'TLS_FLAVOR': 'cert', 'INBOUND_TLS_ENFORCE': False, - 'AUTH_RATELIMIT': '10/minute;1000/hour', - 'AUTH_RATELIMIT_SUBNET': True, + 'AUTH_RATELIMIT': '1000/minute;10000/hour', + 'AUTH_RATELIMIT_SUBNET': False, 'DISABLE_STATISTICS': False, # Mail settings 'DMARC_RUA': None, diff --git a/docs/configuration.rst b/docs/configuration.rst index 16ea23c3..d7ebfc11 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -41,7 +41,7 @@ The ``AUTH_RATELIMIT`` holds a security setting for fighting attackers that try to guess user passwords. The value is the limit of failed authentication attempts that a single IP address can perform against IMAP, POP and SMTP authentication endpoints. -If ``AUTH_RATELIMIT_SUBNET`` is ``True`` (which is the default), the ``AUTH_RATELIMIT`` +If ``AUTH_RATELIMIT_SUBNET`` is ``True`` (default: False), the ``AUTH_RATELIMIT`` rules does also apply to auth requests coming from ``SUBNET``, especially for the webmail. If you disable this, ensure that the rate limit on the webmail is enforced in a different way (e.g. roundcube plug-in), otherwise an attacker can simply bypass the limit using webmail. diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index 3769a210..fee66933 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -51,7 +51,7 @@ Or in plain english: if receivers start to classify your mail as spam, this post

/ minute + value="10000" required > / minute

diff --git a/towncrier/newsfragments/1867.feature b/towncrier/newsfragments/1867.feature new file mode 100644 index 00000000..fbd3a7d7 --- /dev/null +++ b/towncrier/newsfragments/1867.feature @@ -0,0 +1 @@ +Changed default value of AUTH_RATELIMIT_SUBNET to false. Increased default value of the rate limit in setup utility (AUTH_RATELIMIT) to a higher value. From 4cfa2dbc2addc1bab34f5402f1b52df2d89ec536 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Fri, 6 Aug 2021 16:44:18 +0200 Subject: [PATCH 067/163] Increase width of rate limiting text box. --- setup/templates/steps/config.html | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index fee66933..72b83915 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -50,7 +50,7 @@ Or in plain english: if receivers start to classify your mail as spam, this post
-

/ minute

From a7d99bdedd3decc7dc02609fc070337451302eb2 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Fri, 6 Aug 2021 22:35:37 +0200 Subject: [PATCH 068/163] Update CHANGELOG.md and process towncrier newsfragments. --- CHANGELOG.md | 32 +++++++++++++++++++++++++--- towncrier/newsfragments/1660.bugfix | 1 - towncrier/newsfragments/1686.bugfix | 1 - towncrier/newsfragments/1720.bugfix | 2 -- towncrier/newsfragments/1783.misc | 1 - towncrier/newsfragments/1837.bugfix | 1 - towncrier/newsfragments/1841.feature | 1 - towncrier/newsfragments/1845.feature | 1 - towncrier/newsfragments/1857.doc | 1 - towncrier/newsfragments/1861.bugfix | 1 - towncrier/newsfragments/1867.feature | 1 - towncrier/newsfragments/1874.bugfix | 1 - towncrier/newsfragments/1880.feature | 1 - towncrier/newsfragments/191.bugfix | 1 - 14 files changed, 29 insertions(+), 17 deletions(-) delete mode 100644 towncrier/newsfragments/1660.bugfix delete mode 100644 towncrier/newsfragments/1686.bugfix delete mode 100644 towncrier/newsfragments/1720.bugfix delete mode 100644 towncrier/newsfragments/1783.misc delete mode 100644 towncrier/newsfragments/1837.bugfix delete mode 100644 towncrier/newsfragments/1841.feature delete mode 100644 towncrier/newsfragments/1845.feature delete mode 100644 towncrier/newsfragments/1857.doc delete mode 100644 towncrier/newsfragments/1861.bugfix delete mode 100644 towncrier/newsfragments/1867.feature delete mode 100644 towncrier/newsfragments/1874.bugfix delete mode 100644 towncrier/newsfragments/1880.feature delete mode 100644 towncrier/newsfragments/191.bugfix diff --git a/CHANGELOG.md b/CHANGELOG.md index 579f3e82..09b9f68f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -4,18 +4,44 @@ Changelog Upgrade should run fine as long as you generate a new compose or stack configuration and upgrade your mailu.env. -Please note that the current 1.8 is what we call a "soft release": It’s there for everyone to see and use, but to limit possible user-impact of this very big release, it’s not yet the default in the setup-utility for new users. When upgrading, please treat it with some care, and be sure to always have backups! - There are some changes to the configuration overrides. Override files are now mounted read-only into the containers. The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from overrides/ to overrides/dovecot and overrides/postfix/. See https://mailu.io/1.8/faq.html#how-can-i-override-settings for all the mappings. +<<<<<<< HEAD Please note that the shipped image for PostgreSQL database is deprecated. We advise to switch to an external database server. +======= +One major change for the docker compose file is that the antispam needs a fixed hostname [#1837](https://github.com/Mailu/Mailu/issues/1837). +This is handled when you regenerate the docker-compose file. A fixed hostname is required to retain rspamd history. + +Please not that the shipped image for PostgreSQL database is deprecated. +We advise to switch to an external PostgreSQL database server. +>>>>>>> afaacf5a... Update CHANGELOG.md and process towncrier newsfragments. -v1.8.0 - 2020-09-28 +1.8.0 - 2021-08-06 +-------------------- + +- Features: Update version of roundcube webmail and carddav plugin. This is a security update. ([#1841](https://github.com/Mailu/Mailu/issues/1841)) +- Features: Update version of rainloop webmail to 1.16.0. This is a security update. ([#1845](https://github.com/Mailu/Mailu/issues/1845)) +- Features: Changed default value of AUTH_RATELIMIT_SUBNET to false. Increased default value of the rate limit in setup utility (AUTH_RATELIMIT) to a higher value. ([#1867](https://github.com/Mailu/Mailu/issues/1867)) +- Features: Update jquery used in setup. Set pinned versions in requirements.txt for setup. This is a security update. ([#1880](https://github.com/Mailu/Mailu/issues/1880)) +- Bugfixes: Replace PUBLIC_HOSTNAME and PUBLIC_IP in "Received" headers to ensure that no undue spam points are attributed ([#191](https://github.com/Mailu/Mailu/issues/191)) +- Bugfixes: Don't replace nested headers (typically in attached emails) ([#1660](https://github.com/Mailu/Mailu/issues/1660)) +- Bugfixes: Fix letsencrypt access to certbot for the mail-letsencrypt flavour ([#1686](https://github.com/Mailu/Mailu/issues/1686)) +- Bugfixes: Fix CVE-2020-25275 and CVE-2020-24386 by using alpine 3.13 for + dovecot which contains a fixed dovecot version. ([#1720](https://github.com/Mailu/Mailu/issues/1720)) +- Bugfixes: Antispam service now uses a static hostname. Rspamd history is only retained when the service has a fixed hostname. ([#1837](https://github.com/Mailu/Mailu/issues/1837)) +- Bugfixes: Fix a bug preventing colons from being used in passwords when using radicale/webdav. ([#1861](https://github.com/Mailu/Mailu/issues/1861)) +- Bugfixes: Remove dot in blueprint name to prevent critical flask startup error in setup. ([#1874](https://github.com/Mailu/Mailu/issues/1874)) +- Bugfixes: fix punycode encoding of domain names ([#1891](https://github.com/Mailu/Mailu/issues/1891)) +- Improved Documentation: Update fail2ban documentation to use systemd backend instead of filepath for journald ([#1857](https://github.com/Mailu/Mailu/issues/1857)) +- Misc: ([#1783](https://github.com/Mailu/Mailu/issues/1783)) + + +v1.8.0rc - 2020-09-28 -------------------- - Features: Add support for backward-forwarding using SRS ([#328](https://github.com/Mailu/Mailu/issues/328)) diff --git a/towncrier/newsfragments/1660.bugfix b/towncrier/newsfragments/1660.bugfix deleted file mode 100644 index a90fb099..00000000 --- a/towncrier/newsfragments/1660.bugfix +++ /dev/null @@ -1 +0,0 @@ -Don't replace nested headers (typically in attached emails) diff --git a/towncrier/newsfragments/1686.bugfix b/towncrier/newsfragments/1686.bugfix deleted file mode 100644 index 932d7d7c..00000000 --- a/towncrier/newsfragments/1686.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix letsencrypt access to certbot for the mail-letsencrypt flavour diff --git a/towncrier/newsfragments/1720.bugfix b/towncrier/newsfragments/1720.bugfix deleted file mode 100644 index 0bf2b8e6..00000000 --- a/towncrier/newsfragments/1720.bugfix +++ /dev/null @@ -1,2 +0,0 @@ -Fix CVE-2020-25275 and CVE-2020-24386 by using alpine 3.13 for -dovecot which contains a fixed dovecot version. diff --git a/towncrier/newsfragments/1783.misc b/towncrier/newsfragments/1783.misc deleted file mode 100644 index 2ee4c97f..00000000 --- a/towncrier/newsfragments/1783.misc +++ /dev/null @@ -1 +0,0 @@ -Switch from client side sessions (cookies) to server-side sessions (Redis). This simplies the security model a lot and allows for an easier recovery should a cookie ever land in the hands of an attacker. diff --git a/towncrier/newsfragments/1837.bugfix b/towncrier/newsfragments/1837.bugfix deleted file mode 100644 index dcabcc6b..00000000 --- a/towncrier/newsfragments/1837.bugfix +++ /dev/null @@ -1 +0,0 @@ -Antispam service now uses a static hostname. Rspamd history is only retained when the service has a fixed hostname. diff --git a/towncrier/newsfragments/1841.feature b/towncrier/newsfragments/1841.feature deleted file mode 100644 index c91f805f..00000000 --- a/towncrier/newsfragments/1841.feature +++ /dev/null @@ -1 +0,0 @@ -Update version of roundcube webmail and carddav plugin. This is a security update. \ No newline at end of file diff --git a/towncrier/newsfragments/1845.feature b/towncrier/newsfragments/1845.feature deleted file mode 100644 index afde9313..00000000 --- a/towncrier/newsfragments/1845.feature +++ /dev/null @@ -1 +0,0 @@ -Update version of rainloop webmail to 1.16.0. This is a security update. diff --git a/towncrier/newsfragments/1857.doc b/towncrier/newsfragments/1857.doc deleted file mode 100644 index 06cb91ab..00000000 --- a/towncrier/newsfragments/1857.doc +++ /dev/null @@ -1 +0,0 @@ -Update fail2ban documentation to use systemd backend instead of filepath for journald \ No newline at end of file diff --git a/towncrier/newsfragments/1861.bugfix b/towncrier/newsfragments/1861.bugfix deleted file mode 100644 index 1e28d1b6..00000000 --- a/towncrier/newsfragments/1861.bugfix +++ /dev/null @@ -1 +0,0 @@ -Fix a bug preventing colons from being used in passwords when using radicale/webdav. diff --git a/towncrier/newsfragments/1867.feature b/towncrier/newsfragments/1867.feature deleted file mode 100644 index fbd3a7d7..00000000 --- a/towncrier/newsfragments/1867.feature +++ /dev/null @@ -1 +0,0 @@ -Changed default value of AUTH_RATELIMIT_SUBNET to false. Increased default value of the rate limit in setup utility (AUTH_RATELIMIT) to a higher value. diff --git a/towncrier/newsfragments/1874.bugfix b/towncrier/newsfragments/1874.bugfix deleted file mode 100644 index a301835e..00000000 --- a/towncrier/newsfragments/1874.bugfix +++ /dev/null @@ -1 +0,0 @@ -Remove dot in blueprint name to prevent critical flask startup error in setup. diff --git a/towncrier/newsfragments/1880.feature b/towncrier/newsfragments/1880.feature deleted file mode 100644 index 212dc906..00000000 --- a/towncrier/newsfragments/1880.feature +++ /dev/null @@ -1 +0,0 @@ -Update jquery used in setup. Set pinned versions in requirements.txt for setup. This is a security update. diff --git a/towncrier/newsfragments/191.bugfix b/towncrier/newsfragments/191.bugfix deleted file mode 100644 index 185d3074..00000000 --- a/towncrier/newsfragments/191.bugfix +++ /dev/null @@ -1 +0,0 @@ -Replace PUBLIC_HOSTNAME and PUBLIC_IP in "Received" headers to ensure that no undue spam points are attributed From 4b89143362d9ef8cfb985c030047ce74642f7952 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Fri, 6 Aug 2021 23:00:27 +0200 Subject: [PATCH 069/163] Update documentation config and release notes page. --- docs/conf.py | 2 +- docs/releases.rst | 65 +++++++++++++++++++++++++++++++++++++++++++++-- 2 files changed, 64 insertions(+), 3 deletions(-) diff --git a/docs/conf.py b/docs/conf.py index 8f174b64..db7008b3 100644 --- a/docs/conf.py +++ b/docs/conf.py @@ -36,7 +36,7 @@ html_context = { 'github_user': 'mailu', 'github_repo': 'mailu', 'github_version': version, - 'stable_version': '1.7', + 'stable_version': '1.8', 'versions': [ ('1.5', '/1.5/'), ('1.6', '/1.6/'), diff --git a/docs/releases.rst b/docs/releases.rst index 7a15d1fa..7473b033 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -1,8 +1,69 @@ Release notes ============= -Mailu 1.8 - 2020-10-02 ----------------------- +Mailu 1.8 - 2021-08-7 +--------------------- + +The full 1.8 release is finally ready. There have been some changes in the contributors team. Many people from the contributors team have stepped back due to changed priorities in their life. +We are very grateful for all their contributions and hope we will see them back again in the future. +This is the main reason why it took so long for 1.8 to be fully released. + +Fortunately more people have decided to join the project. Some very nice contributions have been made which will become part of the next 1.9 release. +We hope that future Mailu releases will be released more quickly now we have more active contributors again. + +For a list of all changes refer to `CHANGELOG.md` in the root folder of the Mailu github project. Please read the 'Override location changes' section further on this page. It contains important information for the people who use the overrides folder. + +New Functionality & Improvements +```````````````````````````````` + +Here’s a short summary of new features: + +- Roundcube and Rainloop have been updated. +- All dependencies have been updated to the latest security update. +- Fail2ban documentation has been improved. +- Switch from client side (cookie) sessions to server side sessions. +- Full-text-search is back after having been disabled for a while due to nasty bugs. It can still be disabled via the mailu.env file. +- Tons of documentation improvements, especially geared towards new users. +- (Experimental) support for different architectures, such as ARM. +- Improvements around webmails, such as CardDAV, GPG and a new skin for an updated roundcube, and support for MySQL for it. Updated Rainloop, too. +- Improvements around relaying, such as AUTH LOGIN and non-standard port support. +- Update to alpine:3.14 as baseimage for most containers. +- Setup warns users about compose-IPv6 deployments which have caused open relays in the past. +- Improved handling of upper-vs-lowercase aliases and user-addresses. +- Improved rate-limiting system. +- Support for SRS. +- Japanese localisation is now available. + + +Upgrading +````````` + +Upgrade should run fine as long as you generate a new compose or stack +configuration and upgrade your mailu.env. + +Please not that the shipped image for PostgreSQL database is deprecated. +The shipped image for PostgreSQL is not maintained anymore from release 1.8. +We recommend switching to an external PostgreSQL image as soon as possible. + +Override location changes +^^^^^^^^^^^^^^^^^^^^^^^^^ + +If you have regenerated the Docker compose and environment files, there are some changes to the configuration overrides. +Override files are now mounted read-only into the containers. The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from ``overrides/`` to ``overrides/dovecot`` and ``overrides/postfix/``. + +Update your DNS SPF Records +^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +It has become known that the SPF DNS records generated by the admin interface are not completely standard compliant anymore. Please check the DNS records for your domains and compare them to what the new admin-interface instructs you to use. In most cases, this should be a simple copy-paste operation for you …. + +Fixed hostname for antispam service +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +For history to be retained in Rspamd, the antispam container requires a static hostname. When you re-generate your docker-compose.yml file (or helm-chart), this will be covered. + + +Mailu 1.8rc - 2020-10-02 +------------------------ Release 1.8 has come a long way again. Due to corona the project slowed down to a crawl. Fortunately new contributors have joined the team what enabled us to still release Mailu 1.8 this year. From 6581f8f087d62b841e9939ea3cf3814ea9e9a518 Mon Sep 17 00:00:00 2001 From: Dimitri Huisman <52963853+Diman0@users.noreply.github.com> Date: Fri, 6 Aug 2021 23:17:41 +0200 Subject: [PATCH 070/163] Resolve merge conflict --- CHANGELOG.md | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 09b9f68f..3ad0061b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -9,18 +9,14 @@ The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from overrides/ to overrides/dovecot and overrides/postfix/. See https://mailu.io/1.8/faq.html#how-can-i-override-settings for all the mappings. -<<<<<<< HEAD -Please note that the shipped image for PostgreSQL database is deprecated. -We advise to switch to an external database server. -======= -One major change for the docker compose file is that the antispam needs a fixed hostname [#1837](https://github.com/Mailu/Mailu/issues/1837). -This is handled when you regenerate the docker-compose file. A fixed hostname is required to retain rspamd history. +One major change for the docker compose file is that the antispam container needs a fixed hostname [#1837](https://github.com/Mailu/Mailu/issues/1837). +This is handled when you regenerate the docker-compose file. A fixed hostname is required to retain rspamd history. +This is also handled in the helm-chart repo. Please not that the shipped image for PostgreSQL database is deprecated. We advise to switch to an external PostgreSQL database server. ->>>>>>> afaacf5a... Update CHANGELOG.md and process towncrier newsfragments. - + 1.8.0 - 2021-08-06 -------------------- From f0997ed0fd5b3be5e8a6964bfd3197ced1aa5ef9 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Sat, 7 Aug 2021 09:12:43 +0200 Subject: [PATCH 071/163] Improved changelog entry --- CHANGELOG.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 3ad0061b..0a128163 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -27,7 +27,7 @@ We advise to switch to an external PostgreSQL database server. - Bugfixes: Replace PUBLIC_HOSTNAME and PUBLIC_IP in "Received" headers to ensure that no undue spam points are attributed ([#191](https://github.com/Mailu/Mailu/issues/191)) - Bugfixes: Don't replace nested headers (typically in attached emails) ([#1660](https://github.com/Mailu/Mailu/issues/1660)) - Bugfixes: Fix letsencrypt access to certbot for the mail-letsencrypt flavour ([#1686](https://github.com/Mailu/Mailu/issues/1686)) -- Bugfixes: Fix CVE-2020-25275 and CVE-2020-24386 by using alpine 3.13 for +- Bugfixes: Fix CVE-2020-25275 and CVE-2020-24386 by upgrading alpine for dovecot which contains a fixed dovecot version. ([#1720](https://github.com/Mailu/Mailu/issues/1720)) - Bugfixes: Antispam service now uses a static hostname. Rspamd history is only retained when the service has a fixed hostname. ([#1837](https://github.com/Mailu/Mailu/issues/1837)) - Bugfixes: Fix a bug preventing colons from being used in passwords when using radicale/webdav. ([#1861](https://github.com/Mailu/Mailu/issues/1861)) From 21e7a338e75437afd59ae4185c87f59d18f8f4e9 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Sat, 7 Aug 2021 09:14:09 +0200 Subject: [PATCH 072/163] Fixed typing error. --- CHANGELOG.md | 2 +- docs/releases.rst | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 0a128163..82f04acc 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,7 +13,7 @@ One major change for the docker compose file is that the antispam container need This is handled when you regenerate the docker-compose file. A fixed hostname is required to retain rspamd history. This is also handled in the helm-chart repo. -Please not that the shipped image for PostgreSQL database is deprecated. +Please note that the shipped image for PostgreSQL database is deprecated. We advise to switch to an external PostgreSQL database server. diff --git a/docs/releases.rst b/docs/releases.rst index 7473b033..3ae25f48 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -41,7 +41,7 @@ Upgrading Upgrade should run fine as long as you generate a new compose or stack configuration and upgrade your mailu.env. -Please not that the shipped image for PostgreSQL database is deprecated. +Please note that the shipped image for PostgreSQL database is deprecated. The shipped image for PostgreSQL is not maintained anymore from release 1.8. We recommend switching to an external PostgreSQL image as soon as possible. From 14a18715111e4d21fd9cac0c7e18a293771f3fd0 Mon Sep 17 00:00:00 2001 From: Diman0 Date: Sat, 7 Aug 2021 09:25:40 +0200 Subject: [PATCH 073/163] enhanced security changelog entry and added recommendation to recreate secret_key --- CHANGELOG.md | 11 ++++++++++- docs/releases.rst | 14 +++++++++++++- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 82f04acc..da945c72 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -13,6 +13,15 @@ One major change for the docker compose file is that the antispam container need This is handled when you regenerate the docker-compose file. A fixed hostname is required to retain rspamd history. This is also handled in the helm-chart repo. +Improvements have been made to protect again session-fixation attacks. +To be fully protected, it is required to change your SECRET_KEY in Mailu.env after upgrading. +A new SECRET_KEY is generated when you recreate your docker-compose.yml & mailu.env file via setup.mailu.io. + +The SECRET_KEY is an uppercase alphanumeric string of length 16. You can manually create such a string via +```cat /dev/urandom | tr -dc 'A-Z0-9' | fold -w ${1:-16} | head -n 1``` + +After changing mailu.env, it is required to recreate all containers for the changes to be propagated. + Please note that the shipped image for PostgreSQL database is deprecated. We advise to switch to an external PostgreSQL database server. @@ -34,7 +43,7 @@ We advise to switch to an external PostgreSQL database server. - Bugfixes: Remove dot in blueprint name to prevent critical flask startup error in setup. ([#1874](https://github.com/Mailu/Mailu/issues/1874)) - Bugfixes: fix punycode encoding of domain names ([#1891](https://github.com/Mailu/Mailu/issues/1891)) - Improved Documentation: Update fail2ban documentation to use systemd backend instead of filepath for journald ([#1857](https://github.com/Mailu/Mailu/issues/1857)) -- Misc: ([#1783](https://github.com/Mailu/Mailu/issues/1783)) +- Misc: Switch from client side (cookie) sessions to server side sessions and protect against session-fixation attacks. We recommend that you change your SECRET_KEY after upgrading. ([#1783](https://github.com/Mailu/Mailu/issues/1783)) v1.8.0rc - 2020-09-28 diff --git a/docs/releases.rst b/docs/releases.rst index 3ae25f48..6c672538 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -21,7 +21,7 @@ Here’s a short summary of new features: - Roundcube and Rainloop have been updated. - All dependencies have been updated to the latest security update. - Fail2ban documentation has been improved. -- Switch from client side (cookie) sessions to server side sessions. +- Switch from client side (cookie) sessions to server side sessions and protect against session-fixation attacks. We recommend that you change your SECRET_KEY after upgrading. - Full-text-search is back after having been disabled for a while due to nasty bugs. It can still be disabled via the mailu.env file. - Tons of documentation improvements, especially geared towards new users. - (Experimental) support for different architectures, such as ARM. @@ -51,6 +51,18 @@ Override location changes If you have regenerated the Docker compose and environment files, there are some changes to the configuration overrides. Override files are now mounted read-only into the containers. The Dovecot and Postfix overrides are moved in their own sub-directory. If there are local override files, they will need to be moved from ``overrides/`` to ``overrides/dovecot`` and ``overrides/postfix/``. +Recreate SECRET_KEY after upgrading +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +Improvements have been made to protect again session-fixation attacks. +To be fully protected, it is required to change your SECRET_KEY in Mailu.env after upgrading. +A new SECRET_KEY is generated when you recreate your docker-compose.yml & mailu.env file via setup.mailu.io. + +The SECRET_KEY is an uppercase alphanumeric string of length 16. You can manually create such a string via +```cat /dev/urandom | tr -dc 'A-Z0-9' | fold -w ${1:-16} | head -n 1``` + +After changing mailu.env, it is required to recreate all containers for the changes to be propagated. + Update your DNS SPF Records ^^^^^^^^^^^^^^^^^^^^^^^^^^^ From 3157fc3623424f7af991f2de86981c2aeced4cca Mon Sep 17 00:00:00 2001 From: Diman0 Date: Sat, 7 Aug 2021 09:27:47 +0200 Subject: [PATCH 074/163] Give docker containers in each test one more minute for starting. --- .github/workflows/CI.yml | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 19a445b4..e2a535dd 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -121,7 +121,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test core suite - run: python tests/compose/test.py core 1 + run: python tests/compose/test.py core 2 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} @@ -168,7 +168,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test fetch - run: python tests/compose/test.py fetchmail 1 + run: python tests/compose/test.py fetchmail 2 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} @@ -215,7 +215,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test clamvav - run: python tests/compose/test.py filters 2 + run: python tests/compose/test.py filters 3 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} @@ -262,7 +262,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test rainloop - run: python tests/compose/test.py rainloop 1 + run: python tests/compose/test.py rainloop 2 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} @@ -309,7 +309,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test roundcube - run: python tests/compose/test.py roundcube 1 + run: python tests/compose/test.py roundcube 2 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} @@ -356,7 +356,7 @@ jobs: - name: Copy all certs run: sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' - name: Test webdav - run: python tests/compose/test.py webdav 1 + run: python tests/compose/test.py webdav 2 env: MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} From 1438253a069da3b10831ef89dc119177f16f5216 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 8 Aug 2021 09:21:14 +0200 Subject: [PATCH 075/163] Ratelimit outgoing emails per user --- core/admin/mailu/configuration.py | 1 + core/admin/mailu/internal/views/postfix.py | 10 ++++++++-- core/admin/mailu/models.py | 8 +++++++- core/admin/mailu/ui/templates/user/list.html | 5 ++++- core/postfix/conf/main.cf | 1 + core/postfix/start.py | 3 ++- setup/flavors/compose/mailu.env | 5 +++++ setup/templates/steps/config.html | 7 +++++++ towncrier/newsfragments/1031.feature | 1 + 9 files changed, 36 insertions(+), 5 deletions(-) create mode 100644 towncrier/newsfragments/1031.feature diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index d2d34d88..50733d52 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -46,6 +46,7 @@ DEFAULT_CONFIG = { 'DKIM_SELECTOR': 'dkim', 'DKIM_PATH': '/dkim/{domain}.{selector}.key', 'DEFAULT_QUOTA': 1000000000, + 'MESSAGE_RATELIMIT': '100/hour', # Web settings 'SITENAME': 'Mailu', 'WEBSITE': 'https://mailu.io', diff --git a/core/admin/mailu/internal/views/postfix.py b/core/admin/mailu/internal/views/postfix.py index c358c37f..06918c61 100644 --- a/core/admin/mailu/internal/views/postfix.py +++ b/core/admin/mailu/internal/views/postfix.py @@ -1,5 +1,6 @@ -from mailu import models +from mailu import models, utils from mailu.internal import internal +from flask import current_app as app import flask import idna @@ -31,7 +32,6 @@ def postfix_alias_map(alias): destination = models.Email.resolve_destination(localpart, domain_name) return flask.jsonify(",".join(destination)) if destination else flask.abort(404) - @internal.route("/postfix/transport/") def postfix_transport(email): if email == '*' or re.match("(^|.*@)\[.*\]$", email): @@ -139,6 +139,12 @@ def postfix_sender_login(sender): destination = models.Email.resolve_destination(localpart, domain_name, True) return flask.jsonify(",".join(destination)) if destination else flask.abort(404) +@internal.route("/postfix/sender/rate/") +def postfix_sender_rate(sender): + """ Rate limit outbound emails per sender login + """ + user = models.User.get(sender) or flask.abort(404) + return flask.abort(404) if user.sender_limiter.hit() else flask.jsonify("REJECT") @internal.route("/postfix/sender/access/") def postfix_sender_access(sender): diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 3a299786..5760c27f 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -27,7 +27,7 @@ from sqlalchemy.ext.hybrid import hybrid_property from sqlalchemy.inspection import inspect from werkzeug.utils import cached_property -from mailu import dkim +from mailu import dkim, utils db = flask_sqlalchemy.SQLAlchemy() @@ -501,6 +501,12 @@ class User(Base, Email): self.reply_enddate > now ) + @property + def sender_limiter(self): + return utils.limiter.get_limiter( + app.config["MESSAGE_RATELIMIT"], "sender", self.email + ) + @classmethod def get_password_context(cls): """ create password context for hashing and verification diff --git a/core/admin/mailu/ui/templates/user/list.html b/core/admin/mailu/ui/templates/user/list.html index 2aff662f..746afd45 100644 --- a/core/admin/mailu/ui/templates/user/list.html +++ b/core/admin/mailu/ui/templates/user/list.html @@ -19,7 +19,8 @@ {% trans %}User settings{% endtrans %} {% trans %}Email{% endtrans %} {% trans %}Features{% endtrans %} - {% trans %}Quota{% endtrans %} + {% trans %}Storage Quota{% endtrans %} + {% trans %}Sending Quota{% endtrans %} {% trans %}Comment{% endtrans %} {% trans %}Created{% endtrans %} {% trans %}Last edit{% endtrans %} @@ -41,6 +42,8 @@ {% if user.enable_pop %}pop3{% endif %} {{ user.quota_bytes_used | filesizeformat }} / {{ (user.quota_bytes | filesizeformat) if user.quota_bytes else '∞' }} + {% set limiter = user.sender_limiter %} + {{ limiter.get_window_stats()[1] }} / {{ limiter.limit }} {{ user.comment or '-' }} {{ user.created_at }} {{ user.updated_at or '' }} diff --git a/core/postfix/conf/main.cf b/core/postfix/conf/main.cf index 8f35f609..6f5a20b8 100644 --- a/core/postfix/conf/main.cf +++ b/core/postfix/conf/main.cf @@ -100,6 +100,7 @@ smtpd_sender_login_maps = ${podop}senderlogin smtpd_helo_required = yes smtpd_client_restrictions = + check_sasl_access ${podop}senderrate, permit_mynetworks, check_sender_access ${podop}senderaccess, reject_non_fqdn_sender, diff --git a/core/postfix/start.py b/core/postfix/start.py index e0c781b7..139616b2 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -25,7 +25,8 @@ def start_podop(): ("recipientmap", "url", url + "recipient/map/§"), ("sendermap", "url", url + "sender/map/§"), ("senderaccess", "url", url + "sender/access/§"), - ("senderlogin", "url", url + "sender/login/§") + ("senderlogin", "url", url + "sender/login/§"), + ("senderrate", "url", url + "sender/rate/§") ]) def is_valid_postconf_line(line): diff --git a/setup/flavors/compose/mailu.env b/setup/flavors/compose/mailu.env index d45f5517..52f4ee04 100644 --- a/setup/flavors/compose/mailu.env +++ b/setup/flavors/compose/mailu.env @@ -62,6 +62,11 @@ ANTIVIRUS={{ antivirus_enabled or 'none' }} # Max attachment size will be 33% smaller MESSAGE_SIZE_LIMIT={{ message_size_limit or '50000000' }} +# Message rate limit (per user) +{% if message_ratelimit_pd > '0' %} +MESSAGE_RATELIMIT={{ message_ratelimit_pd }}/day +{% endif %} + # Networks granted relay permissions # Use this with care, all hosts in this networks will be able to send mail without authentication! RELAYNETS= diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index 72b83915..87410fca 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -55,6 +55,13 @@ Or in plain english: if receivers start to classify your mail as spam, this post

+
+ + +

/ day +

+
+