From 02cfe326d3226f8dfffeda445c3de736b64288d7 Mon Sep 17 00:00:00 2001 From: lub Date: Sun, 30 Aug 2020 01:04:36 +0200 Subject: [PATCH 01/74] support using files for SECRET_KEY and DB_PW this enables usage of e.g. docker swarm secrets instead of exposing the passwords directly via environment variables just use DB_PW_FILE and SECRET_KEY_FILE instead of DB_PW and SECRET_KEY --- core/admin/mailu/configuration.py | 11 ++++++++++- webmails/roundcube/config.inc.php | 2 +- 2 files changed, 11 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 66b0b832..eacf7803 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -100,6 +100,15 @@ class ConfigManager(dict): if self.config["WEBMAIL"] != "none": self.config["WEBMAIL_ADDRESS"] = self.get_host_address("WEBMAIL") + def __get_env(self, key, value): + key_file = key + "_FILE" + if key_file in os.environ: + with open(os.environ.get(key_file)) as file: + value_from_file = file.read() + return value_from_file.strip() + else: + return os.environ.get(key, value) + def __coerce_value(self, value): if isinstance(value, str) and value.lower() in ('true','yes'): return True @@ -111,7 +120,7 @@ class ConfigManager(dict): self.config.update(app.config) # get environment variables self.config.update({ - key: self.__coerce_value(os.environ.get(key, value)) + key: self.__coerce_value(self.__get_env(key, value)) for key, value in DEFAULT_CONFIG.items() }) self.resolve_hosts() diff --git a/webmails/roundcube/config.inc.php b/webmails/roundcube/config.inc.php index eb40047a..627b96a7 100644 --- a/webmails/roundcube/config.inc.php +++ b/webmails/roundcube/config.inc.php @@ -5,7 +5,7 @@ $config = array(); // Generals $config['db_dsnw'] = getenv('DB_DSNW');; $config['temp_dir'] = '/tmp/'; -$config['des_key'] = getenv('SECRET_KEY'); +$config['des_key'] = getenv('SECRET_KEY') ? getenv('SECRET_KEY') : trim(file_get_contents(getenv('SECRET_KEY_FILE'))); $config['cipher_method'] = 'AES-256-CBC'; $config['identities_level'] = 0; $config['reply_all_mode'] = 1; From 426355f6b861058a1f489f791f23c2ab44d6ed60 Mon Sep 17 00:00:00 2001 From: lub Date: Sun, 30 Aug 2020 01:14:47 +0200 Subject: [PATCH 02/74] add some docs about _FILE variables --- docs/swarm/master/README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/docs/swarm/master/README.md b/docs/swarm/master/README.md index 58723c33..42e742da 100644 --- a/docs/swarm/master/README.md +++ b/docs/swarm/master/README.md @@ -106,6 +106,9 @@ As a side effect of this ingress mode "feature", make sure that the ingress subn - front and webmail are scalable (pending POD_ADDRESS_RANGE is used), although the let's encrypt magic might not like it (race condidtion ? or risk to be banned by let's encrypt server if too many front containers attemps to renew the certs at the same time) - redis, antispam, antivirus, fetchmail, admin, webdav have not been tested (hence replicas=1 in the following docker-compose.yml file) +## Docker secrets +There are DB_PW_FILE and SECRET_KEY_FILE environment variables available to specify files for these variables. These can be used to configure Docker secrets instead of writing the values directly into the `docker-compose.yml` or `mailu.env`. + ## Variable substitution and docker-compose.yml The docker stack deploy command doesn't support variable substitution in the .yml file itself. As a consequence, we cannot simply use ``` docker stack deploy -c docker.compose.yml mailu ``` From 714fa044e08288d14ba02b016b5aca2114e68faa Mon Sep 17 00:00:00 2001 From: lub Date: Sun, 30 Aug 2020 01:19:42 +0200 Subject: [PATCH 03/74] add towncrier for #1607 --- towncrier/newsfragments/1607.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1607.feature diff --git a/towncrier/newsfragments/1607.feature b/towncrier/newsfragments/1607.feature new file mode 100644 index 00000000..de9f0895 --- /dev/null +++ b/towncrier/newsfragments/1607.feature @@ -0,0 +1 @@ +Implement SECRET_KEY_FILE and DB_PW_FILE variables for usage with Docker secrets. From f0f873ffe7f176d480dc9a80cb68242f1fe8a69d Mon Sep 17 00:00:00 2001 From: lub Date: Tue, 1 Sep 2020 21:48:09 +0200 Subject: [PATCH 04/74] add option to enforce inbound starttls --- core/admin/mailu/configuration.py | 1 + core/admin/mailu/internal/nginx.py | 30 ++++++++++++++++++++++++------ docs/configuration.rst | 7 +++++++ 3 files changed, 32 insertions(+), 6 deletions(-) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 66b0b832..7fcd1ee7 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -31,6 +31,7 @@ DEFAULT_CONFIG = { 'HOSTNAMES': 'mail.mailu.io,alternative.mailu.io,yetanother.mailu.io', 'POSTMASTER': 'postmaster', 'TLS_FLAVOR': 'cert', + 'INBOUND_TLS_ENFORCE': False, 'AUTH_RATELIMIT': '10/minute;1000/hour', 'AUTH_RATELIMIT_SUBNET': True, 'DISABLE_STATISTICS': False, diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index fa127584..a7771f91 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -17,6 +17,9 @@ STATUSES = { "smtp": "535 5.7.8", "pop3": "-ERR Authentication failed" }), + "encryption": ("Must issue a STARTTLS command first", { + "smtp": "530 5.7.0" + }), } @@ -28,12 +31,27 @@ def handle_authentication(headers): protocol = headers["Auth-Protocol"] # Incoming mail, no authentication if method == "none" and protocol == "smtp": - server, port = get_server(headers["Auth-Protocol"], False) - return { - "Auth-Status": "OK", - "Auth-Server": server, - "Auth-Port": port - } + server, port = get_server(protocol, False) + if app.config["INBOUND_TLS_ENFORCE"]: + if "Auth-SSl" in headers and headers["Auth-SSL"] == "on": + return { + "Auth-Status": "OK", + "Auth-Server": server, + "Auth-Port": port + } + else: + status, code = get_status(protocol, "encryption") + return { + "Auth-Status": status, + "Auth-Error-Code" : code, + "Auth-Wait": 0 + } + else: + return { + "Auth-Status": "OK", + "Auth-Server": server, + "Auth-Port": port + } # Authenticated user elif method == "plain": server, port = get_server(headers["Auth-Protocol"], True) diff --git a/docs/configuration.rst b/docs/configuration.rst index 4b211925..3438b7fe 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -73,6 +73,13 @@ By default postfix uses "opportunistic TLS" for outbound mail. This can be chang by setting ``OUTBOUND_TLS_LEVEL`` to ``encrypt``. This setting is highly recommended if you are a relayhost that supports TLS. +Similarily by default nginx uses "opportunistic TLS" for inbound mail. This can be changed +by setting ``INBOUND_TLS_ENFORCE`` to ``True``. Please note that this is forbidden for +internet facing hosts according to e.g. `RFC 3207`_ , because this prevents MTAs without STARTTLS +support or e.g. mismatching TLS versions to deliver emails to Mailu. + +.. _`RFC 3207`: https://tools.ietf.org/html/rfc3207 + The ``FETCHMAIL_DELAY`` is a delay (in seconds) for the fetchmail service to go and fetch new email if available. Do not use too short delays if you do not want to be blacklisted by external services, but not too long delays if you From d348477efc933e5f2d1fa85c027b7d7fb2ccf623 Mon Sep 17 00:00:00 2001 From: lub Date: Tue, 1 Sep 2020 21:50:21 +0200 Subject: [PATCH 05/74] add towncrier for 1610 --- towncrier/newsfragments/1610.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1610.feature diff --git a/towncrier/newsfragments/1610.feature b/towncrier/newsfragments/1610.feature new file mode 100644 index 00000000..b56ac332 --- /dev/null +++ b/towncrier/newsfragments/1610.feature @@ -0,0 +1 @@ +Add possibility to enforce inbound STARTTLS via INBOUND_TLS_LEVEL=true From 05e2af180256b6a9387cd437d023c8d3f968a651 Mon Sep 17 00:00:00 2001 From: lub Date: Wed, 2 Sep 2020 15:16:10 +0200 Subject: [PATCH 06/74] fix small typo in Auth-SSL --- core/admin/mailu/internal/nginx.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index a7771f91..e1f8cb7a 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -33,7 +33,7 @@ def handle_authentication(headers): if method == "none" and protocol == "smtp": server, port = get_server(protocol, False) if app.config["INBOUND_TLS_ENFORCE"]: - if "Auth-SSl" in headers and headers["Auth-SSL"] == "on": + if "Auth-SSL" in headers and headers["Auth-SSL"] == "on": return { "Auth-Status": "OK", "Auth-Server": server, From 66db1f8fd075a0160915814b2a9d945f123efcf4 Mon Sep 17 00:00:00 2001 From: lub Date: Sat, 12 Sep 2020 01:32:03 +0200 Subject: [PATCH 07/74] add OCSP stapling to nginx.conf It's not added in tls.conf, because apparently the mail ssl module doesnt' support OCSP stapling. https://nginx.org/en/docs/http/ngx_http_ssl_module.html#ssl_stapling ^ exists https://nginx.org/en/docs/mail/ngx_mail_ssl_module.html#ssl_stapling ^ missing When the configured certificate doesn't have OCSP information, it'll just log a warning during startup. --- core/nginx/conf/nginx.conf | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index 46db324f..bea822a5 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -58,6 +58,8 @@ http { listen [::]:443 ssl http2; include /etc/nginx/tls.conf; + ssl_stapling on; + ssl_stapling_verify on; ssl_session_cache shared:SSLHTTP:50m; add_header Strict-Transport-Security 'max-age=31536000'; From e8b67470800f7b9c0a808b9d0f71b5bd034e892f Mon Sep 17 00:00:00 2001 From: lub Date: Sat, 12 Sep 2020 01:38:37 +0200 Subject: [PATCH 08/74] add newsfragemnt for #1618 --- towncrier/newsfragments/1618.feature | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1618.feature diff --git a/towncrier/newsfragments/1618.feature b/towncrier/newsfragments/1618.feature new file mode 100644 index 00000000..443f2b5c --- /dev/null +++ b/towncrier/newsfragments/1618.feature @@ -0,0 +1 @@ +Enable OCSP stapling for the http server within nginx. From 59bc4f7aea9da3f3ccf9ceca9a07af825de9e4af Mon Sep 17 00:00:00 2001 From: anrc <15327800+githtz@users.noreply.github.com> Date: Thu, 24 Sep 2020 13:16:25 +0200 Subject: [PATCH 09/74] Remove the username from the milter_headers Rspamd adds the name of the authenticated user by default. Setting add_smtp_user to false prevents the login to be leaked. --- core/rspamd/conf/milter_headers.conf | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/rspamd/conf/milter_headers.conf b/core/rspamd/conf/milter_headers.conf index cb680cfa..7da200df 100644 --- a/core/rspamd/conf/milter_headers.conf +++ b/core/rspamd/conf/milter_headers.conf @@ -5,6 +5,9 @@ skip_authenticated = false; use = ["x-spamd-bar", "x-spam-level", "x-virus", "authentication-results"]; routines { + authentication-results { + add_smtp_user = false; + } x-virus { symbols = ["CLAM_VIRUS", "FPROT_VIRUS", "JUST_EICAR"]; } From 3f037e2f08acdf078064e4e03fc1c2b46551b27a Mon Sep 17 00:00:00 2001 From: anrc <15327800+githtz@users.noreply.github.com> Date: Thu, 24 Sep 2020 16:53:42 +0200 Subject: [PATCH 10/74] Add changelog --- towncrier/newsfragments/1638.fix | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1638.fix diff --git a/towncrier/newsfragments/1638.fix b/towncrier/newsfragments/1638.fix new file mode 100644 index 00000000..9a87e41e --- /dev/null +++ b/towncrier/newsfragments/1638.fix @@ -0,0 +1 @@ +Hide the login of the user in sent emails From d63ca857b415036dcd7e72ff2ea26cc8993f27ea Mon Sep 17 00:00:00 2001 From: lub Date: Sat, 21 Nov 2020 00:55:28 +0100 Subject: [PATCH 11/74] update rainloop to php 7.4 --- webmails/rainloop/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index c67c7496..ee040f25 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -2,10 +2,10 @@ ARG ARCH="" ARG QEMU=other # NOTE: only add file if building for arm -FROM ${ARCH}php:7.3-apache as build_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 -FROM ${ARCH}php:7.3-apache as build_other +FROM ${ARCH}php:7.4-apache as build_other FROM build_${QEMU} #Shared layer between rainloop and roundcube From 8dd5dac3ed6adecdd129aef42680ce3a04cd7413 Mon Sep 17 00:00:00 2001 From: lub Date: Sat, 21 Nov 2020 00:55:38 +0100 Subject: [PATCH 12/74] update roundcube to php 7.4 --- webmails/roundcube/Dockerfile | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/webmails/roundcube/Dockerfile b/webmails/roundcube/Dockerfile index 79b911b0..1c303342 100644 --- a/webmails/roundcube/Dockerfile +++ b/webmails/roundcube/Dockerfile @@ -1,10 +1,10 @@ # NOTE: only add file if building for arm ARG ARCH="" ARG QEMU=other -FROM ${ARCH}php:7.3-apache as build_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 -FROM ${ARCH}php:7.3-apache as build_other +FROM ${ARCH}php:7.4-apache as build_other FROM build_${QEMU} #Shared layer between rainloop and roundcube From 0b14fefb1acef5b7f8dccce56a1f94c8ad3854e3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tomasz=20W=C3=B3jcik?= Date: Mon, 21 Dec 2020 00:19:27 +0100 Subject: [PATCH 13/74] fix typo in faq.rst --- docs/faq.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/faq.rst b/docs/faq.rst index b292cd05..4037800a 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -129,7 +129,7 @@ So when you have something like this: - The admin interface generates ``MX`` and ``SPF`` examples which point to the first entry of ``HOSTNAMES`` but these are only examples. You can modify them to use any other ``HOSTNAMES`` entry. -You're mail service will be reachable for IMAP, POP3, SMTP and Webmail at the addresses: +Your mail service will be reachable for IMAP, POP3, SMTP and Webmail at the addresses: - mail.example.com - mail.foo.com From bee0261dd8dd802e79ade31bc9e3a98f8c8a55b9 Mon Sep 17 00:00:00 2001 From: Stephan Holl Date: Wed, 23 Dec 2020 18:48:11 +0100 Subject: [PATCH 14/74] Add details for postfix-overrides --- docs/faq.rst | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/faq.rst b/docs/faq.rst index b292cd05..0a171bc9 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -257,7 +257,10 @@ Postfix, Dovecot, Nginx and Rspamd support overriding configuration files. Overr ``$ROOT/overrides``. Please refer to the official documentation of those programs for the correct syntax. The following file names will be taken as override configuration: -- `Postfix`_ - ``postfix.cf`` in postfix sub-directory; +- `Postfix`_ : + - ``postfix.cf`` as ``/overrides/postfix.cf`` + - ``master.cf`` as ``/overrides/postfix.master`` + - All ``/overrides/*.map`` files - `Dovecot`_ - ``dovecot.conf`` in dovecot sub-directory; - `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory; - `Rspamd`_ - All files in the ``rspamd`` sub-directory. From 6ba40bc0d79e82d55b34694fd62093d88c470617 Mon Sep 17 00:00:00 2001 From: Stephan Holl Date: Wed, 23 Dec 2020 18:53:56 +0100 Subject: [PATCH 15/74] Add newsfragment --- towncrier/newsfragments/1712.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1712.misc diff --git a/towncrier/newsfragments/1712.misc b/towncrier/newsfragments/1712.misc new file mode 100644 index 00000000..57c5a3b8 --- /dev/null +++ b/towncrier/newsfragments/1712.misc @@ -0,0 +1 @@ +This adds more details about the postfix-override possibilities (fixes #1628) From f56af3053aec9980d1b8b022307208b676c8bc06 Mon Sep 17 00:00:00 2001 From: Mordi Sacks Date: Sun, 17 Jan 2021 01:28:25 +0200 Subject: [PATCH 16/74] Removed email address --- core/admin/mailu/translations/he/LC_MESSAGES/messages.po | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/translations/he/LC_MESSAGES/messages.po b/core/admin/mailu/translations/he/LC_MESSAGES/messages.po index 4fe58afc..e884b737 100644 --- a/core/admin/mailu/translations/he/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/he/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" "PO-Revision-Date: 2019-11-27 22:20+0000\n" -"Last-Translator: Mordi Sacks \n" +"Last-Translator: Mordi Sacks \n" "Language-Team: Hebrew \n" "Language: he\n" From 82b5920b160e8be37ab9b6b27311c19463739dee Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20P=2E=20Barazzutti?= Date: Thu, 21 Jan 2021 19:54:47 +0100 Subject: [PATCH 17/74] typos --- CHANGELOG.md | 4 ++-- docs/releases.rst | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index a9c78f33..579f3e82 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -11,7 +11,7 @@ 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. -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 database server. @@ -66,7 +66,7 @@ configuration and upgrade your mailu.env. If you run the PostgreSQL server, the database was upgrade, so you will need to dump the database before upgrading and load the dump after the upgrade is -complete. Please not that the shipped image for PostgreSQL database will be +complete. Please note that the shipped image for PostgreSQL database will be deprecated before 1.8.0, you can switch to an external database server by then. - Deprecation: using the internal postgres image will be deprecated by 1.8.0 diff --git a/docs/releases.rst b/docs/releases.rst index e5bd06c0..141b66fd 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -33,7 +33,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 database as soon as possible. @@ -95,7 +95,7 @@ configuration and upgrade your mailu.env. If you run the PostgreSQL server, the database was upgrade, so you will need to dump the database before upgrading and load the dump after the upgrade is -complete. Please not that the shipped image for PostgreSQL database will be +complete. Please note that the shipped image for PostgreSQL database will be deprecated before 1.8.0, you can switch to an external database server by then. From 444529b7df2fca33f7bd3cdc9a89c3bb51e4e0b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20P=2E=20Barazzutti?= Date: Thu, 21 Jan 2021 19:55:53 +0100 Subject: [PATCH 18/74] rewording in doc --- docs/releases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.rst b/docs/releases.rst index 141b66fd..f8b1c731 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -35,7 +35,7 @@ configuration and upgrade your mailu.env. 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 database as soon as possible. +We recommend switching to another database as soon as possible (SQLite or MySQL). Override location changes ^^^^^^^^^^^^^^^^^^^^^^^^^ From 9e8183ee7193cffd42cd3e3ba9678a67e53a621e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20P=2E=20Barazzutti?= Date: Fri, 22 Jan 2021 05:29:54 +0100 Subject: [PATCH 19/74] rewording about the usage of PostgreSQL Co-authored-by: lub --- docs/releases.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/releases.rst b/docs/releases.rst index f8b1c731..7a15d1fa 100644 --- a/docs/releases.rst +++ b/docs/releases.rst @@ -35,7 +35,7 @@ configuration and upgrade your mailu.env. 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 another database as soon as possible (SQLite or MySQL). +We recommend switching to an external PostgreSQL database as soon as possible. Override location changes ^^^^^^^^^^^^^^^^^^^^^^^^^ From 612632e4fc7b498d8fb1fc714af1a02d0e1a1859 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Sun, 31 Jan 2021 10:58:41 +0100 Subject: [PATCH 20/74] Need to docker login before pulling images To avoid triggering the Download rate limite --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 467f6f5b..ae50eedb 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,6 +34,7 @@ install: before_script: - docker-compose -v + - docker login -u $DOCKER_UN -p $DOCKER_PW - docker-compose -f tests/build.yml build - sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' From 788d069b5379b0ae86e5d955994e144cc4d246f8 Mon Sep 17 00:00:00 2001 From: ofthesun9 Date: Sun, 31 Jan 2021 15:39:32 +0100 Subject: [PATCH 21/74] Modify docker login cmd to use --password-stdin and avoid warning --- .travis.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index ae50eedb..f2a85630 100644 --- a/.travis.yml +++ b/.travis.yml @@ -34,7 +34,7 @@ install: before_script: - docker-compose -v - - docker login -u $DOCKER_UN -p $DOCKER_PW + - echo "$DOCKER_PW" | docker login --username $DOCKER_UN --password-stdin - docker-compose -f tests/build.yml build - sudo -- sh -c 'mkdir -p /mailu && cp -r tests/certs /mailu && chmod 600 /mailu/certs/*' From 88f992de16ff6273b345136a0dca068c33cea9cc Mon Sep 17 00:00:00 2001 From: lub Date: Sat, 13 Feb 2021 13:34:44 +0100 Subject: [PATCH 22/74] show flash messages again This basically restores the behaviour, that got removed in ecdf0c25b3d9bbaa028bdc46cb721d2fb406dde2 during refactoring. --- core/admin/mailu/ui/templates/base.html | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/admin/mailu/ui/templates/base.html b/core/admin/mailu/ui/templates/base.html index 8a841e47..74d5653c 100644 --- a/core/admin/mailu/ui/templates/base.html +++ b/core/admin/mailu/ui/templates/base.html @@ -1,4 +1,5 @@ {% import "macros.html" as macros %} +{% import "bootstrap/utils.html" as utils %} @@ -37,6 +38,7 @@
+ {{ utils.flashed_messages(container=False) }} {% block content %}{% endblock %}
From 3ada506dbd08451deb24bfefa53efa7f4fc18b19 Mon Sep 17 00:00:00 2001 From: Stephan Holl <1610827+sholl@users.noreply.github.com> Date: Sat, 13 Feb 2021 17:35:33 +0100 Subject: [PATCH 23/74] Update docs/faq.rst as @lub suggests Co-authored-by: lub --- docs/faq.rst | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/docs/faq.rst b/docs/faq.rst index 0a171bc9..f200199d 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -258,9 +258,9 @@ Postfix, Dovecot, Nginx and Rspamd support overriding configuration files. Overr correct syntax. The following file names will be taken as override configuration: - `Postfix`_ : - - ``postfix.cf`` as ``/overrides/postfix.cf`` - - ``master.cf`` as ``/overrides/postfix.master`` - - All ``/overrides/*.map`` files + - ``main.cf`` as ``$ROOT/overrides/postfix/postfix.cf`` + - ``master.cf`` as ``$ROOT/overrides/postfix/postfix.master`` + - All ``$ROOT/overrides/postfix/*.map`` files - `Dovecot`_ - ``dovecot.conf`` in dovecot sub-directory; - `Nginx`_ - All ``*.conf`` files in the ``nginx`` sub-directory; - `Rspamd`_ - All files in the ``rspamd`` sub-directory. From aa8cb9890693b1563cb873df79d50a2fab6230e3 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 18 Feb 2021 12:31:45 +0100 Subject: [PATCH 24/74] Set sensible cookie options --- core/admin/mailu/configuration.py | 3 +++ 1 file changed, 3 insertions(+) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 2cf6a478..982a1eb0 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -123,6 +123,9 @@ class ConfigManager(dict): self.config['RATELIMIT_STORAGE_URL'] = 'redis://{0}/2'.format(self.config['REDIS_ADDRESS']) self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS']) + self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' + self.config['SESSION_COOKIE_HTTPONLY'] = True + self.config['SESSION_COOKIE_SECURE'] = self.config['TLS_FLAVOR'] != 'notls' # update the app config itself app.config = self From b6716f0d74681919384733414b8ca93c0dbf3dca Mon Sep 17 00:00:00 2001 From: Dario Ernst Date: Sat, 20 Feb 2021 13:03:08 +0100 Subject: [PATCH 25/74] Remove "CHUNKING" capability from nginx-smtp MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit With `CHUNKING`set as a capability, nginx advertises this capability to clients at a stage where the SMTP dialog does not seem to be forwarded to the proxy-target (postfix) yet. Nginx' SMTP parser itself does not support the `BDAT` command issued as part of a chunke-d dialog. This makes Nginx respond with a `250 2.0.0 OK` and close the connection, after the mail-data got sent by the client — without forwarding this to the proxy-target. With this, users mail can be lost. Furthermore, when a user uses a sieve filter to forward mail, dovecot sometimes chunks the forwarded mail when sending it through `front`. These forwards then fail. Removing `CHUNKING` from the capabilities fixes this behavior. --- core/nginx/conf/nginx.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/nginx/conf/nginx.conf b/core/nginx/conf/nginx.conf index df598c94..f7d9f074 100644 --- a/core/nginx/conf/nginx.conf +++ b/core/nginx/conf/nginx.conf @@ -215,7 +215,7 @@ mail { {% endif %} # Advertise real capabilites of backends (postfix/dovecot) - smtp_capabilities PIPELINING SIZE {{ MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN CHUNKING; + smtp_capabilities PIPELINING SIZE {{ MESSAGE_SIZE_LIMIT }} ETRN ENHANCEDSTATUSCODES 8BITMIME DSN; pop3_capabilities TOP UIDL RESP-CODES PIPELINING AUTH-RESP-CODE USER; imap_capabilities IMAP4 IMAP4rev1 UIDPLUS SASL-IR LOGIN-REFERRALS ID ENABLE IDLE LITERAL+; From 76e5614d13abf71fa39f9bbe0a4c450af897c665 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sat, 27 Feb 2021 10:37:59 +0100 Subject: [PATCH 26/74] Add mergify to the list of trusted authors The idea is to prevent backports from being stuck pending for review for too long. --- .mergify.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.mergify.yml b/.mergify.yml index c1141a93..2af387ed 100644 --- a/.mergify.yml +++ b/.mergify.yml @@ -27,7 +27,7 @@ pull_request_rules: - name: Trusted author and 1 approved review; trigger bors r+ conditions: - - author~=^(kaiyou|muhlemmer|mildred|HorayNarea|adi90x|hoellen|ofthesun9|Nebukadneza|micw|lub|Diman0)$ + - author~=^(mergify|kaiyou|muhlemmer|mildred|HorayNarea|adi90x|hoellen|ofthesun9|Nebukadneza|micw|lub|Diman0)$ - -title~=(WIP|wip) - -label~=^(status/wip|status/blocked|review/need2)$ - "#approved-reviews-by>=1" From af251216b0fd9f16b778d7808a1c672eedb1f2b3 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 11:31:51 +0000 Subject: [PATCH 27/74] Translated using Weblate (English) Currently translated at 11.0% (18 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- core/admin/mailu/translations/en/LC_MESSAGES/messages.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 2ada20b1..91fee01b 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2020-03-11 23:03+0000\n" -"Last-Translator: Jae Beojkkoch \n" +"PO-Revision-Date: 2021-03-03 11:35+0000\n" +"Last-Translator: Jaume Barber \n" "Language-Team: English \n" "Language: en\n" @@ -17,7 +17,7 @@ msgstr "" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.11.2\n" +"X-Generator: Weblate 4.0.1\n" "Generated-By: Babel 2.5.3\n" #: mailu/ui/forms.py:32 @@ -593,7 +593,7 @@ msgstr "" #: mailu/ui/templates/relay/create.html:4 msgid "New relay domain" -msgstr "" +msgstr "New relay domain" #: mailu/ui/templates/relay/edit.html:4 msgid "Edit relayd domain" From 3a9a133226cc67ad3a2c7260763b1fe3c646dea4 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 3 Mar 2021 11:34:06 +0000 Subject: [PATCH 28/74] Translated using Weblate (English) Currently translated at 11.0% (18 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- core/admin/mailu/translations/en/LC_MESSAGES/messages.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 91fee01b..bdfe5716 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" "PO-Revision-Date: 2021-03-03 11:35+0000\n" -"Last-Translator: Jaume Barber \n" +"Last-Translator: Anonymous \n" "Language-Team: English \n" "Language: en\n" @@ -105,7 +105,7 @@ msgstr "" #: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 #: mailu/ui/templates/user/signup_domain.html:16 msgid "Quota" -msgstr "" +msgstr "Quota" #: mailu/ui/forms.py:81 msgid "Allow IMAP access" @@ -229,7 +229,7 @@ msgstr "" #: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20 #: mailu/ui/templates/client.html:47 msgid "TCP port" -msgstr "" +msgstr "TCP port" #: mailu/ui/forms.py:160 msgid "Enable TLS" From b9c2dc1a79f33bb4c38aca5b80501f4b74de6a2a Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 11:24:19 +0000 Subject: [PATCH 29/74] Translated using Weblate (Catalan) Currently translated at 98.6% (149 of 151 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/ca/ --- core/admin/mailu/translations/ca/LC_MESSAGES/messages.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po b/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po index f63b7083..76594a3c 100644 --- a/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2020-04-26 13:09+0000\n" +"PO-Revision-Date: 2021-03-03 11:35+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Catalan \n" @@ -304,7 +304,7 @@ msgstr "Resposta automàtica" #: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26 #: mailu/ui/templates/user/list.html:36 msgid "Fetched accounts" -msgstr "Comptes trobats" +msgstr "Comptes vinculats" #: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4 msgid "Authentication tokens" @@ -324,7 +324,7 @@ msgstr "Administradors" #: mailu/ui/templates/sidebar.html:54 msgid "Relayed domains" -msgstr "Dominis tramesos" +msgstr "Dominis delegats" #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 msgid "Antispam" From 725cdc270c0cce7f1e9ea5c3a14a4f7c5d22f39d Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 11:37:34 +0000 Subject: [PATCH 30/74] Translated using Weblate (Spanish) Currently translated at 100.0% (163 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/es/ --- core/admin/mailu/translations/es/LC_MESSAGES/messages.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/translations/es/LC_MESSAGES/messages.po b/core/admin/mailu/translations/es/LC_MESSAGES/messages.po index 94b39439..ff6b9f36 100644 --- a/core/admin/mailu/translations/es/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/es/LC_MESSAGES/messages.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Mailu\n" -"PO-Revision-Date: 2020-03-11 23:03+0000\n" +"PO-Revision-Date: 2021-03-03 12:37+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Spanish \n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.11.2\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -425,7 +425,7 @@ msgstr "Añadir una cuenta" #: mailu/ui/templates/fetch/list.html:19 msgid "Endpoint" -msgstr "Punto final" +msgstr "Endpoint" #: mailu/ui/templates/fetch/list.html:22 msgid "Last check" @@ -437,7 +437,7 @@ msgstr "Añadir un gestor" #: mailu/ui/templates/manager/list.html:4 msgid "Manager list" -msgstr "Gestor de lista" +msgstr "Lista de gestores" #: mailu/ui/templates/manager/list.html:12 msgid "Add manager" From 5e0aa65c8d29d6fc16d463fe4e34fa777b552a69 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:02:15 +0000 Subject: [PATCH 31/74] Translated using Weblate (Italian) Currently translated at 96.3% (157 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/it/ --- core/admin/mailu/translations/it/LC_MESSAGES/messages.po | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/translations/it/LC_MESSAGES/messages.po b/core/admin/mailu/translations/it/LC_MESSAGES/messages.po index 9ef5ac84..6ec219bf 100644 --- a/core/admin/mailu/translations/it/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/it/LC_MESSAGES/messages.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Mailu\n" -"PO-Revision-Date: 2020-03-11 23:03+0000\n" +"PO-Revision-Date: 2021-03-03 17:03+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Italian \n" @@ -10,7 +10,7 @@ msgstr "" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=2; plural=n != 1;\n" -"X-Generator: Weblate 3.11.2\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -576,6 +576,7 @@ msgid "Relayed domain list" msgstr "Elenco di domini affidati" #: mailu/ui/templates/relay/list.html:9 +#, fuzzy msgid "New relayed domain" msgstr "Nuovo dominio affidato" From 43133d85154eae91c662b8b756dc3e89d26ac7cd Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:05:23 +0000 Subject: [PATCH 32/74] Added translation using Weblate (Basque) --- .../translations/eu/LC_MESSAGES/messages.po | 669 ++++++++++++++++++ 1 file changed, 669 insertions(+) create mode 100644 core/admin/mailu/translations/eu/LC_MESSAGES/messages.po diff --git a/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po b/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po new file mode 100644 index 00000000..3a72c9af --- /dev/null +++ b/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po @@ -0,0 +1,669 @@ +# Translations template for PROJECT. +# Copyright (C) 2018 ORGANIZATION +# This file is distributed under the same license as the PROJECT project. +# FIRST AUTHOR , 2018. +# +msgid "" +msgstr "" +"Project-Id-Version: PROJECT VERSION\n" +"Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" +"POT-Creation-Date: 2018-04-22 12:10+0200\n" +"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" +"Last-Translator: Automatically generated\n" +"Language-Team: none\n" +"Language: eu\n" +"MIME-Version: 1.0\n" +"Content-Type: text/plain; charset=utf-8\n" +"Content-Transfer-Encoding: 8bit\n" +"Generated-By: Babel 2.5.3\n" + +#: mailu/ui/forms.py:32 +msgid "Invalid email address." +msgstr "" + +#: mailu/ui/forms.py:36 +msgid "Confirm" +msgstr "" + +#: mailu/ui/forms.py:40 mailu/ui/forms.py:77 +msgid "E-mail" +msgstr "" + +#: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90 +#: mailu/ui/forms.py:109 mailu/ui/forms.py:162 +#: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59 +msgid "Password" +msgstr "" + +#: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4 +#: mailu/ui/templates/sidebar.html:111 +msgid "Sign in" +msgstr "" + +#: mailu/ui/forms.py:46 mailu/ui/forms.py:56 +#: mailu/ui/templates/domain/details.html:27 +#: mailu/ui/templates/domain/list.html:18 mailu/ui/templates/relay/list.html:17 +msgid "Domain name" +msgstr "" + +#: mailu/ui/forms.py:47 +msgid "Maximum user count" +msgstr "" + +#: mailu/ui/forms.py:48 +msgid "Maximum alias count" +msgstr "" + +#: mailu/ui/forms.py:49 +msgid "Maximum user quota" +msgstr "" + +#: mailu/ui/forms.py:50 +msgid "Enable sign-up" +msgstr "" + +#: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83 +#: mailu/ui/forms.py:128 mailu/ui/forms.py:140 +#: mailu/ui/templates/alias/list.html:21 mailu/ui/templates/domain/list.html:21 +#: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19 +#: mailu/ui/templates/user/list.html:23 +msgid "Comment" +msgstr "" + +#: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66 +#: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141 +msgid "Create" +msgstr "" + +#: mailu/ui/forms.py:57 +msgid "Initial admin" +msgstr "" + +#: mailu/ui/forms.py:58 +msgid "Admin password" +msgstr "" + +#: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 +msgid "Confirm password" +msgstr "" + +#: mailu/ui/forms.py:65 +msgid "Alternative name" +msgstr "" + +#: mailu/ui/forms.py:70 +msgid "Relayed domain name" +msgstr "" + +#: mailu/ui/forms.py:71 mailu/ui/templates/relay/list.html:18 +msgid "Remote host" +msgstr "" + +#: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 +#: mailu/ui/templates/user/signup_domain.html:16 +msgid "Quota" +msgstr "" + +#: mailu/ui/forms.py:81 +msgid "Allow IMAP access" +msgstr "" + +#: mailu/ui/forms.py:82 +msgid "Allow POP3 access" +msgstr "" + +#: mailu/ui/forms.py:84 +msgid "Enabled" +msgstr "" + +#: mailu/ui/forms.py:85 +msgid "Save" +msgstr "" + +#: mailu/ui/forms.py:89 +msgid "Email address" +msgstr "" + +#: mailu/ui/forms.py:93 mailu/ui/templates/sidebar.html:117 +#: mailu/ui/templates/user/signup.html:4 +#: mailu/ui/templates/user/signup_domain.html:4 +msgid "Sign up" +msgstr "" + +#: mailu/ui/forms.py:97 +msgid "Displayed name" +msgstr "" + +#: mailu/ui/forms.py:98 +msgid "Enable spam filter" +msgstr "" + +#: mailu/ui/forms.py:99 +msgid "Spam filter tolerance" +msgstr "" + +#: mailu/ui/forms.py:100 +msgid "Enable forwarding" +msgstr "" + +#: mailu/ui/forms.py:101 +msgid "Keep a copy of the emails" +msgstr "" + +#: mailu/ui/forms.py:103 mailu/ui/forms.py:139 +#: mailu/ui/templates/alias/list.html:20 +msgid "Destination" +msgstr "" + +#: mailu/ui/forms.py:105 +msgid "Save settings" +msgstr "" + +#: mailu/ui/forms.py:110 +msgid "Password check" +msgstr "" + +#: mailu/ui/forms.py:111 mailu/ui/templates/sidebar.html:16 +msgid "Update password" +msgstr "" + +#: mailu/ui/forms.py:115 +msgid "Enable automatic reply" +msgstr "" + +#: mailu/ui/forms.py:116 +msgid "Reply subject" +msgstr "" + +#: mailu/ui/forms.py:117 +msgid "Reply body" +msgstr "" + +#: mailu/ui/forms.py:119 +msgid "End of vacation" +msgstr "" + +#: mailu/ui/forms.py:120 +msgid "Update" +msgstr "" + +#: mailu/ui/forms.py:125 +msgid "Your token (write it down, as it will never be displayed again)" +msgstr "" + +#: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20 +msgid "Authorized IP" +msgstr "" + +#: mailu/ui/forms.py:136 +msgid "Alias" +msgstr "" + +#: mailu/ui/forms.py:138 +msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" +msgstr "" + +#: mailu/ui/forms.py:145 +msgid "Admin email" +msgstr "" + +#: mailu/ui/forms.py:146 mailu/ui/forms.py:151 mailu/ui/forms.py:164 +msgid "Submit" +msgstr "" + +#: mailu/ui/forms.py:150 +msgid "Manager email" +msgstr "" + +#: mailu/ui/forms.py:155 +msgid "Protocol" +msgstr "" + +#: mailu/ui/forms.py:158 +msgid "Hostname or IP" +msgstr "" + +#: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20 +#: mailu/ui/templates/client.html:47 +msgid "TCP port" +msgstr "" + +#: mailu/ui/forms.py:160 +msgid "Enable TLS" +msgstr "" + +#: mailu/ui/forms.py:161 mailu/ui/templates/client.html:28 +#: mailu/ui/templates/client.html:55 mailu/ui/templates/fetch/list.html:20 +msgid "Username" +msgstr "" + +#: mailu/ui/forms.py:163 +msgid "Keep emails on the server" +msgstr "" + +#: mailu/ui/forms.py:168 +msgid "Announcement subject" +msgstr "" + +#: mailu/ui/forms.py:170 +msgid "Announcement body" +msgstr "" + +#: mailu/ui/forms.py:172 +msgid "Send" +msgstr "" + +#: mailu/ui/templates/announcement.html:4 +msgid "Public announcement" +msgstr "" + +#: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82 +msgid "Client setup" +msgstr "" + +#: mailu/ui/templates/client.html:16 mailu/ui/templates/client.html:43 +msgid "Mail protocol" +msgstr "" + +#: mailu/ui/templates/client.html:24 mailu/ui/templates/client.html:51 +msgid "Server name" +msgstr "" + +#: mailu/ui/templates/confirm.html:4 +msgid "Confirm action" +msgstr "" + +#: mailu/ui/templates/confirm.html:13 +#, python-format +msgid "You are about to %(action)s. Please confirm your action." +msgstr "" + +#: mailu/ui/templates/docker-error.html:4 +msgid "Docker error" +msgstr "" + +#: mailu/ui/templates/docker-error.html:12 +msgid "An error occurred while talking to the Docker server." +msgstr "" + +#: mailu/ui/templates/login.html:8 +msgid "to access the administration tools" +msgstr "" + +#: mailu/ui/templates/sidebar.html:11 mailu/ui/templates/user/list.html:34 +msgid "Settings" +msgstr "" + +#: mailu/ui/templates/sidebar.html:21 mailu/ui/templates/user/list.html:35 +msgid "Auto-reply" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:4 mailu/ui/templates/sidebar.html:26 +#: mailu/ui/templates/user/list.html:36 +msgid "Fetched accounts" +msgstr "" + +#: mailu/ui/templates/sidebar.html:31 mailu/ui/templates/token/list.html:4 +msgid "Authentication tokens" +msgstr "" + +#: mailu/ui/templates/sidebar.html:35 +msgid "Administration" +msgstr "" + +#: mailu/ui/templates/sidebar.html:44 +msgid "Announcement" +msgstr "" + +#: mailu/ui/templates/sidebar.html:49 +msgid "Administrators" +msgstr "" + +#: mailu/ui/templates/sidebar.html:54 +msgid "Relayed domains" +msgstr "" + +#: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 +msgid "Antispam" +msgstr "" + +#: mailu/ui/templates/sidebar.html:66 +msgid "Mail domains" +msgstr "" + +#: mailu/ui/templates/sidebar.html:72 +msgid "Go to" +msgstr "" + +#: mailu/ui/templates/sidebar.html:76 +msgid "Webmail" +msgstr "" + +#: mailu/ui/templates/sidebar.html:87 +msgid "Website" +msgstr "" + +#: mailu/ui/templates/sidebar.html:92 +msgid "Help" +msgstr "" + +#: mailu/ui/templates/domain/signup.html:4 mailu/ui/templates/sidebar.html:98 +msgid "Register a domain" +msgstr "" + +#: mailu/ui/templates/sidebar.html:105 +msgid "Sign out" +msgstr "" + +#: mailu/ui/templates/working.html:4 +msgid "We are still working on this feature!" +msgstr "" + +#: mailu/ui/templates/admin/create.html:4 +msgid "Add a global administrator" +msgstr "" + +#: mailu/ui/templates/admin/list.html:4 +msgid "Global administrators" +msgstr "" + +#: mailu/ui/templates/admin/list.html:9 +msgid "Add administrator" +msgstr "" + +#: mailu/ui/templates/admin/list.html:16 mailu/ui/templates/alias/list.html:18 +#: mailu/ui/templates/alternative/list.html:18 +#: mailu/ui/templates/domain/list.html:16 mailu/ui/templates/fetch/list.html:18 +#: mailu/ui/templates/manager/list.html:18 +#: mailu/ui/templates/relay/list.html:16 mailu/ui/templates/token/list.html:18 +#: mailu/ui/templates/user/list.html:18 +msgid "Actions" +msgstr "" + +#: mailu/ui/templates/admin/list.html:17 mailu/ui/templates/alias/list.html:19 +#: mailu/ui/templates/manager/list.html:19 mailu/ui/templates/user/list.html:20 +msgid "Email" +msgstr "" + +#: mailu/ui/templates/admin/list.html:22 mailu/ui/templates/alias/list.html:29 +#: mailu/ui/templates/alternative/list.html:25 +#: mailu/ui/templates/domain/list.html:31 mailu/ui/templates/fetch/list.html:31 +#: mailu/ui/templates/manager/list.html:24 +#: mailu/ui/templates/relay/list.html:27 mailu/ui/templates/token/list.html:26 +#: mailu/ui/templates/user/list.html:31 +msgid "Delete" +msgstr "" + +#: mailu/ui/templates/alias/create.html:4 +msgid "Create alias" +msgstr "" + +#: mailu/ui/templates/alias/edit.html:4 +msgid "Edit alias" +msgstr "" + +#: mailu/ui/templates/alias/list.html:4 +msgid "Alias list" +msgstr "" + +#: mailu/ui/templates/alias/list.html:12 +msgid "Add alias" +msgstr "" + +#: mailu/ui/templates/alias/list.html:22 +#: mailu/ui/templates/alternative/list.html:20 +#: mailu/ui/templates/domain/list.html:22 mailu/ui/templates/fetch/list.html:24 +#: mailu/ui/templates/relay/list.html:20 mailu/ui/templates/token/list.html:21 +#: mailu/ui/templates/user/list.html:24 +msgid "Created" +msgstr "" + +#: mailu/ui/templates/alias/list.html:23 mailu/ui/templates/domain/list.html:23 +#: mailu/ui/templates/fetch/list.html:25 mailu/ui/templates/relay/list.html:21 +#: mailu/ui/templates/user/list.html:25 +msgid "Last edit" +msgstr "" + +#: mailu/ui/templates/alias/list.html:28 mailu/ui/templates/domain/list.html:30 +#: mailu/ui/templates/fetch/list.html:30 mailu/ui/templates/relay/list.html:26 +#: mailu/ui/templates/user/list.html:30 +msgid "Edit" +msgstr "" + +#: mailu/ui/templates/alternative/create.html:4 +msgid "Create alternative domain" +msgstr "" + +#: mailu/ui/templates/alternative/list.html:4 +msgid "Alternative domain list" +msgstr "" + +#: mailu/ui/templates/alternative/list.html:12 +msgid "Add alternative" +msgstr "" + +#: mailu/ui/templates/alternative/list.html:19 +msgid "Name" +msgstr "" + +#: mailu/ui/templates/domain/create.html:4 +#: mailu/ui/templates/domain/list.html:9 +msgid "New domain" +msgstr "" + +#: mailu/ui/templates/domain/details.html:4 +msgid "Domain details" +msgstr "" + +#: mailu/ui/templates/domain/details.html:15 +msgid "Regenerate keys" +msgstr "" + +#: mailu/ui/templates/domain/details.html:17 +msgid "Generate keys" +msgstr "" + +#: mailu/ui/templates/domain/details.html:31 +msgid "DNS MX entry" +msgstr "" + +#: mailu/ui/templates/domain/details.html:35 +msgid "DNS SPF entries" +msgstr "" + +#: mailu/ui/templates/domain/details.html:42 +msgid "DKIM public key" +msgstr "" + +#: mailu/ui/templates/domain/details.html:46 +msgid "DNS DKIM entry" +msgstr "" + +#: mailu/ui/templates/domain/details.html:50 +msgid "DNS DMARC entry" +msgstr "" + +#: mailu/ui/templates/domain/edit.html:4 +msgid "Edit domain" +msgstr "" + +#: mailu/ui/templates/domain/list.html:4 +msgid "Domain list" +msgstr "" + +#: mailu/ui/templates/domain/list.html:17 +msgid "Manage" +msgstr "" + +#: mailu/ui/templates/domain/list.html:19 +msgid "Mailbox count" +msgstr "" + +#: mailu/ui/templates/domain/list.html:20 +msgid "Alias count" +msgstr "" + +#: mailu/ui/templates/domain/list.html:28 +msgid "Details" +msgstr "" + +#: mailu/ui/templates/domain/list.html:35 +msgid "Users" +msgstr "" + +#: mailu/ui/templates/domain/list.html:36 +msgid "Aliases" +msgstr "" + +#: mailu/ui/templates/domain/list.html:37 +msgid "Managers" +msgstr "" + +#: mailu/ui/templates/domain/list.html:39 +msgid "Alternatives" +msgstr "" + +#: mailu/ui/templates/domain/signup.html:13 +msgid "" +"In order to register a new domain, you must first setup the\n" +" domain zone so that the domain MX points to this server" +msgstr "" + +#: mailu/ui/templates/domain/signup.html:18 +msgid "" +"If you do not know how to setup an MX record for your DNS " +"zone,\n" +" please contact your DNS provider or administrator. Also, please wait " +"a\n" +" couple minutes after the MX is set so the local server " +"cache\n" +" expires." +msgstr "" + +#: mailu/ui/templates/fetch/create.html:4 +msgid "Add a fetched account" +msgstr "" + +#: mailu/ui/templates/fetch/edit.html:4 +msgid "Update a fetched account" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:12 +msgid "Add an account" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:19 +msgid "Endpoint" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:21 +msgid "Keep emails" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:22 +msgid "Last check" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:35 +msgid "yes" +msgstr "" + +#: mailu/ui/templates/fetch/list.html:35 +msgid "no" +msgstr "" + +#: mailu/ui/templates/manager/create.html:4 +msgid "Add a manager" +msgstr "" + +#: mailu/ui/templates/manager/list.html:4 +msgid "Manager list" +msgstr "" + +#: mailu/ui/templates/manager/list.html:12 +msgid "Add manager" +msgstr "" + +#: mailu/ui/templates/relay/create.html:4 +msgid "New relay domain" +msgstr "" + +#: mailu/ui/templates/relay/edit.html:4 +msgid "Edit relayd domain" +msgstr "" + +#: mailu/ui/templates/relay/list.html:4 +msgid "Relayed domain list" +msgstr "" + +#: mailu/ui/templates/relay/list.html:9 +msgid "New relayed domain" +msgstr "" + +#: mailu/ui/templates/token/create.html:4 +msgid "Create an authentication token" +msgstr "" + +#: mailu/ui/templates/token/list.html:12 +msgid "New token" +msgstr "" + +#: mailu/ui/templates/user/create.html:4 +msgid "New user" +msgstr "" + +#: mailu/ui/templates/user/create.html:15 +msgid "General" +msgstr "" + +#: mailu/ui/templates/user/create.html:22 +msgid "Features and quotas" +msgstr "" + +#: mailu/ui/templates/user/edit.html:4 +msgid "Edit user" +msgstr "" + +#: mailu/ui/templates/user/forward.html:4 +msgid "Forward emails" +msgstr "" + +#: mailu/ui/templates/user/list.html:4 +msgid "User list" +msgstr "" + +#: mailu/ui/templates/user/list.html:12 +msgid "Add user" +msgstr "" + +#: mailu/ui/templates/user/list.html:19 mailu/ui/templates/user/settings.html:4 +msgid "User settings" +msgstr "" + +#: mailu/ui/templates/user/list.html:21 +msgid "Features" +msgstr "" + +#: mailu/ui/templates/user/password.html:4 +msgid "Password update" +msgstr "" + +#: mailu/ui/templates/user/reply.html:4 +msgid "Automatic reply" +msgstr "" + +#: mailu/ui/templates/user/settings.html:22 +msgid "Auto-forward" +msgstr "" + +#: mailu/ui/templates/user/signup_domain.html:8 +msgid "pick a domain for the new account" +msgstr "" + +#: mailu/ui/templates/user/signup_domain.html:14 +msgid "Domain" +msgstr "" + +#: mailu/ui/templates/user/signup_domain.html:15 +msgid "Available slots" +msgstr "" From 7de94275a0c01f9b11bcf533b42a7e7148b6b4f2 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 3 Mar 2021 11:35:58 +0000 Subject: [PATCH 33/74] Translated using Weblate (English) Currently translated at 17.7% (29 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- .../mailu/translations/en/LC_MESSAGES/messages.po | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index bdfe5716..0b050560 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2021-03-03 11:35+0000\n" +"PO-Revision-Date: 2021-03-03 17:17+0000\n" "Last-Translator: Anonymous \n" "Language-Team: English \n" @@ -30,13 +30,13 @@ msgstr "Confirm" #: mailu/ui/forms.py:40 mailu/ui/forms.py:77 msgid "E-mail" -msgstr "" +msgstr "E-mail" #: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90 #: mailu/ui/forms.py:109 mailu/ui/forms.py:162 #: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59 msgid "Password" -msgstr "" +msgstr "Password" #: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4 #: mailu/ui/templates/sidebar.html:111 @@ -283,7 +283,7 @@ msgstr "" #: mailu/ui/templates/docker-error.html:4 msgid "Docker error" -msgstr "" +msgstr "Docker error" #: mailu/ui/templates/docker-error.html:12 msgid "An error occurred while talking to the Docker server." @@ -669,7 +669,7 @@ msgstr "" #: mailu/ui/templates/user/signup_domain.html:14 msgid "Domain" -msgstr "" +msgstr "Domain" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" From 7c0158c5f8fc64ca4dc913229e81e51367283ca7 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 11:36:15 +0000 Subject: [PATCH 34/74] Translated using Weblate (English) Currently translated at 17.7% (29 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- core/admin/mailu/translations/en/LC_MESSAGES/messages.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 0b050560..a09ac1c7 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" "PO-Revision-Date: 2021-03-03 17:17+0000\n" -"Last-Translator: Anonymous \n" +"Last-Translator: Jaume Barber \n" "Language-Team: English \n" "Language: en\n" @@ -328,7 +328,7 @@ msgstr "" #: mailu/ui/templates/sidebar.html:54 msgid "Relayed domains" -msgstr "" +msgstr "Relayed domains" #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 msgid "Antispam" @@ -601,11 +601,11 @@ msgstr "" #: mailu/ui/templates/relay/list.html:4 msgid "Relayed domain list" -msgstr "" +msgstr "Relayed domain list" #: mailu/ui/templates/relay/list.html:9 msgid "New relayed domain" -msgstr "" +msgstr "New relayed domain" #: mailu/ui/templates/token/create.html:4 msgid "Create an authentication token" From a2933d00f3e9ab6834de095f9a6a5975be9c4bce Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:17:19 +0000 Subject: [PATCH 35/74] Translated using Weblate (English) Currently translated at 29.4% (48 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- core/admin/mailu/translations/en/LC_MESSAGES/messages.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index a09ac1c7..68f0177d 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2021-03-03 17:17+0000\n" +"PO-Revision-Date: 2021-03-03 17:57+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: English \n" @@ -51,7 +51,7 @@ msgstr "" #: mailu/ui/forms.py:47 msgid "Maximum user count" -msgstr "" +msgstr "Maximum user count" #: mailu/ui/forms.py:48 msgid "Maximum alias count" @@ -332,7 +332,7 @@ msgstr "Relayed domains" #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 msgid "Antispam" -msgstr "" +msgstr "Antispam" #: mailu/ui/templates/sidebar.html:66 msgid "Mail domains" From 3d17000ceb419014c9a7fb20fb90e4f9257cc33e Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 3 Mar 2021 17:20:37 +0000 Subject: [PATCH 36/74] Translated using Weblate (English) Currently translated at 29.4% (48 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- .../translations/en/LC_MESSAGES/messages.po | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 68f0177d..026f47c6 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" "PO-Revision-Date: 2021-03-03 17:57+0000\n" -"Last-Translator: Jaume Barber \n" +"Last-Translator: Anonymous \n" "Language-Team: English \n" "Language: en\n" @@ -71,12 +71,12 @@ msgstr "" #: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19 #: mailu/ui/templates/user/list.html:23 msgid "Comment" -msgstr "" +msgstr "Comment" #: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66 #: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141 msgid "Create" -msgstr "" +msgstr "Create" #: mailu/ui/forms.py:57 msgid "Initial admin" @@ -88,11 +88,11 @@ msgstr "" #: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 msgid "Confirm password" -msgstr "" +msgstr "Confirm password" #: mailu/ui/forms.py:65 msgid "Alternative name" -msgstr "" +msgstr "Alternative name" #: mailu/ui/forms.py:70 msgid "Relayed domain name" @@ -109,19 +109,19 @@ msgstr "Quota" #: mailu/ui/forms.py:81 msgid "Allow IMAP access" -msgstr "" +msgstr "Allow IMAP access" #: mailu/ui/forms.py:82 msgid "Allow POP3 access" -msgstr "" +msgstr "Allow POP3 access" #: mailu/ui/forms.py:84 msgid "Enabled" -msgstr "" +msgstr "Enabled" #: mailu/ui/forms.py:85 msgid "Save" -msgstr "" +msgstr "Save" #: mailu/ui/forms.py:89 msgid "Email address" @@ -139,7 +139,7 @@ msgstr "" #: mailu/ui/forms.py:98 msgid "Enable spam filter" -msgstr "" +msgstr "Enable spam filter" #: mailu/ui/forms.py:99 msgid "Spam filter tolerance" From 0dc8817f326d03f7d0478d8e3356520b0e85f3d0 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:57:27 +0000 Subject: [PATCH 37/74] Translated using Weblate (English) Currently translated at 38.6% (63 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- .../translations/en/LC_MESSAGES/messages.po | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 026f47c6..6773c1f2 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2021-03-03 17:57+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2021-03-03 18:18+0000\n" +"Last-Translator: Jaume Barber \n" "Language-Team: English \n" "Language: en\n" @@ -59,11 +59,11 @@ msgstr "" #: mailu/ui/forms.py:49 msgid "Maximum user quota" -msgstr "" +msgstr "Maximum user quota" #: mailu/ui/forms.py:50 msgid "Enable sign-up" -msgstr "" +msgstr "Enable sign-up" #: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83 #: mailu/ui/forms.py:128 mailu/ui/forms.py:140 @@ -80,11 +80,11 @@ msgstr "Create" #: mailu/ui/forms.py:57 msgid "Initial admin" -msgstr "" +msgstr "Initial admin" #: mailu/ui/forms.py:58 msgid "Admin password" -msgstr "" +msgstr "Admin password" #: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 msgid "Confirm password" @@ -131,7 +131,7 @@ msgstr "" #: mailu/ui/templates/user/signup.html:4 #: mailu/ui/templates/user/signup_domain.html:4 msgid "Sign up" -msgstr "" +msgstr "Sign up" #: mailu/ui/forms.py:97 msgid "Displayed name" @@ -143,7 +143,7 @@ msgstr "Enable spam filter" #: mailu/ui/forms.py:99 msgid "Spam filter tolerance" -msgstr "" +msgstr "Spam filter tolerance" #: mailu/ui/forms.py:100 msgid "Enable forwarding" From 58c22fd2c6128e208c1fb7dc128ba7ac548261b0 Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 3 Mar 2021 18:09:32 +0000 Subject: [PATCH 38/74] Translated using Weblate (English) Currently translated at 38.6% (63 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- .../mailu/translations/en/LC_MESSAGES/messages.po | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index 6773c1f2..f931b362 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -9,7 +9,7 @@ msgstr "" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" "PO-Revision-Date: 2021-03-03 18:18+0000\n" -"Last-Translator: Jaume Barber \n" +"Last-Translator: Anonymous \n" "Language-Team: English \n" "Language: en\n" @@ -147,7 +147,7 @@ msgstr "Spam filter tolerance" #: mailu/ui/forms.py:100 msgid "Enable forwarding" -msgstr "" +msgstr "Enable forwarding" #: mailu/ui/forms.py:101 msgid "Keep a copy of the emails" @@ -160,7 +160,7 @@ msgstr "" #: mailu/ui/forms.py:105 msgid "Save settings" -msgstr "" +msgstr "Save settings" #: mailu/ui/forms.py:110 msgid "Password check" @@ -184,11 +184,11 @@ msgstr "" #: mailu/ui/forms.py:119 msgid "End of vacation" -msgstr "" +msgstr "End of vacation" #: mailu/ui/forms.py:120 msgid "Update" -msgstr "" +msgstr "Update" #: mailu/ui/forms.py:125 msgid "Your token (write it down, as it will never be displayed again)" @@ -200,7 +200,7 @@ msgstr "" #: mailu/ui/forms.py:136 msgid "Alias" -msgstr "" +msgstr "Alias" #: mailu/ui/forms.py:138 msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" From 6da597887060fa66bb3d711dde96749718bfcf6b Mon Sep 17 00:00:00 2001 From: Anonymous Date: Wed, 3 Mar 2021 11:39:11 +0000 Subject: [PATCH 39/74] Translated using Weblate (German) Currently translated at 88.3% (144 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/de/ --- .../mailu/translations/de/LC_MESSAGES/messages.po | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/translations/de/LC_MESSAGES/messages.po b/core/admin/mailu/translations/de/LC_MESSAGES/messages.po index 941c22ef..4ae71561 100644 --- a/core/admin/mailu/translations/de/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/de/LC_MESSAGES/messages.po @@ -1,11 +1,16 @@ msgid "" msgstr "" +"Project-Id-Version: Mailu\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Anonymous \n" +"Language-Team: German \n" +"Language: de\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: POEditor.com\n" -"Project-Id-Version: Mailu\n" -"Language: de\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -64,7 +69,7 @@ msgstr "Passwort bestätigen" #: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 #: mailu/ui/templates/user/signup_domain.html:16 msgid "Quota" -msgstr "Quota" +msgstr "Kontingent" #: mailu/ui/forms.py:81 msgid "Allow IMAP access" @@ -699,4 +704,3 @@ msgstr "Domain" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" msgstr "Verfügbare Plätze" - From 6143d66eb888cc02a58ba91bc5e912cdc1d31424 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 18:18:39 +0000 Subject: [PATCH 40/74] Translated using Weblate (English) Currently translated at 39.2% (64 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/en/ --- core/admin/mailu/translations/en/LC_MESSAGES/messages.po | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po index f931b362..4db1dbf1 100644 --- a/core/admin/mailu/translations/en/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/en/LC_MESSAGES/messages.po @@ -8,8 +8,8 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2021-03-03 18:18+0000\n" -"Last-Translator: Anonymous \n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Jaume Barber \n" "Language-Team: English \n" "Language: en\n" @@ -196,7 +196,7 @@ msgstr "" #: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20 msgid "Authorized IP" -msgstr "" +msgstr "Authorized IP" #: mailu/ui/forms.py:136 msgid "Alias" From 5e96a4bfcfbe93a3a45922811b4e88ebad874fa8 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 13:11:18 +0000 Subject: [PATCH 41/74] Translated using Weblate (Spanish) Currently translated at 91.4% (149 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/es/ --- core/admin/mailu/translations/es/LC_MESSAGES/messages.po | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/translations/es/LC_MESSAGES/messages.po b/core/admin/mailu/translations/es/LC_MESSAGES/messages.po index ff6b9f36..c70ed6f5 100644 --- a/core/admin/mailu/translations/es/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/es/LC_MESSAGES/messages.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Mailu\n" -"PO-Revision-Date: 2021-03-03 12:37+0000\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Spanish \n" @@ -578,7 +578,7 @@ msgstr "Lista de dominios externos (relayed)" #: mailu/ui/templates/relay/list.html:9 msgid "New relayed domain" -msgstr "Nuevo dominio externo (relayed)" +msgstr "Editar dominio externo (relay)" #: mailu/ui/forms.py:125 msgid "Your token (write it down, as it will never be displayed again)" From 480ec29d3d8dbde9bb1ad7b7ba9fb79b630d87a9 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:03:23 +0000 Subject: [PATCH 42/74] Translated using Weblate (Italian) Currently translated at 91.4% (149 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/it/ --- core/admin/mailu/translations/it/LC_MESSAGES/messages.po | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/admin/mailu/translations/it/LC_MESSAGES/messages.po b/core/admin/mailu/translations/it/LC_MESSAGES/messages.po index 6ec219bf..9ed5e132 100644 --- a/core/admin/mailu/translations/it/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/it/LC_MESSAGES/messages.po @@ -1,7 +1,7 @@ msgid "" msgstr "" "Project-Id-Version: Mailu\n" -"PO-Revision-Date: 2021-03-03 17:03+0000\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Italian \n" @@ -576,7 +576,6 @@ msgid "Relayed domain list" msgstr "Elenco di domini affidati" #: mailu/ui/templates/relay/list.html:9 -#, fuzzy msgid "New relayed domain" msgstr "Nuovo dominio affidato" From 7a01a6338968ceba61443416f697dc78662c26bd Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 12:15:37 +0000 Subject: [PATCH 43/74] Translated using Weblate (Portuguese) Currently translated at 88.3% (144 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/pt/ --- .../mailu/translations/pt/LC_MESSAGES/messages.po | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/translations/pt/LC_MESSAGES/messages.po b/core/admin/mailu/translations/pt/LC_MESSAGES/messages.po index 58338380..f9673767 100644 --- a/core/admin/mailu/translations/pt/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/pt/LC_MESSAGES/messages.po @@ -1,11 +1,16 @@ msgid "" msgstr "" +"Project-Id-Version: Mailu\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Jaume Barber \n" +"Language-Team: Portuguese \n" +"Language: pt\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: POEditor.com\n" -"Project-Id-Version: Mailu\n" -"Language: pt\n" +"Plural-Forms: nplurals=2; plural=n > 1;\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -183,7 +188,7 @@ msgstr "Erro no docker" #: mailu/ui/templates/docker-error.html:12 msgid "An error occurred while talking to the Docker server." -msgstr "Um erro foi encontrado na conexão com o servidor Docker" +msgstr "Um erro foi encontrado na conexão com o servidor Docker." #: mailu/admin/templates/login.html:6 msgid "Your account" @@ -700,4 +705,3 @@ msgstr "Domínio" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" msgstr "Slots disponíveis" - From afae5d1c24a33f8f6652e5d23105c63b18d5d546 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 12:16:00 +0000 Subject: [PATCH 44/74] Translated using Weblate (Russian) Currently translated at 88.3% (144 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/ru/ --- core/admin/mailu/translations/ru/LC_MESSAGES/messages.po | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/translations/ru/LC_MESSAGES/messages.po b/core/admin/mailu/translations/ru/LC_MESSAGES/messages.po index 72e5f0cb..790119fc 100644 --- a/core/admin/mailu/translations/ru/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/ru/LC_MESSAGES/messages.po @@ -1,8 +1,8 @@ msgid "" msgstr "" "Project-Id-Version: Mailu\n" -"PO-Revision-Date: 2019-07-22 06:23+0000\n" -"Last-Translator: kaiyou \n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Jaume Barber \n" "Language-Team: Russian \n" "Language: ru\n" @@ -11,7 +11,7 @@ msgstr "" "Content-Transfer-Encoding: 8bit\n" "Plural-Forms: nplurals=3; plural=n%10==1 && n%100!=11 ? 0 : n%10>=2 && n%10<=" "4 && (n%100<10 || n%100>=20) ? 1 : 2;\n" -"X-Generator: Weblate 3.3\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -189,7 +189,7 @@ msgstr "Ошибка Docker" #: mailu/ui/templates/docker-error.html:12 msgid "An error occurred while talking to the Docker server." -msgstr "Произошла ошибка при обращении к серверу Docker" +msgstr "Произошла ошибка при обращении к серверу Docker." #: mailu/admin/templates/login.html:6 msgid "Your account" From cd9992f79cbc399b30e713e9bea5ed98f4371227 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 12:16:15 +0000 Subject: [PATCH 45/74] Translated using Weblate (Swedish) Currently translated at 74.2% (121 of 163 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/sv/ --- .../mailu/translations/sv/LC_MESSAGES/messages.po | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/translations/sv/LC_MESSAGES/messages.po b/core/admin/mailu/translations/sv/LC_MESSAGES/messages.po index 825888f1..071040f6 100644 --- a/core/admin/mailu/translations/sv/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/sv/LC_MESSAGES/messages.po @@ -1,11 +1,16 @@ msgid "" msgstr "" +"Project-Id-Version: Mailu\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Jaume Barber \n" +"Language-Team: Swedish \n" +"Language: sv\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=UTF-8\n" "Content-Transfer-Encoding: 8bit\n" -"X-Generator: POEditor.com\n" -"Project-Id-Version: Mailu\n" -"Language: sk\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.1\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." @@ -183,7 +188,7 @@ msgstr "Docker fel" #: mailu/ui/templates/docker-error.html:12 msgid "An error occurred while talking to the Docker server." -msgstr "Ett fel inträffade vid kommunikation med Docker" +msgstr "Ett fel inträffade vid kommunikation med Docker." #: mailu/admin/templates/login.html:6 msgid "Your account" @@ -699,4 +704,3 @@ msgstr "" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" msgstr "" - From a49b9d79744282ea3b404845a262ed8324595504 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 11:43:04 +0000 Subject: [PATCH 46/74] Translated using Weblate (Catalan) Currently translated at 99.3% (150 of 151 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/ca/ --- .../translations/ca/LC_MESSAGES/messages.po | 34 ++++++++++--------- 1 file changed, 18 insertions(+), 16 deletions(-) diff --git a/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po b/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po index 76594a3c..880709f1 100644 --- a/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/ca/LC_MESSAGES/messages.po @@ -8,7 +8,7 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: 2021-03-03 11:35+0000\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" "Last-Translator: Jaume Barber \n" "Language-Team: Catalan \n" @@ -139,7 +139,7 @@ msgstr "Nom per mostrar" #: mailu/ui/forms.py:98 msgid "Enable spam filter" -msgstr "Activeu filtre d'spam" +msgstr "Activeu filtre spam" #: mailu/ui/forms.py:99 msgid "Spam filter tolerance" @@ -204,7 +204,8 @@ msgstr "Àlies" #: mailu/ui/forms.py:138 msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" -msgstr "Feu servir sintaxi tipus SQL (ex. per a agafar tots els àlies)" +msgstr "" +"Feu servir sintaxi tipus SQL (ex. per seleccionar tots els àlies catch-all)" #: mailu/ui/forms.py:145 msgid "Admin email" @@ -246,11 +247,11 @@ msgstr "Mantén els correus al servidor" #: mailu/ui/forms.py:168 msgid "Announcement subject" -msgstr "Tema de l'avís" +msgstr "Tema de la notificació" #: mailu/ui/forms.py:170 msgid "Announcement body" -msgstr "Missatge de l'avís" +msgstr "Missatge de la notificació" #: mailu/ui/forms.py:172 msgid "Send" @@ -258,7 +259,7 @@ msgstr "Envia" #: mailu/ui/templates/announcement.html:4 msgid "Public announcement" -msgstr "Avís públic" +msgstr "Notificació pública" #: mailu/ui/templates/client.html:4 mailu/ui/templates/sidebar.html:82 msgid "Client setup" @@ -316,7 +317,7 @@ msgstr "Administració" #: mailu/ui/templates/sidebar.html:44 msgid "Announcement" -msgstr "Avís" +msgstr "Notificació" #: mailu/ui/templates/sidebar.html:49 msgid "Administrators" @@ -324,7 +325,7 @@ msgstr "Administradors" #: mailu/ui/templates/sidebar.html:54 msgid "Relayed domains" -msgstr "Dominis delegats" +msgstr "Dominis traspassats" #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 msgid "Antispam" @@ -546,18 +547,19 @@ msgid "" " expires." msgstr "" "Si no sabeu configurar un registre MX a la zona DNS,\n" -"contacteu el vostre proveïdor o administrador de DNS. Per favor, espereu \n" +"contacteu amb el vostre proveïdor o administrador de DNS. Per favor, espereu " +"\n" "uns quants minuts despres d'ajustar el registre MX perquè la " "caixet \n" "del servidor local expire." #: mailu/ui/templates/fetch/create.html:4 msgid "Add a fetched account" -msgstr "Afegiu un compte (fetched)" +msgstr "Afegiu un compte extern" #: mailu/ui/templates/fetch/edit.html:4 msgid "Update a fetched account" -msgstr "Actualitzeu un compte (fetched)" +msgstr "Actualitzeu compte extern" #: mailu/ui/templates/fetch/list.html:12 msgid "Add an account" @@ -605,11 +607,11 @@ msgstr "Editeu domini llegat (relayed)" #: mailu/ui/templates/relay/list.html:4 msgid "Relayed domain list" -msgstr "Llista de dominis llegats (relayed)" +msgstr "Llista de dominis traspassats" #: mailu/ui/templates/relay/list.html:9 msgid "New relayed domain" -msgstr "Nou domini llegat (relayed)" +msgstr "Nou domini traspassat" #: mailu/ui/templates/token/create.html:4 msgid "Create an authentication token" @@ -653,7 +655,7 @@ msgstr "Ajustos d'usuari" #: mailu/ui/templates/user/list.html:21 msgid "Features" -msgstr "Funcions" +msgstr "Característiques" #: mailu/ui/templates/user/password.html:4 msgid "Password update" @@ -669,11 +671,11 @@ msgstr "Auto-reenviament" #: mailu/ui/templates/user/signup_domain.html:8 msgid "pick a domain for the new account" -msgstr "tria un domini per al compte nou" +msgstr "trieu un domini per al compte nou" #: mailu/ui/templates/user/signup_domain.html:14 msgid "Domain" -msgstr "Domini" +msgstr "Nom de domini" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" From 5bb67dfcbb47fb0b0c43e631337676b17f9569b1 Mon Sep 17 00:00:00 2001 From: Jaume Barber Date: Wed, 3 Mar 2021 17:08:54 +0000 Subject: [PATCH 47/74] Translated using Weblate (Basque) Currently translated at 100.0% (151 of 151 strings) Translation: Mailu/admin Translate-URL: https://translate.tedomum.net/projects/mailu/admin/eu/ --- .../translations/eu/LC_MESSAGES/messages.po | 87 ++++++++++--------- 1 file changed, 45 insertions(+), 42 deletions(-) diff --git a/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po b/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po index 3a72c9af..6ca737a3 100644 --- a/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po +++ b/core/admin/mailu/translations/eu/LC_MESSAGES/messages.po @@ -8,32 +8,35 @@ msgstr "" "Project-Id-Version: PROJECT VERSION\n" "Report-Msgid-Bugs-To: EMAIL@ADDRESS\n" "POT-Creation-Date: 2018-04-22 12:10+0200\n" -"PO-Revision-Date: YEAR-MO-DA HO:MI+ZONE\n" -"Last-Translator: Automatically generated\n" -"Language-Team: none\n" +"PO-Revision-Date: 2021-03-04 18:46+0000\n" +"Last-Translator: Jaume Barber \n" +"Language-Team: Basque \n" "Language: eu\n" "MIME-Version: 1.0\n" "Content-Type: text/plain; charset=utf-8\n" "Content-Transfer-Encoding: 8bit\n" +"Plural-Forms: nplurals=2; plural=n != 1;\n" +"X-Generator: Weblate 4.0.1\n" "Generated-By: Babel 2.5.3\n" #: mailu/ui/forms.py:32 msgid "Invalid email address." -msgstr "" +msgstr "baliogabeko helbide elektronikoa." #: mailu/ui/forms.py:36 msgid "Confirm" -msgstr "" +msgstr "Ados" #: mailu/ui/forms.py:40 mailu/ui/forms.py:77 msgid "E-mail" -msgstr "" +msgstr "E-mail" #: mailu/ui/forms.py:41 mailu/ui/forms.py:78 mailu/ui/forms.py:90 #: mailu/ui/forms.py:109 mailu/ui/forms.py:162 #: mailu/ui/templates/client.html:32 mailu/ui/templates/client.html:59 msgid "Password" -msgstr "" +msgstr "Pasahitza" #: mailu/ui/forms.py:42 mailu/ui/templates/login.html:4 #: mailu/ui/templates/sidebar.html:111 @@ -48,7 +51,7 @@ msgstr "" #: mailu/ui/forms.py:47 msgid "Maximum user count" -msgstr "" +msgstr "Erabiltzaileen gehieneko kopurua" #: mailu/ui/forms.py:48 msgid "Maximum alias count" @@ -56,11 +59,11 @@ msgstr "" #: mailu/ui/forms.py:49 msgid "Maximum user quota" -msgstr "" +msgstr "Erabiltzaile bakoitzeko gehieneko espazioa" #: mailu/ui/forms.py:50 msgid "Enable sign-up" -msgstr "" +msgstr "Gaitu erregistroa" #: mailu/ui/forms.py:51 mailu/ui/forms.py:72 mailu/ui/forms.py:83 #: mailu/ui/forms.py:128 mailu/ui/forms.py:140 @@ -68,57 +71,57 @@ msgstr "" #: mailu/ui/templates/relay/list.html:19 mailu/ui/templates/token/list.html:19 #: mailu/ui/templates/user/list.html:23 msgid "Comment" -msgstr "" +msgstr "Iruzkindua" #: mailu/ui/forms.py:52 mailu/ui/forms.py:61 mailu/ui/forms.py:66 #: mailu/ui/forms.py:73 mailu/ui/forms.py:132 mailu/ui/forms.py:141 msgid "Create" -msgstr "" +msgstr "Sortu" #: mailu/ui/forms.py:57 msgid "Initial admin" -msgstr "" +msgstr "Administratzailea" #: mailu/ui/forms.py:58 msgid "Admin password" -msgstr "" +msgstr "Administratzaileko pasahitza" #: mailu/ui/forms.py:59 mailu/ui/forms.py:79 mailu/ui/forms.py:91 msgid "Confirm password" -msgstr "" +msgstr "Berretsi pasahitza" #: mailu/ui/forms.py:65 msgid "Alternative name" -msgstr "" +msgstr "Izen alternatiboa" #: mailu/ui/forms.py:70 msgid "Relayed domain name" -msgstr "" +msgstr "Igorritako domeinu izena" #: mailu/ui/forms.py:71 mailu/ui/templates/relay/list.html:18 msgid "Remote host" -msgstr "" +msgstr "Urruneko ostalaria" #: mailu/ui/forms.py:80 mailu/ui/templates/user/list.html:22 #: mailu/ui/templates/user/signup_domain.html:16 msgid "Quota" -msgstr "" +msgstr "Espazioa" #: mailu/ui/forms.py:81 msgid "Allow IMAP access" -msgstr "" +msgstr "Baimendu IMAP sarbidea" #: mailu/ui/forms.py:82 msgid "Allow POP3 access" -msgstr "" +msgstr "Baimendu POP3 sarbidea" #: mailu/ui/forms.py:84 msgid "Enabled" -msgstr "" +msgstr "Gaituta" #: mailu/ui/forms.py:85 msgid "Save" -msgstr "" +msgstr "Gorde" #: mailu/ui/forms.py:89 msgid "Email address" @@ -128,7 +131,7 @@ msgstr "" #: mailu/ui/templates/user/signup.html:4 #: mailu/ui/templates/user/signup_domain.html:4 msgid "Sign up" -msgstr "" +msgstr "Erregistratu" #: mailu/ui/forms.py:97 msgid "Displayed name" @@ -136,15 +139,15 @@ msgstr "" #: mailu/ui/forms.py:98 msgid "Enable spam filter" -msgstr "" +msgstr "Gaitu spam iragazkia" #: mailu/ui/forms.py:99 msgid "Spam filter tolerance" -msgstr "" +msgstr "Spam iragazkiaren tolerantzia" #: mailu/ui/forms.py:100 msgid "Enable forwarding" -msgstr "" +msgstr "Gaitu birbidaltzea" #: mailu/ui/forms.py:101 msgid "Keep a copy of the emails" @@ -157,7 +160,7 @@ msgstr "" #: mailu/ui/forms.py:105 msgid "Save settings" -msgstr "" +msgstr "Gorde ezarpenak" #: mailu/ui/forms.py:110 msgid "Password check" @@ -181,11 +184,11 @@ msgstr "" #: mailu/ui/forms.py:119 msgid "End of vacation" -msgstr "" +msgstr "Oporren amaiera" #: mailu/ui/forms.py:120 msgid "Update" -msgstr "" +msgstr "Eguneratu" #: mailu/ui/forms.py:125 msgid "Your token (write it down, as it will never be displayed again)" @@ -193,11 +196,11 @@ msgstr "" #: mailu/ui/forms.py:130 mailu/ui/templates/token/list.html:20 msgid "Authorized IP" -msgstr "" +msgstr "Baimendutako IP" #: mailu/ui/forms.py:136 msgid "Alias" -msgstr "" +msgstr "Ezizenza" #: mailu/ui/forms.py:138 msgid "Use SQL LIKE Syntax (e.g. for catch-all aliases)" @@ -226,7 +229,7 @@ msgstr "" #: mailu/ui/forms.py:159 mailu/ui/templates/client.html:20 #: mailu/ui/templates/client.html:47 msgid "TCP port" -msgstr "" +msgstr "TCP ataka" #: mailu/ui/forms.py:160 msgid "Enable TLS" @@ -276,11 +279,11 @@ msgstr "" #: mailu/ui/templates/confirm.html:13 #, python-format msgid "You are about to %(action)s. Please confirm your action." -msgstr "" +msgstr "Zu zara %(action)s-etan. Mesedez ekintza honen berretsi." #: mailu/ui/templates/docker-error.html:4 msgid "Docker error" -msgstr "" +msgstr "Docker-en errorea" #: mailu/ui/templates/docker-error.html:12 msgid "An error occurred while talking to the Docker server." @@ -321,11 +324,11 @@ msgstr "" #: mailu/ui/templates/sidebar.html:54 msgid "Relayed domains" -msgstr "" +msgstr "Igorritako domeinuak" #: mailu/ui/templates/sidebar.html:59 mailu/ui/templates/user/settings.html:15 msgid "Antispam" -msgstr "" +msgstr "Antispam" #: mailu/ui/templates/sidebar.html:66 msgid "Mail domains" @@ -586,19 +589,19 @@ msgstr "" #: mailu/ui/templates/relay/create.html:4 msgid "New relay domain" -msgstr "" +msgstr "Igorritako domeinu berria" #: mailu/ui/templates/relay/edit.html:4 msgid "Edit relayd domain" -msgstr "" +msgstr "Editatu igorritako domeinua" #: mailu/ui/templates/relay/list.html:4 msgid "Relayed domain list" -msgstr "" +msgstr "Igorritako domeinuen zerrenda" #: mailu/ui/templates/relay/list.html:9 msgid "New relayed domain" -msgstr "" +msgstr "Igorritako domeinu berria" #: mailu/ui/templates/token/create.html:4 msgid "Create an authentication token" @@ -662,7 +665,7 @@ msgstr "" #: mailu/ui/templates/user/signup_domain.html:14 msgid "Domain" -msgstr "" +msgstr "Domeinu izena" #: mailu/ui/templates/user/signup_domain.html:15 msgid "Available slots" From 0dcc059cd6950422588a694c3727a443cf56feab Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Fri, 5 Mar 2021 22:26:46 +0100 Subject: [PATCH 48/74] Add a new knob as discussed on matrix with lub --- core/admin/mailu/configuration.py | 2 +- docs/configuration.rst | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 982a1eb0..dac913fa 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -54,6 +54,7 @@ DEFAULT_CONFIG = { # Advanced settings 'PASSWORD_SCHEME': 'PBKDF2', 'LOG_LEVEL': 'WARNING', + 'SESSION_COOKIE_SECURE': True, # Host settings 'HOST_IMAP': 'imap', 'HOST_LMTP': 'imap:2525', @@ -125,7 +126,6 @@ class ConfigManager(dict): self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS']) self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' self.config['SESSION_COOKIE_HTTPONLY'] = True - self.config['SESSION_COOKIE_SECURE'] = self.config['TLS_FLAVOR'] != 'notls' # update the app config itself app.config = self diff --git a/docs/configuration.rst b/docs/configuration.rst index 5ff3546a..9123054c 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -142,6 +142,8 @@ The ``PASSWORD_SCHEME`` is the password encryption scheme. You should use the default value, unless you are importing password from a separate system and want to keep using the old password encryption scheme. +The ``SESSION_COOKIE_SECURE`` (default: True) setting controls the secure flag on the cookies of the administrative interface. It should only be turned off if you intend to access it over plain HTTP. + The ``LOG_LEVEL`` setting is used by the python start-up scripts as a logging threshold. Log messages equal or higher than this priority will be printed. Can be one of: CRITICAL, ERROR, WARNING, INFO, DEBUG or NOTSET. From 58b2cdc4288854481e8914b3a1b4318708906e15 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 21 Jan 2021 20:01:57 +0100 Subject: [PATCH 49/74] Don't do more work than necessary --- core/admin/mailu/internal/nginx.py | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index 1e0b16c2..de4248fa 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -49,11 +49,14 @@ def handle_authentication(headers): user = models.User.query.get(user_email) status = False if user: - for token in user.tokens: - if (token.check_password(password) and - (not token.ip or token.ip == ip)): - status = True - if user.check_password(password): + # All tokens are 32 characters hex lowercase + if len(password) == 32: + for token in user.tokens: + if (token.check_password(password) and + (not token.ip or token.ip == ip)): + status = True + break + if not status and user.check_password(password): status = True if status: if protocol == "imap" and not user.enable_imap: From eb7895bd1cf5ae41ccfda384f06480767ed75172 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 7 Feb 2021 17:08:52 +0100 Subject: [PATCH 50/74] Don't do more work than necessary (/webdav) This is also fixing tokens on /webdav/ --- core/admin/mailu/internal/views/auth.py | 20 ++++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/core/admin/mailu/internal/views/auth.py b/core/admin/mailu/internal/views/auth.py index 825dba56..26d57b3d 100644 --- a/core/admin/mailu/internal/views/auth.py +++ b/core/admin/mailu/internal/views/auth.py @@ -53,10 +53,22 @@ def basic_authentication(): encoded = authorization.replace("Basic ", "") user_email, password = base64.b64decode(encoded).split(b":") user = models.User.query.get(user_email.decode("utf8")) - if user and user.enabled and user.check_password(password.decode("utf8")): - response = flask.Response() - response.headers["X-User"] = user.email - return response + if user and user.enabled: + password = password.decode('utf-8') + status = False + # All tokens are 32 characters hex lowercase + if len(password) == 32: + for token in user.tokens: + if (token.check_password(password) and + (not token.ip or token.ip == ip)): + status = True + break + if not status and user.check_password(password): + status = True + if status: + response = flask.Response() + response.headers["X-User"] = user.email + return response response = flask.Response(status=401) response.headers["WWW-Authenticate"] = 'Basic realm="Login Required"' return response From 00b001f76b7818f2561b9212fbe22edad113a970 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 21 Jan 2021 20:37:25 +0100 Subject: [PATCH 51/74] Improve the token storage format shortcomings of the previous format included: - 1000x slower than it should be (no point in adding rounds since there is enough entropy: they are not bruteforceable) - vulnerable to DoS as explained in https://passlib.readthedocs.io/en/stable/lib/passlib.hash.sha256_crypt.html#security-issues --- core/admin/mailu/models.py | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index bbc00f2d..164312ad 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -493,10 +493,18 @@ class Token(Base): ip = db.Column(db.String(255)) def check_password(self, password): - return hash.sha256_crypt.verify(password, self.password) + if self.password.startswith("$5$"): + if hash.sha256_crypt.verify(password, self.password): + self.set_password(password) + db.session.add(self) + db.session.commit() + return True + return False + return hash.pbkdf2_sha256.verify(password, self.password) def set_password(self, password): - self.password = hash.sha256_crypt.using(rounds=1000).hash(password) + # tokens have 128bits of entropy, they are not bruteforceable + self.password = hash.pbkdf2_sha256.using(rounds=1).hash(password) def __str__(self): return self.comment From 7137ba6ff18c87185e25b9913377d8e7ce3fa8b6 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 2 Feb 2021 20:10:18 +0100 Subject: [PATCH 52/74] Misc improvements to PASSWORD_SCHEME - remove PASSWORD_SCHEME altogether - introduce CREDENTIAL_ROUNDS - migrate all old hashes to the current format - auto-detect/enable all hash types that passlib supports - upgrade passlib to 1.7.4 (see #1706: ldap_salted_sha512 support) --- core/admin/mailu/configuration.py | 2 +- core/admin/mailu/manage.py | 24 +++++++-------------- core/admin/mailu/models.py | 35 ++++++++++++++++++++----------- core/admin/requirements-prod.txt | 2 +- docs/cli.rst | 1 - docs/compose/.env | 5 ++--- docs/configuration.rst | 4 +--- 7 files changed, 35 insertions(+), 38 deletions(-) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 3d4d8668..cdee1084 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -33,6 +33,7 @@ DEFAULT_CONFIG = { 'TLS_FLAVOR': 'cert', 'AUTH_RATELIMIT': '10/minute;1000/hour', 'AUTH_RATELIMIT_SUBNET': True, + 'CREDENTIAL_ROUNDS': 12, 'DISABLE_STATISTICS': False, # Mail settings 'DMARC_RUA': None, @@ -52,7 +53,6 @@ DEFAULT_CONFIG = { 'RECAPTCHA_PUBLIC_KEY': '', 'RECAPTCHA_PRIVATE_KEY': '', # Advanced settings - 'PASSWORD_SCHEME': 'PBKDF2', 'LOG_LEVEL': 'WARNING', 'SESSION_COOKIE_SECURE': True, # Host settings diff --git a/core/admin/mailu/manage.py b/core/admin/mailu/manage.py index 62f214d3..9c576404 100644 --- a/core/admin/mailu/manage.py +++ b/core/admin/mailu/manage.py @@ -86,13 +86,10 @@ def admin(localpart, domain_name, password, mode='create'): @click.argument('localpart') @click.argument('domain_name') @click.argument('password') -@click.argument('hash_scheme', required=False) @flask_cli.with_appcontext -def user(localpart, domain_name, password, hash_scheme=None): +def user(localpart, domain_name, password): """ Create a user """ - if hash_scheme is None: - hash_scheme = app.config['PASSWORD_SCHEME'] domain = models.Domain.query.get(domain_name) if not domain: domain = models.Domain(name=domain_name) @@ -102,7 +99,7 @@ def user(localpart, domain_name, password, hash_scheme=None): domain=domain, global_admin=False ) - user.set_password(password, hash_scheme=hash_scheme) + user.set_password(password) db.session.add(user) db.session.commit() @@ -111,17 +108,14 @@ def user(localpart, domain_name, password, hash_scheme=None): @click.argument('localpart') @click.argument('domain_name') @click.argument('password') -@click.argument('hash_scheme', required=False) @flask_cli.with_appcontext -def password(localpart, domain_name, password, hash_scheme=None): +def password(localpart, domain_name, password): """ Change the password of an user """ email = '{0}@{1}'.format(localpart, domain_name) user = models.User.query.get(email) - if hash_scheme is None: - hash_scheme = app.config['PASSWORD_SCHEME'] if user: - user.set_password(password, hash_scheme=hash_scheme) + user.set_password(password) else: print("User " + email + " not found.") db.session.commit() @@ -148,13 +142,10 @@ def domain(domain_name, max_users=-1, max_aliases=-1, max_quota_bytes=0): @click.argument('localpart') @click.argument('domain_name') @click.argument('password_hash') -@click.argument('hash_scheme') @flask_cli.with_appcontext -def user_import(localpart, domain_name, password_hash, hash_scheme = None): +def user_import(localpart, domain_name, password_hash): """ Import a user along with password hash. """ - if hash_scheme is None: - hash_scheme = app.config['PASSWORD_SCHEME'] domain = models.Domain.query.get(domain_name) if not domain: domain = models.Domain(name=domain_name) @@ -164,7 +155,7 @@ def user_import(localpart, domain_name, password_hash, hash_scheme = None): domain=domain, global_admin=False ) - user.set_password(password_hash, hash_scheme=hash_scheme, raw=True) + user.set_password(password_hash, raw=True) db.session.add(user) db.session.commit() @@ -217,7 +208,6 @@ def config_update(verbose=False, delete_objects=False): localpart = user_config['localpart'] domain_name = user_config['domain'] password_hash = user_config.get('password_hash', None) - hash_scheme = user_config.get('hash_scheme', None) domain = models.Domain.query.get(domain_name) email = '{0}@{1}'.format(localpart, domain_name) optional_params = {} @@ -239,7 +229,7 @@ def config_update(verbose=False, delete_objects=False): else: for k in optional_params: setattr(user, k, optional_params[k]) - user.set_password(password_hash, hash_scheme=hash_scheme, raw=True) + user.set_password(password_hash, raw=True) db.session.add(user) aliases = new_config.get('aliases', []) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 164312ad..905af4a2 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -1,7 +1,7 @@ from mailu import dkim from sqlalchemy.ext import declarative -from passlib import context, hash +from passlib import context, hash, registry from datetime import datetime, date from email.mime import text from flask import current_app as app @@ -370,17 +370,30 @@ class User(Base, Email): 'CRYPT': "des_crypt"} def get_password_context(self): + schemes = registry.list_crypt_handlers() + # scrypt throws a warning if the native wheels aren't found + schemes.remove('scrypt') + # we can't leave plaintext schemes as they will be misidentified + for scheme in schemes: + if scheme.endswith('plaintext'): + schemes.remove(scheme) return context.CryptContext( - schemes=self.scheme_dict.values(), - default=self.scheme_dict[app.config['PASSWORD_SCHEME']], + schemes=schemes, + default='bcrypt_sha256', + bcrypt_sha256__rounds=app.config['CREDENTIAL_ROUNDS'], + deprecated='auto' ) def check_password(self, password): context = self.get_password_context() - reference = re.match('({[^}]+})?(.*)', self.password).group(2) - result = context.verify(password, reference) - if result and context.identify(reference) != context.default_scheme(): - self.set_password(password) + # {scheme} will most likely be migrated on first use + reference = self.password + if self.password.startswith("{"): + reference = re.match('({[^}]+})?(.*)', reference).group(2) + + result, new_hash = context.verify_and_update(password, reference) + if new_hash: + self.password = new_hash db.session.add(self) db.session.commit() return result @@ -389,13 +402,11 @@ class User(Base, Email): """Set password for user with specified encryption scheme @password: plain text password to encrypt (if raw == True the hash itself) """ - if hash_scheme is None: - hash_scheme = app.config['PASSWORD_SCHEME'] - # for the list of hash schemes see https://wiki2.dovecot.org/Authentication/PasswordSchemes if raw: - self.password = '{'+hash_scheme+'}' + password + self.password = password else: - self.password = '{'+hash_scheme+'}' + self.get_password_context().encrypt(password, self.scheme_dict[hash_scheme]) + self.password = self.get_password_context().hash(password) + app.cache.delete(self.get_id()) def get_managed_domains(self): if self.global_admin: diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index a3c32855..f767f431 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -29,7 +29,7 @@ limits==1.3 Mako==1.0.9 MarkupSafe==1.1.1 mysqlclient==1.4.2.post1 -passlib==1.7.1 +passlib==1.7.4 psycopg2==2.8.2 pycparser==2.19 pyOpenSSL==19.0.0 diff --git a/docs/cli.rst b/docs/cli.rst index a9cff41c..8e94026b 100644 --- a/docs/cli.rst +++ b/docs/cli.rst @@ -85,7 +85,6 @@ where mail-config.yml looks like: - localpart: foo domain: example.com password_hash: klkjhumnzxcjkajahsdqweqqwr - hash_scheme: MD5-CRYPT aliases: - localpart: alias1 diff --git a/docs/compose/.env b/docs/compose/.env index 7f91c270..432b20b0 100644 --- a/docs/compose/.env +++ b/docs/compose/.env @@ -144,9 +144,8 @@ LOG_DRIVER=json-file # Docker-compose project name, this will prepended to containers names. COMPOSE_PROJECT_NAME=mailu -# Default password scheme used for newly created accounts and changed passwords -# (value: PBKDF2, BLF-CRYPT, SHA512-CRYPT, SHA256-CRYPT) -PASSWORD_SCHEME=PBKDF2 +# Number of rounds used by the password hashing scheme +CREDENTIAL_ROUNDS=12 # Header to take the real ip from REAL_IP_HEADER= diff --git a/docs/configuration.rst b/docs/configuration.rst index 9123054c..bc2027c6 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -138,9 +138,7 @@ Depending on your particular deployment you most probably will want to change th Advanced settings ----------------- -The ``PASSWORD_SCHEME`` is the password encryption scheme. You should use the -default value, unless you are importing password from a separate system and -want to keep using the old password encryption scheme. +The ``CREDENTIAL_ROUNDS`` (default: 12) is the number of rounds used by the password hashing scheme. You should use the default value. The ``SESSION_COOKIE_SECURE`` (default: True) setting controls the secure flag on the cookies of the administrative interface. It should only be turned off if you intend to access it over plain HTTP. From 57a6abaf50400802be5da48913c75cff00dce6f4 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 7 Feb 2021 09:31:07 +0100 Subject: [PATCH 53/74] Remove {scheme} from the DB if mailu has set it --- core/admin/mailu/models.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 905af4a2..9ab9088e 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -386,10 +386,14 @@ class User(Base, Email): def check_password(self, password): context = self.get_password_context() - # {scheme} will most likely be migrated on first use reference = self.password + # strip {scheme} if that's something mailu has added + # passlib will identify *crypt based hashes just fine + # on its own if self.password.startswith("{"): - reference = re.match('({[^}]+})?(.*)', reference).group(2) + scheme = self.password.split('}')[0][1:] + if scheme in scheme_dict: + reference = reference[len(scheme)+2:] result, new_hash = context.verify_and_update(password, reference) if new_hash: From 927bd2bd8ec8051e93609d3e8fd24706cc8dc8a2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 7 Feb 2021 17:29:58 +0100 Subject: [PATCH 54/74] towncrier --- towncrier/newsfragments/1194.misc | 1 + towncrier/newsfragments/1662.feature | 1 + 2 files changed, 2 insertions(+) create mode 100644 towncrier/newsfragments/1194.misc create mode 100644 towncrier/newsfragments/1662.feature diff --git a/towncrier/newsfragments/1194.misc b/towncrier/newsfragments/1194.misc new file mode 100644 index 00000000..7cbf2b94 --- /dev/null +++ b/towncrier/newsfragments/1194.misc @@ -0,0 +1 @@ +Switch to bcrypt_sha256, remove PASSWORD_SCHEME and replace it with CREDENTIAL_ROUNDS diff --git a/towncrier/newsfragments/1662.feature b/towncrier/newsfragments/1662.feature new file mode 100644 index 00000000..4fc8b2fd --- /dev/null +++ b/towncrier/newsfragments/1662.feature @@ -0,0 +1 @@ +Enable support of all hash types passlib supports. Convert them to the default scheme on first use. From fda758e2b4ea19751369dd122797c5210e18dc15 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sun, 7 Feb 2021 17:34:22 +0100 Subject: [PATCH 55/74] remove merge artifact --- core/admin/mailu/models.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index 9ab9088e..b7a4d501 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -392,7 +392,7 @@ class User(Base, Email): # on its own if self.password.startswith("{"): scheme = self.password.split('}')[0][1:] - if scheme in scheme_dict: + if scheme in self.scheme_dict: reference = reference[len(scheme)+2:] result, new_hash = context.verify_and_update(password, reference) @@ -410,7 +410,6 @@ class User(Base, Email): self.password = password else: self.password = self.get_password_context().hash(password) - app.cache.delete(self.get_id()) def get_managed_domains(self): if self.global_admin: From 89d88e0c19476692abef0b0b13c4765f2db7bacb Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 8 Feb 2021 08:50:32 +0100 Subject: [PATCH 56/74] Fix the test --- tests/compose/core/00_create_users.sh | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/compose/core/00_create_users.sh b/tests/compose/core/00_create_users.sh index 49d0511b..f5108302 100755 --- a/tests/compose/core/00_create_users.sh +++ b/tests/compose/core/00_create_users.sh @@ -6,6 +6,6 @@ echo "The above error was intended!" docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'FooBar' --mode=ifmissing || exit 1 # Should not fail and update the password; update mode docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu admin admin mailu.io 'password' --mode=update || exit 1 -docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user user mailu.io 'password' 'SHA512-CRYPT' || exit 1 -docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user 'user/with/slash' mailu.io 'password' 'SHA512-CRYPT' || exit 1 +docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user user mailu.io 'password' || exit 1 +docker-compose -f tests/compose/core/docker-compose.yml exec -T admin flask mailu user 'user/with/slash' mailu.io 'password' || exit 1 echo "User testing succesfull!" From 29306d5abbd17ebd9b479d9438ccfa5cc00a3de6 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 8 Feb 2021 08:56:03 +0100 Subject: [PATCH 57/74] Fix the tests (again) --- tests/compose/core/02_forward_test.sh | 2 -- tests/compose/core/04_reply_test.sh | 2 -- 2 files changed, 4 deletions(-) diff --git a/tests/compose/core/02_forward_test.sh b/tests/compose/core/02_forward_test.sh index 595820cf..a53fa459 100755 --- a/tests/compose/core/02_forward_test.sh +++ b/tests/compose/core/02_forward_test.sh @@ -2,7 +2,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm users: - localpart: forwardinguser password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" - hash_scheme: MD5-CRYPT domain: mailu.io forward_enabled: true forward_destination: ["user@mailu.io"] @@ -14,7 +13,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm users: - localpart: forwardinguser password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" - hash_scheme: MD5-CRYPT domain: mailu.io forward_enabled: false forward_destination: [] diff --git a/tests/compose/core/04_reply_test.sh b/tests/compose/core/04_reply_test.sh index 83c114f6..e1479cf0 100755 --- a/tests/compose/core/04_reply_test.sh +++ b/tests/compose/core/04_reply_test.sh @@ -2,7 +2,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm users: - localpart: replyuser password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" - hash_scheme: MD5-CRYPT domain: mailu.io reply_enabled: true reply_subject: This will not reach me @@ -15,7 +14,6 @@ cat << EOF | docker-compose -f tests/compose/core/docker-compose.yml exec -T adm users: - localpart: replyuser password_hash: "\$1\$F2OStvi1\$Q8hBIHkdJpJkJn/TrMIZ9/" - hash_scheme: MD5-CRYPT domain: mailu.io reply_enabled: false EOF From d0b34f8e240a1049ed5e1ccd3399af3ff18236e2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 08:56:06 +0100 Subject: [PATCH 58/74] Move CREDENTIAL_ROUNDS to advanced settings --- core/admin/mailu/configuration.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index cdee1084..429e778c 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -33,7 +33,6 @@ DEFAULT_CONFIG = { 'TLS_FLAVOR': 'cert', 'AUTH_RATELIMIT': '10/minute;1000/hour', 'AUTH_RATELIMIT_SUBNET': True, - 'CREDENTIAL_ROUNDS': 12, 'DISABLE_STATISTICS': False, # Mail settings 'DMARC_RUA': None, @@ -55,6 +54,7 @@ DEFAULT_CONFIG = { # Advanced settings 'LOG_LEVEL': 'WARNING', 'SESSION_COOKIE_SECURE': True, + 'CREDENTIAL_ROUNDS': 12, # Host settings 'HOST_IMAP': 'imap', 'HOST_LMTP': 'imap:2525', From f9ed517b394e3d267fcae8f960e2299df9bb389f Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 09:02:09 +0100 Subject: [PATCH 59/74] Be specific token length --- core/admin/mailu/ui/views/tokens.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/ui/views/tokens.py b/core/admin/mailu/ui/views/tokens.py index 069587e1..820dd405 100644 --- a/core/admin/mailu/ui/views/tokens.py +++ b/core/admin/mailu/ui/views/tokens.py @@ -26,7 +26,7 @@ def token_create(user_email): form = forms.TokenForm() wtforms_components.read_only(form.displayed_password) if not form.raw_password.data: - form.raw_password.data = pwd.genword(entropy=128, charset="hex") + form.raw_password.data = pwd.genword(entropy=128, length=32, charset="hex") form.displayed_password.data = form.raw_password.data if form.validate_on_submit(): token = models.Token(user=user) From df230cb482777e0b3c06e26174af203b5f3070b7 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 09:20:02 +0100 Subject: [PATCH 60/74] Refactor auth under nginx.check_credentials() --- core/admin/mailu/internal/nginx.py | 32 ++++++++++++------------- core/admin/mailu/internal/views/auth.py | 20 ++++------------ 2 files changed, 19 insertions(+), 33 deletions(-) diff --git a/core/admin/mailu/internal/nginx.py b/core/admin/mailu/internal/nginx.py index de4248fa..f9ebbf13 100644 --- a/core/admin/mailu/internal/nginx.py +++ b/core/admin/mailu/internal/nginx.py @@ -19,6 +19,20 @@ STATUSES = { }), } +def check_credentials(user, password, ip, protocol=None): + if not user or not user.enabled or (protocol == "imap" and not user.enable_imap) or (protocol == "pop3" and not user.enable_pop): + return False + is_ok = False + # All tokens are 32 characters hex lowercase + if len(password) == 32: + for token in user.tokens: + if (token.check_password(password) and + (not token.ip or token.ip == ip)): + is_ok = True + break + if not is_ok and user.check_password(password): + is_ok = True + return is_ok def handle_authentication(headers): """ Handle an HTTP nginx authentication request @@ -47,23 +61,7 @@ def handle_authentication(headers): password = raw_password.encode("iso8859-1").decode("utf8") ip = urllib.parse.unquote(headers["Client-Ip"]) user = models.User.query.get(user_email) - status = False - if user: - # All tokens are 32 characters hex lowercase - if len(password) == 32: - for token in user.tokens: - if (token.check_password(password) and - (not token.ip or token.ip == ip)): - status = True - break - if not status and user.check_password(password): - status = True - if status: - if protocol == "imap" and not user.enable_imap: - status = False - elif protocol == "pop3" and not user.enable_pop: - status = False - if status and user.enabled: + if check_credentials(user, password, ip, protocol): return { "Auth-Status": "OK", "Auth-Server": server, diff --git a/core/admin/mailu/internal/views/auth.py b/core/admin/mailu/internal/views/auth.py index 26d57b3d..edd62e37 100644 --- a/core/admin/mailu/internal/views/auth.py +++ b/core/admin/mailu/internal/views/auth.py @@ -53,22 +53,10 @@ def basic_authentication(): encoded = authorization.replace("Basic ", "") user_email, password = base64.b64decode(encoded).split(b":") user = models.User.query.get(user_email.decode("utf8")) - if user and user.enabled: - password = password.decode('utf-8') - status = False - # All tokens are 32 characters hex lowercase - if len(password) == 32: - for token in user.tokens: - if (token.check_password(password) and - (not token.ip or token.ip == ip)): - status = True - break - if not status and user.check_password(password): - status = True - if status: - response = flask.Response() - response.headers["X-User"] = user.email - return response + if nginx.check_credentials(user, password.decode('utf-8'), flask.request.remote_addr, "web"): + response = flask.Response() + response.headers["X-User"] = user.email + return response response = flask.Response(status=401) response.headers["WWW-Authenticate"] = 'Basic realm="Login Required"' return response From 20d2b621aa42793eedb55219c01da3b9b8ee32f2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 09:33:37 +0100 Subject: [PATCH 61/74] Improve the description of CREDENTIAL_ROUNDS --- docs/configuration.rst | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/configuration.rst b/docs/configuration.rst index bc2027c6..26bdb024 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -138,7 +138,7 @@ Depending on your particular deployment you most probably will want to change th Advanced settings ----------------- -The ``CREDENTIAL_ROUNDS`` (default: 12) is the number of rounds used by the password hashing scheme. You should use the default value. +The ``CREDENTIAL_ROUNDS`` (default: 12) setting is the number of rounds used by the password hashing scheme. The number of rounds can be reduced in case faster authentication is needed or increased when additional protection is desired. Keep in mind that this is a mitigation against offline attacks on password hashes, aiming to prevent credential stuffing (due to password re-use) on other systems. The ``SESSION_COOKIE_SECURE`` (default: True) setting controls the secure flag on the cookies of the administrative interface. It should only be turned off if you intend to access it over plain HTTP. From 45e5cb9bb37b49f294c973b98ed9cf8f0607498b Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 09:37:13 +0100 Subject: [PATCH 62/74] Improve the towncrier messages --- towncrier/newsfragments/1194.misc | 1 - towncrier/newsfragments/1662.feature | 2 +- towncrier/newsfragments/1753.feature | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) delete mode 100644 towncrier/newsfragments/1194.misc create mode 100644 towncrier/newsfragments/1753.feature diff --git a/towncrier/newsfragments/1194.misc b/towncrier/newsfragments/1194.misc deleted file mode 100644 index 7cbf2b94..00000000 --- a/towncrier/newsfragments/1194.misc +++ /dev/null @@ -1 +0,0 @@ -Switch to bcrypt_sha256, remove PASSWORD_SCHEME and replace it with CREDENTIAL_ROUNDS diff --git a/towncrier/newsfragments/1662.feature b/towncrier/newsfragments/1662.feature index 4fc8b2fd..f8219757 100644 --- a/towncrier/newsfragments/1662.feature +++ b/towncrier/newsfragments/1662.feature @@ -1 +1 @@ -Enable support of all hash types passlib supports. Convert them to the default scheme on first use. +Enable support of all hash types passlib supports. diff --git a/towncrier/newsfragments/1753.feature b/towncrier/newsfragments/1753.feature new file mode 100644 index 00000000..09eb834a --- /dev/null +++ b/towncrier/newsfragments/1753.feature @@ -0,0 +1 @@ +Switch to bcrypt_sha256, replace PASSWORD_SCHEME with CREDENTIAL_ROUNDS and dynamically update existing hashes on first login From 1c5b58cba4da0b411aa4cd6bb911196e8a0fbf25 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 11:19:28 +0100 Subject: [PATCH 63/74] Remove scheme_dict --- core/admin/mailu/models.py | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index b7a4d501..fab2103a 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -362,13 +362,6 @@ class User(Base, Email): self.reply_enddate > now ) - scheme_dict = {'PBKDF2': "pbkdf2_sha512", - 'BLF-CRYPT': "bcrypt", - 'SHA512-CRYPT': "sha512_crypt", - 'SHA256-CRYPT': "sha256_crypt", - 'MD5-CRYPT': "md5_crypt", - 'CRYPT': "des_crypt"} - def get_password_context(self): schemes = registry.list_crypt_handlers() # scrypt throws a warning if the native wheels aren't found @@ -392,7 +385,7 @@ class User(Base, Email): # on its own if self.password.startswith("{"): scheme = self.password.split('}')[0][1:] - if scheme in self.scheme_dict: + if scheme in ['PBKDF2', 'BLF-CRYPT', 'SHA512-CRYPT', 'SHA256-CRYPT', 'MD5-CRYPT', 'CRYPT']: reference = reference[len(scheme)+2:] result, new_hash = context.verify_and_update(password, reference) From 5f05fee8b32209d4888de324cc3e3a578ff83715 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Feb 2021 11:23:49 +0100 Subject: [PATCH 64/74] Don't need regexps anymore --- core/admin/mailu/models.py | 1 - 1 file changed, 1 deletion(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index fab2103a..c8426fa2 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -8,7 +8,6 @@ from flask import current_app as app import flask_sqlalchemy import sqlalchemy -import re import time import os import glob From 96ae54d04db3ff26edf8413e99dc980d610562a8 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Thu, 11 Feb 2021 23:14:09 +0100 Subject: [PATCH 65/74] CryptContext should be a singleton --- core/admin/mailu/models.py | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index c8426fa2..a63c33a5 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -304,6 +304,7 @@ class User(Base, Email): """ A user is an email address that has a password to access a mailbox. """ __tablename__ = "user" + _ctx = None domain = db.relationship(Domain, backref=db.backref('users', cascade='all, delete-orphan')) @@ -361,7 +362,10 @@ class User(Base, Email): self.reply_enddate > now ) - def get_password_context(self): + def get_password_context(): + if User._ctx: + return User._ctx + schemes = registry.list_crypt_handlers() # scrypt throws a warning if the native wheels aren't found schemes.remove('scrypt') @@ -369,15 +373,15 @@ class User(Base, Email): for scheme in schemes: if scheme.endswith('plaintext'): schemes.remove(scheme) - return context.CryptContext( + User._ctx = context.CryptContext( schemes=schemes, default='bcrypt_sha256', bcrypt_sha256__rounds=app.config['CREDENTIAL_ROUNDS'], deprecated='auto' ) + return User._ctx def check_password(self, password): - context = self.get_password_context() reference = self.password # strip {scheme} if that's something mailu has added # passlib will identify *crypt based hashes just fine @@ -387,7 +391,7 @@ class User(Base, Email): if scheme in ['PBKDF2', 'BLF-CRYPT', 'SHA512-CRYPT', 'SHA256-CRYPT', 'MD5-CRYPT', 'CRYPT']: reference = reference[len(scheme)+2:] - result, new_hash = context.verify_and_update(password, reference) + result, new_hash = User.get_password_context().verify_and_update(password, reference) if new_hash: self.password = new_hash db.session.add(self) @@ -401,7 +405,7 @@ class User(Base, Email): if raw: self.password = password else: - self.password = self.get_password_context().hash(password) + self.password = User.get_password_context().hash(password) def get_managed_domains(self): if self.global_admin: From 22af5b8432b1f229d8a4a29e5ee46b1fe0c62bba Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Sat, 20 Feb 2021 19:10:20 +0100 Subject: [PATCH 66/74] Switch to server-side sessions in redis --- core/admin/mailu/__init__.py | 4 ++++ core/admin/requirements-prod.txt | 1 + core/admin/requirements.txt | 1 + 3 files changed, 6 insertions(+) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index 4de3e580..4d7efba1 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -1,5 +1,8 @@ import flask import flask_bootstrap +import redis +from flask_kvsession import KVSessionExtension +from simplekv.memory.redisstore import RedisStore from mailu import utils, debug, models, manage, configuration @@ -17,6 +20,7 @@ def create_app_from_config(config): # Initialize application extensions config.init_app(app) models.db.init_app(app) + KVSessionExtension(RedisStore(redis.StrictRedis().from_url('redis://{0}/3'.format(config['REDIS_ADDRESS']))), app) utils.limiter.init_app(app) utils.babel.init_app(app) utils.login.init_app(app) diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index f767f431..54cf9a14 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -13,6 +13,7 @@ Flask==1.0.2 Flask-Babel==0.12.2 Flask-Bootstrap==3.3.7.1 Flask-DebugToolbar==0.10.1 +Flask-KVSession==0.6.2 Flask-Limiter==1.0.1 Flask-Login==0.4.1 Flask-Migrate==2.4.0 diff --git a/core/admin/requirements.txt b/core/admin/requirements.txt index 9739ed3f..abb37234 100644 --- a/core/admin/requirements.txt +++ b/core/admin/requirements.txt @@ -3,6 +3,7 @@ Flask-Login Flask-SQLAlchemy Flask-bootstrap Flask-Babel +Flask-KVSession Flask-migrate Flask-script Flask-wtf From d459c374322f219ab12801d17817c12c628f1fdc Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 22 Feb 2021 20:34:06 +0100 Subject: [PATCH 67/74] make session IDs 128bits --- core/admin/mailu/configuration.py | 1 + 1 file changed, 1 insertion(+) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index 429e778c..a9ab937f 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -135,6 +135,7 @@ class ConfigManager(dict): self.config['QUOTA_STORAGE_URL'] = 'redis://{0}/1'.format(self.config['REDIS_ADDRESS']) self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' self.config['SESSION_COOKIE_HTTPONLY'] = True + self.config['SESSION_KEY_BITS'] = 128 # update the app config itself app.config = self From a1d32568d6aceec8b0a2a0fd0514714585020edc Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 22 Feb 2021 20:43:52 +0100 Subject: [PATCH 68/74] Regenerate session-ids to prevent session fixation --- core/admin/mailu/ui/views/base.py | 2 ++ core/admin/mailu/ui/views/users.py | 2 ++ 2 files changed, 4 insertions(+) diff --git a/core/admin/mailu/ui/views/base.py b/core/admin/mailu/ui/views/base.py index 7501a883..625c02e1 100644 --- a/core/admin/mailu/ui/views/base.py +++ b/core/admin/mailu/ui/views/base.py @@ -17,6 +17,7 @@ def login(): if form.validate_on_submit(): user = models.User.login(form.email.data, form.pw.data) if user: + flask.session.regenerate() flask_login.login_user(user) endpoint = flask.request.args.get('next', '.index') return flask.redirect(flask.url_for(endpoint) @@ -30,6 +31,7 @@ def login(): @access.authenticated def logout(): flask_login.logout_user() + flask.session.destroy() return flask.redirect(flask.url_for('.index')) diff --git a/core/admin/mailu/ui/views/users.py b/core/admin/mailu/ui/views/users.py index 8830ff5b..2784fe53 100644 --- a/core/admin/mailu/ui/views/users.py +++ b/core/admin/mailu/ui/views/users.py @@ -119,6 +119,7 @@ def user_password(user_email): if form.pw.data != form.pw2.data: flask.flash('Passwords do not match', 'error') else: + flask.session.regenerate() user.set_password(form.pw.data) models.db.session.commit() flask.flash('Password updated for %s' % user) @@ -186,6 +187,7 @@ def user_signup(domain_name=None): if domain.has_email(form.localpart.data): flask.flash('Email is already used', 'error') else: + flask.session.regenerate() user = models.User(domain=domain) form.populate_obj(user) user.set_password(form.pw.data) From b9becd86497fa685e80cca2ccbe20d54405e6d24 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 22 Feb 2021 21:15:25 +0100 Subject: [PATCH 69/74] make sessions expire --- core/admin/mailu/configuration.py | 3 +++ docs/configuration.rst | 2 ++ 2 files changed, 5 insertions(+) diff --git a/core/admin/mailu/configuration.py b/core/admin/mailu/configuration.py index a9ab937f..0f50bc95 100644 --- a/core/admin/mailu/configuration.py +++ b/core/admin/mailu/configuration.py @@ -1,5 +1,6 @@ import os +from datetime import timedelta from socrate import system DEFAULT_CONFIG = { @@ -53,6 +54,7 @@ DEFAULT_CONFIG = { 'RECAPTCHA_PRIVATE_KEY': '', # Advanced settings 'LOG_LEVEL': 'WARNING', + 'SESSION_LIFETIME': 24, 'SESSION_COOKIE_SECURE': True, 'CREDENTIAL_ROUNDS': 12, # Host settings @@ -136,6 +138,7 @@ class ConfigManager(dict): self.config['SESSION_COOKIE_SAMESITE'] = 'Strict' self.config['SESSION_COOKIE_HTTPONLY'] = True self.config['SESSION_KEY_BITS'] = 128 + self.config['PERMANENT_SESSION_LIFETIME'] = timedelta(hours=int(self.config['SESSION_LIFETIME'])) # update the app config itself app.config = self diff --git a/docs/configuration.rst b/docs/configuration.rst index 26bdb024..7cb53d13 100644 --- a/docs/configuration.rst +++ b/docs/configuration.rst @@ -142,6 +142,8 @@ The ``CREDENTIAL_ROUNDS`` (default: 12) setting is the number of rounds used by The ``SESSION_COOKIE_SECURE`` (default: True) setting controls the secure flag on the cookies of the administrative interface. It should only be turned off if you intend to access it over plain HTTP. +``SESSION_LIFETIME`` (default: 24) is the length in hours a session is valid for on the administrative interface. + The ``LOG_LEVEL`` setting is used by the python start-up scripts as a logging threshold. Log messages equal or higher than this priority will be printed. Can be one of: CRITICAL, ERROR, WARNING, INFO, DEBUG or NOTSET. From 481cb6739216d168e6c439852a7db2e441b13f68 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 22 Feb 2021 21:18:06 +0100 Subject: [PATCH 70/74] cleanup old sessions on startup --- core/admin/mailu/__init__.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/core/admin/mailu/__init__.py b/core/admin/mailu/__init__.py index 4d7efba1..f9ca2466 100644 --- a/core/admin/mailu/__init__.py +++ b/core/admin/mailu/__init__.py @@ -20,7 +20,7 @@ def create_app_from_config(config): # Initialize application extensions config.init_app(app) models.db.init_app(app) - KVSessionExtension(RedisStore(redis.StrictRedis().from_url('redis://{0}/3'.format(config['REDIS_ADDRESS']))), app) + KVSessionExtension(RedisStore(redis.StrictRedis().from_url('redis://{0}/3'.format(config['REDIS_ADDRESS']))), app).cleanup_sessions(app) utils.limiter.init_app(app) utils.babel.init_app(app) utils.login.init_app(app) From 64d757582d2f3531604503d3608dd2815a591c72 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Mon, 22 Feb 2021 21:59:15 +0100 Subject: [PATCH 71/74] Disable anti-csrf on the login form The rationale is that the attacker doesn't have the password... and that doing it this way we avoid creating useless sessions --- core/admin/mailu/ui/forms.py | 2 ++ 1 file changed, 2 insertions(+) diff --git a/core/admin/mailu/ui/forms.py b/core/admin/mailu/ui/forms.py index 356137e8..32bb31ab 100644 --- a/core/admin/mailu/ui/forms.py +++ b/core/admin/mailu/ui/forms.py @@ -46,6 +46,8 @@ class ConfirmationForm(flask_wtf.FlaskForm): class LoginForm(flask_wtf.FlaskForm): + class Meta: + csrf = False email = fields.StringField(_('E-mail'), [validators.Email()]) pw = fields.PasswordField(_('Password'), [validators.DataRequired()]) submit = fields.SubmitField(_('Sign in')) From 513d2a4c5ef6930fe4d6f6e7371039233227dfb5 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Mar 2021 19:43:08 +0100 Subject: [PATCH 72/74] Fix bug #1660: nested headers shouldn't be touched --- core/postfix/conf/master.cf | 1 + 1 file changed, 1 insertion(+) diff --git a/core/postfix/conf/master.cf b/core/postfix/conf/master.cf index b43095ee..e45a8ccf 100644 --- a/core/postfix/conf/master.cf +++ b/core/postfix/conf/master.cf @@ -12,6 +12,7 @@ smtp inet n - n - - smtpd -o cleanup_service_name=outclean outclean unix n - n - 0 cleanup -o header_checks=pcre:/etc/postfix/outclean_header_filter.cf + -o nested_header_checks= # Internal postfix services pickup unix n - n 60 1 pickup From 97be7359fe1d2de4fcf9022325dcb66b387999c2 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Mar 2021 19:47:34 +0100 Subject: [PATCH 73/74] towncrier --- towncrier/newsfragments/1660.bugfix | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1660.bugfix diff --git a/towncrier/newsfragments/1660.bugfix b/towncrier/newsfragments/1660.bugfix new file mode 100644 index 00000000..a90fb099 --- /dev/null +++ b/towncrier/newsfragments/1660.bugfix @@ -0,0 +1 @@ +Don't replace nested headers (typically in attached emails) From b872b46097f507ae48fbb2a102207530678c36d7 Mon Sep 17 00:00:00 2001 From: Florent Daigniere Date: Tue, 9 Mar 2021 20:13:31 +0100 Subject: [PATCH 74/74] towncrier --- towncrier/newsfragments/1783.misc | 1 + 1 file changed, 1 insertion(+) create mode 100644 towncrier/newsfragments/1783.misc diff --git a/towncrier/newsfragments/1783.misc b/towncrier/newsfragments/1783.misc new file mode 100644 index 00000000..2ee4c97f --- /dev/null +++ b/towncrier/newsfragments/1783.misc @@ -0,0 +1 @@ +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.