diff --git a/.github/workflows/CI.yml b/.github/workflows/CI.yml index 2b81a60d..55595838 100644 --- a/.github/workflows/CI.yml +++ b/.github/workflows/CI.yml @@ -13,7 +13,7 @@ on: - '[1-9].[0-9].[0-9]' # pre-releases, e.g. 1.8-pre1 - 1.8-pre[0-9] - # test branches, e.g. test-debian + # test branches, e.g. test-debian - test-* ############################################### @@ -39,6 +39,21 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + #For branch TESTING, we set the image tag to PR-xxxx + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -58,7 +73,7 @@ jobs: run: echo "$DOCKER_PW" | docker login --username $DOCKER_UN --password-stdin - name: Build all docker images env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} run: docker-compose -f tests/build.yml build @@ -94,7 +109,7 @@ jobs: - name: Test core suite run: python tests/compose/test.py core 1 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -127,7 +142,7 @@ jobs: - name: Test fetch run: python tests/compose/test.py fetchmail 1 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -160,7 +175,7 @@ jobs: - name: Test clamvav run: python tests/compose/test.py filters 2 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -193,7 +208,7 @@ jobs: - name: Test rainloop run: python tests/compose/test.py rainloop 1 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -226,7 +241,7 @@ jobs: - name: Test roundcube run: python tests/compose/test.py roundcube 1 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -259,7 +274,7 @@ jobs: - name: Test webdav run: python tests/compose/test.py webdav 1 env: - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} @@ -280,6 +295,21 @@ jobs: shell: bash run: | echo "BRANCH=${GITHUB_REF#refs/heads/}" >> $GITHUB_ENV + #For branch TESTING, we set the image tag to PR-xxxx + - name: Derive MAILU_VERSION for branch testing + if: ${{ env.BRANCH == 'testing' }} + shell: bash + env: + COMMIT_MESSAGE: ${{ github.event.head_commit.message }} + run: | + echo "MAILU_VERSION=pr-${COMMIT_MESSAGE//[!0-9]/}" >> $GITHUB_ENV + - name: Derive MAILU_VERSION for other branches than testing + if: ${{ env.BRANCH != 'testing' }} + shell: bash + env: + MAILU_BRANCH: ${{ env.BRANCH }} + run: | + echo "MAILU_VERSION=${{ env.MAILU_BRANCH }}" >> $GITHUB_ENV - name: Create folder for storing images run: | sudo mkdir -p /images @@ -300,9 +330,8 @@ jobs: DOCKER_PW: ${{ secrets.Docker_Password }} DOCKER_ORG: ${{ secrets.DOCKER_ORG }} DOCKER_ORG_TESTS: ${{ secrets.DOCKER_ORG_TESTS }} - MAILU_VERSION: ${{ env.BRANCH }} + MAILU_VERSION: ${{ env.MAILU_VERSION }} TRAVIS_BRANCH: ${{ env.BRANCH }} - TRAVIS_COMMIT_MESSAGE: ${{ github.event.head_commit.message }} run: bash tests/deploy.sh # This job is watched by bors. It only complets if building,testing and deploy worked. diff --git a/PULL_REQUEST_TEMPLATE.md b/PULL_REQUEST_TEMPLATE.md index 059318fc..8fb3265d 100644 --- a/PULL_REQUEST_TEMPLATE.md +++ b/PULL_REQUEST_TEMPLATE.md @@ -13,4 +13,4 @@ Before we can consider review and merge, please make sure the following list is If an entry in not applicable, you can check it or remove it from the list. - [ ] In case of feature or enhancement: documentation updated accordingly -- [ ] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/guide.html#changelog) entry file. +- [ ] Unless it's docs or a minor change: add [changelog](https://mailu.io/master/contributors/workflow.html#changelog) entry file. diff --git a/core/admin/Dockerfile b/core/admin/Dockerfile index a0d3d996..0a3b8468 100644 --- a/core/admin/Dockerfile +++ b/core/admin/Dockerfile @@ -26,7 +26,7 @@ WORKDIR /app COPY requirements-prod.txt requirements.txt RUN apk add --no-cache openssl curl postgresql-libs mariadb-connector-c \ && apk add --no-cache --virtual build-dep \ - openssl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev \ + openssl-dev libffi-dev python3-dev build-base postgresql-dev mariadb-connector-c-dev cargo \ && pip3 install -r requirements.txt \ && apk del --no-cache build-dep diff --git a/core/admin/mailu/internal/views/auth.py b/core/admin/mailu/internal/views/auth.py index 8ff10aed..2baeddce 100644 --- a/core/admin/mailu/internal/views/auth.py +++ b/core/admin/mailu/internal/views/auth.py @@ -63,7 +63,7 @@ def basic_authentication(): authorization = flask.request.headers.get("Authorization") if authorization and authorization.startswith("Basic "): encoded = authorization.replace("Basic ", "") - user_email, password = base64.b64decode(encoded).split(b":") + user_email, password = base64.b64decode(encoded).split(b":", 1) user = models.User.query.get(user_email.decode("utf8")) if nginx.check_credentials(user, password.decode('utf-8'), flask.request.remote_addr, "web"): response = flask.Response() diff --git a/core/admin/mailu/models.py b/core/admin/mailu/models.py index b5ba29c0..3a299786 100644 --- a/core/admin/mailu/models.py +++ b/core/admin/mailu/models.py @@ -57,10 +57,9 @@ class IdnaEmail(db.TypeDecorator): def process_bind_param(self, value, dialect): """ encode unicode domain part of email address to punycode """ - localpart, domain_name = value.rsplit('@', 1) + localpart, domain_name = value.lower().rsplit('@', 1) if '@' in localpart: raise ValueError('email local part must not contain "@"') - domain_name = domain_name.lower() return f'{localpart}@{idna.encode(domain_name).decode("ascii")}' def process_result_value(self, value, dialect): @@ -272,11 +271,12 @@ class Domain(Base): return dkim.strip_key(dkim_key).decode('utf8') def generate_dkim_key(self): - """ generate and activate new DKIM key """ + """ generate new DKIM key """ self.dkim_key = dkim.gen_key() def has_email(self, localpart): """ checks if localpart is configured for domain """ + localpart = localpart.lower() for email in chain(self.users, self.aliases): if email.localpart == localpart: return True @@ -355,8 +355,8 @@ class Email(object): @email.setter def email(self, value): """ setter for email - sets _email, localpart and domain_name at once """ - self.localpart, self.domain_name = value.rsplit('@', 1) - self._email = value + self._email = value.lower() + self.localpart, self.domain_name = self._email.rsplit('@', 1) @staticmethod def _update_localpart(target, value, *_): @@ -371,8 +371,8 @@ class Email(object): @classmethod def __declare_last__(cls): # gets called after mappings are completed - sqlalchemy.event.listen(User.localpart, 'set', cls._update_localpart, propagate=True) - sqlalchemy.event.listen(User.domain_name, 'set', cls._update_domain_name, propagate=True) + sqlalchemy.event.listen(cls.localpart, 'set', cls._update_localpart, propagate=True) + sqlalchemy.event.listen(cls.domain_name, 'set', cls._update_domain_name, propagate=True) def sendmail(self, subject, body): """ send an email to the address """ @@ -389,8 +389,7 @@ class Email(object): def resolve_domain(cls, email): """ resolves domain alternative to real domain """ localpart, domain_name = email.rsplit('@', 1) if '@' in email else (None, email) - alternative = Alternative.query.get(domain_name) - if alternative: + if alternative := Alternative.query.get(domain_name): domain_name = alternative.domain_name return (localpart, domain_name) @@ -401,12 +400,14 @@ class Email(object): localpart_stripped = None stripped_alias = None - if os.environ.get('RECIPIENT_DELIMITER') in localpart: - localpart_stripped = localpart.rsplit(os.environ.get('RECIPIENT_DELIMITER'), 1)[0] + delim = os.environ.get('RECIPIENT_DELIMITER') + if delim in localpart: + localpart_stripped = localpart.rsplit(delim, 1)[0] user = User.query.get(f'{localpart}@{domain_name}') if not user and localpart_stripped: user = User.query.get(f'{localpart_stripped}@{domain_name}') + if user: email = f'{localpart}@{domain_name}' @@ -416,15 +417,15 @@ class Email(object): destination.append(email) else: destination = [email] + return destination pure_alias = Alias.resolve(localpart, domain_name) - stripped_alias = Alias.resolve(localpart_stripped, domain_name) if pure_alias and not pure_alias.wildcard: return pure_alias.destination - if stripped_alias: + if stripped_alias := Alias.resolve(localpart_stripped, domain_name): return stripped_alias.destination if pure_alias: diff --git a/core/admin/mailu/ui/templates/user/reply.html b/core/admin/mailu/ui/templates/user/reply.html index 7225a178..1a161188 100644 --- a/core/admin/mailu/ui/templates/user/reply.html +++ b/core/admin/mailu/ui/templates/user/reply.html @@ -14,7 +14,7 @@ {{ form.hidden_tag() }} {{ macros.form_field(form.reply_enabled, onchange="if(this.checked){$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').removeAttr('readonly')} - else{$('#reply_subject,#reply_body,#reply_enddate').attr('readonly', '')}") }} + else{$('#reply_subject,#reply_body,#reply_enddate,#reply_startdate').attr('readonly', '')}") }} {{ macros.form_field(form.reply_subject, **{("rw" if user.reply_enabled else "readonly"): ""}) }} {{ macros.form_field(form.reply_body, rows=10, diff --git a/core/admin/mailu/ui/views/domains.py b/core/admin/mailu/ui/views/domains.py index 719d3844..f394ce7d 100644 --- a/core/admin/mailu/ui/views/domains.py +++ b/core/admin/mailu/ui/views/domains.py @@ -74,6 +74,8 @@ def domain_details(domain_name): def domain_genkeys(domain_name): domain = models.Domain.query.get(domain_name) or flask.abort(404) domain.generate_dkim_key() + models.db.session.add(domain) + models.db.session.commit() return flask.redirect( flask.url_for(".domain_details", domain_name=domain_name)) diff --git a/core/admin/package.json b/core/admin/package.json index a1107c69..77f39986 100644 --- a/core/admin/package.json +++ b/core/admin/package.json @@ -2,34 +2,30 @@ "name": "mailu", "version": "1.0.0", "description": "Mailu admin assets", - "main": "assest/index.js", + "main": "assets/index.js", + "directories": { + "lib": "lib" + }, "scripts": { "test": "echo \"Error: no test specified\" && exit 1" }, "author": "", "license": "ISC", "dependencies": { - "@babel/core": "^7.4.4", - "@babel/preset-env": "^7.4.4", - "admin-lte": "^2.4.10", - "babel-loader": "^8.0.5", - "bootstrap": "^3.4.1", + "@babel/core": "^7.14.6", + "admin-lte": "^2.4.18", + "babel-loader": "^8.0.6", "css-loader": "^2.1.1", "expose-loader": "^0.7.5", - "file-loader": "^3.0.1", - "font-awesome": "^4.7.0", - "font-awesome-loader": "^1.0.2", - "jQuery": "^1.7.4", - "less": "^3.9.0", + "jquery": "^3.6.0", + "less": "^3.13.1", "less-loader": "^5.0.0", - "mini-css-extract-plugin": "^0.6.0", - "node-sass": "^4.12.0", - "popper.js": "^1.15.0", - "sass-loader": "^7.1.0", - "select2": "^4.0.7-rc.0", - "style-loader": "^0.23.1", - "url-loader": "^1.1.2", - "webpack": "^4.30.0", - "webpack-cli": "^3.3.2" + "mini-css-extract-plugin": "^1.2.1", + "node-sass": "^4.13.1", + "sass-loader": "^7.3.1", + "select2": "^4.0.13", + "url-loader": "^2.3.0", + "webpack": "^4.33.0", + "webpack-cli": "^3.3.12" } } diff --git a/core/admin/requirements-prod.txt b/core/admin/requirements-prod.txt index c4663557..88ff2981 100644 --- a/core/admin/requirements-prod.txt +++ b/core/admin/requirements-prod.txt @@ -5,7 +5,7 @@ bcrypt==3.1.6 blinker==1.4 cffi==1.12.3 Click==7.0 -cryptography==3.2 +cryptography==3.4.7 decorator==4.4.0 dnspython==1.16.0 dominate==2.3.5 @@ -25,7 +25,7 @@ idna==2.8 infinity==1.4 intervals==0.8.1 itsdangerous==1.1.0 -Jinja2==2.10.1 +Jinja2==2.11.3 limits==1.3 Mako==1.0.9 MarkupSafe==1.1.1 @@ -36,11 +36,11 @@ passlib==1.7.4 psycopg2==2.8.2 pycparser==2.19 Pygments==2.8.1 -pyOpenSSL==19.0.0 +pyOpenSSL==20.0.1 python-dateutil==2.8.0 python-editor==1.0.4 pytz==2019.1 -PyYAML==5.1 +PyYAML==5.4.1 redis==3.2.1 #alpine3:12 provides six==1.15.0 #six==1.12.0 diff --git a/core/admin/start.py b/core/admin/start.py index 2c925e01..0eff3bbe 100755 --- a/core/admin/start.py +++ b/core/admin/start.py @@ -19,7 +19,8 @@ if account is not None and domain is not None and password is not None: os.system("flask mailu admin %s %s '%s' --mode %s" % (account, domain, password, mode)) start_command="".join([ - "gunicorn -w 4 -b :80 ", + "gunicorn --threads ", str(os.cpu_count()), + " -b :80 ", "--access-logfile - " if (log.root.level<=log.INFO) else "", "--error-logfile - ", "--preload ", diff --git a/core/postfix/conf/outclean_header_filter.cf b/core/postfix/conf/outclean_header_filter.cf index 03e33ee9..7e0e92d3 100644 --- a/core/postfix/conf/outclean_header_filter.cf +++ b/core/postfix/conf/outclean_header_filter.cf @@ -4,7 +4,7 @@ # Remove the first line of the Received: header. Note that we cannot fully remove the Received: header # because OpenDKIM requires that a header be present when signing outbound mail. The first line is # where the user's home IP address would be. -/^\s*Received:[^\n]*(.*)/ REPLACE Received: from authenticated-user (PRIMARY_HOSTNAME [PUBLIC_IP])$1 +/^\s*Received:[^\n]*(.*)/ REPLACE Received: from authenticated-user ({{OUTCLEAN}} [{{OUTCLEAN_ADDRESS}}])$1 # Remove other typically private information. /^\s*User-Agent:/ IGNORE diff --git a/core/postfix/start.py b/core/postfix/start.py index b68303e1..e0c781b7 100755 --- a/core/postfix/start.py +++ b/core/postfix/start.py @@ -8,12 +8,13 @@ import logging as log import sys from podop import run_server +from pwd import getpwnam from socrate import system, conf log.basicConfig(stream=sys.stderr, level=os.environ.get("LOG_LEVEL", "WARNING")) def start_podop(): - os.setuid(100) + os.setuid(getpwnam('postfix').pw_uid) url = "http://" + os.environ["ADMIN_ADDRESS"] + "/internal/postfix/" # TODO: Remove verbosity setting from Podop? run_server(0, "postfix", "/tmp/podop.socket", [ @@ -36,6 +37,15 @@ os.environ["FRONT_ADDRESS"] = system.get_host_address_from_environment("FRONT", os.environ["ADMIN_ADDRESS"] = system.get_host_address_from_environment("ADMIN", "admin") os.environ["ANTISPAM_MILTER_ADDRESS"] = system.get_host_address_from_environment("ANTISPAM_MILTER", "antispam:11332") os.environ["LMTP_ADDRESS"] = system.get_host_address_from_environment("LMTP", "imap:2525") +os.environ["OUTCLEAN"] = os.environ["HOSTNAMES"].split(",")[0] +try: + _to_lookup = os.environ["OUTCLEAN"] + # Ensure we lookup a FQDN: @see #1884 + if not _to_lookup.endswith('.'): + _to_lookup += '.' + os.environ["OUTCLEAN_ADDRESS"] = system.resolve_hostname(_to_lookup) +except: + os.environ["OUTCLEAN_ADDRESS"] = "10.10.10.10" for postfix_file in glob.glob("/conf/*.cf"): conf.jinja(postfix_file, os.environ, os.path.join("/etc/postfix", os.path.basename(postfix_file))) diff --git a/docs/faq.rst b/docs/faq.rst index 403fd163..f38fdca2 100644 --- a/docs/faq.rst +++ b/docs/faq.rst @@ -497,6 +497,8 @@ follow these steps: logging: driver: journald + options: + tag: mailu-front 2. Add the /etc/fail2ban/filter.d/bad-auth.conf @@ -506,6 +508,7 @@ follow these steps: [Definition] failregex = .* client login failed: .+ client:\ ignoreregex = + journalmatch = CONTAINER_TAG=mailu-front 3. Add the /etc/fail2ban/jail.d/bad-auth.conf @@ -513,8 +516,8 @@ follow these steps: [bad-auth] enabled = true + backend = systemd filter = bad-auth - logpath = /var/log/messages bantime = 604800 findtime = 300 maxretry = 10 diff --git a/docs/kubernetes/mailu/front.yaml b/docs/kubernetes/mailu/front.yaml index a1d5acb2..2fba1026 100644 --- a/docs/kubernetes/mailu/front.yaml +++ b/docs/kubernetes/mailu/front.yaml @@ -1,4 +1,4 @@ -apiVersion: apps/v1beta2 +apiVersion: apps/v1 kind: DaemonSet metadata: name: mailu-front diff --git a/setup/requirements.txt b/setup/requirements.txt index b6bf2120..f2eb2157 100644 --- a/setup/requirements.txt +++ b/setup/requirements.txt @@ -1,4 +1,4 @@ -flask -flask-bootstrap -redis -gunicorn +Flask==1.0.2 +Flask-Bootstrap==3.3.7.1 +gunicorn==19.9.0 +redis==3.2.1 diff --git a/setup/server.py b/setup/server.py index 0d58fa25..5be1fc83 100644 --- a/setup/server.py +++ b/setup/server.py @@ -54,11 +54,11 @@ def build_app(path): @app.context_processor def app_context(): return dict( - versions=os.getenv("VERSIONS","master").split(','), + versions=os.getenv("VERSIONS","master").split(','), stable_version = os.getenv("stable_version", "master") ) - prefix_bp = flask.Blueprint(version, __name__) + prefix_bp = flask.Blueprint(version.replace(".", "_"), __name__) prefix_bp.jinja_loader = jinja2.ChoiceLoader([ jinja2.FileSystemLoader(os.path.join(path, "templates")), jinja2.FileSystemLoader(os.path.join(path, "flavors")) diff --git a/setup/templates/steps/compose/02_services.html b/setup/templates/steps/compose/02_services.html index 20d4d7cb..5118c304 100644 --- a/setup/templates/steps/compose/02_services.html +++ b/setup/templates/steps/compose/02_services.html @@ -59,7 +59,7 @@ the security implications caused by such an increase of attack surface.

Fetchmail allows users to retrieve mail from an external mail-server via IMAP/POP3 and puts it in their inbox. - + diff --git a/setup/templates/steps/config.html b/setup/templates/steps/config.html index 29d8dddd..3769a210 100644 --- a/setup/templates/steps/config.html +++ b/setup/templates/steps/config.html @@ -83,7 +83,7 @@ manage your email domains, users, etc.

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

Fetchmail allows users to retrieve mail from an external mail-server via IMAP/POP3 and puts it in their inbox. - + diff --git a/tests/deploy.sh b/tests/deploy.sh index a836417b..abb37b6b 100755 --- a/tests/deploy.sh +++ b/tests/deploy.sh @@ -3,14 +3,5 @@ # Skip deploy for staging branch [ "$TRAVIS_BRANCH" = "staging" ] && exit 0 -# Retag in case of `bors try` -if [ "$TRAVIS_BRANCH" = "testing" ]; then - export DOCKER_ORG=$DOCKER_ORG_TESTS - # Commit message is like "Try #99". - # This sets the version tag to "pr-99" - export MAILU_VERSION="pr-${TRAVIS_COMMIT_MESSAGE//[!0-9]/}" - docker-compose -f tests/build.yml build -fi - docker login -u $DOCKER_UN -p $DOCKER_PW docker-compose -f tests/build.yml push diff --git a/towncrier/newsfragments/1294.bugfix b/towncrier/newsfragments/1294.bugfix new file mode 100644 index 00000000..68bb7a8a --- /dev/null +++ b/towncrier/newsfragments/1294.bugfix @@ -0,0 +1 @@ +Ensure that the podop socket is always owned by the postfix user (wasn't the case when build using non-standard base images... typically for arm64) diff --git a/towncrier/newsfragments/1845.feature b/towncrier/newsfragments/1845.feature new file mode 100644 index 00000000..afde9313 --- /dev/null +++ b/towncrier/newsfragments/1845.feature @@ -0,0 +1 @@ +Update version of rainloop webmail to 1.16.0. This is a security update. diff --git a/towncrier/newsfragments/1857.doc b/towncrier/newsfragments/1857.doc new file mode 100644 index 00000000..06cb91ab --- /dev/null +++ b/towncrier/newsfragments/1857.doc @@ -0,0 +1 @@ +Update fail2ban documentation to use systemd backend instead of filepath for journald \ No newline at end of file diff --git a/towncrier/newsfragments/1861.bugfix b/towncrier/newsfragments/1861.bugfix new file mode 100644 index 00000000..1e28d1b6 --- /dev/null +++ b/towncrier/newsfragments/1861.bugfix @@ -0,0 +1 @@ +Fix a bug preventing colons from being used in passwords when using radicale/webdav. diff --git a/towncrier/newsfragments/1874.bugfix b/towncrier/newsfragments/1874.bugfix new file mode 100644 index 00000000..a301835e --- /dev/null +++ b/towncrier/newsfragments/1874.bugfix @@ -0,0 +1 @@ +Remove dot in blueprint name to prevent critical flask startup error in setup. diff --git a/towncrier/newsfragments/1880.feature b/towncrier/newsfragments/1880.feature new file mode 100644 index 00000000..212dc906 --- /dev/null +++ b/towncrier/newsfragments/1880.feature @@ -0,0 +1 @@ +Update jquery used in setup. Set pinned versions in requirements.txt for setup. This is a security update. diff --git a/towncrier/newsfragments/191.bugfix b/towncrier/newsfragments/191.bugfix new file mode 100644 index 00000000..185d3074 --- /dev/null +++ b/towncrier/newsfragments/191.bugfix @@ -0,0 +1 @@ +Replace PUBLIC_HOSTNAME and PUBLIC_IP in "Received" headers to ensure that no undue spam points are attributed diff --git a/webmails/rainloop/Dockerfile b/webmails/rainloop/Dockerfile index 9987330e..9c65f277 100644 --- a/webmails/rainloop/Dockerfile +++ b/webmails/rainloop/Dockerfile @@ -17,7 +17,7 @@ RUN apt-get update && apt-get install -y \ # Shared layer between nginx, dovecot, postfix, postgresql, rspamd, unbound, rainloop, roundcube RUN pip3 install socrate -ENV RAINLOOP_URL https://github.com/RainLoop/rainloop-webmail/releases/download/v1.14.0/rainloop-community-1.14.0.zip +ENV RAINLOOP_URL https://github.com/RainLoop/rainloop-webmail/releases/download/v1.16.0/rainloop-community-1.16.0.zip RUN apt-get update && apt-get install -y \ unzip python3-jinja2 \