1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-14 10:30:27 +00:00

Compare commits

..

57 Commits

Author SHA1 Message Date
FreddleSpl0it a632980871 Merge pull request #6336 from mailcow/staging
Update 2025-02
2025-02-27 11:48:57 +01:00
DerLinkman 5296085189 update.sh: corrected typos inside update.sh 2025-02-27 11:47:08 +01:00
DerLinkman a4c2cf4c67 scripts: adapted new docker image names to docker_garbage function + removed dup 2025-02-27 11:44:52 +01:00
FreddleSpl0it 2d1ef41d32 Merge pull request #6335 from mailcow/staging
Update 2025-02
2025-02-27 11:05:55 +01:00
Peter 3c9d0c9d57 use ghcr.io for backupimage (#6333)
* use ghcr.io for backup image

* backup script: use renamed script + improved build of image

---------

Co-authored-by: DerLinkman <niklas.meyer@servercow.de>
2025-02-27 10:58:23 +01:00
FreddleSpl0it 35a6f81d0d [Redis] use 7.4.2-alpine image 2025-02-27 09:28:52 +01:00
FreddleSpl0it 4b31c04e3e Merge pull request #6330 from mailcow/feat/major-update-prompt
Prompt user before applying major updates
2025-02-27 08:15:21 +01:00
FreddleSpl0it 3d9cc2f6dd add 2025-02 to major versions 2025-02-27 08:14:34 +01:00
DerLinkman 704dd50262 compose: use ghcr.io for new/current mailcow docker images instead of docker hub (#6332) 2025-02-26 15:20:57 +01:00
FreddleSpl0it c4a0e370b7 Merge pull request #6155 from PseudoResonance/fix2752
Fix #2752 - Allow domain recipients for address rewrite
2025-02-26 10:01:03 +01:00
FreddleSpl0it 787fa49d0c prompt user before applying major updates 2025-02-25 12:08:21 +01:00
DerLinkman a6c38590ca rspamd: upgraded rspamd to 3.11.0-2 (incl. NIXSPAM Removal) (#6328) 2025-02-25 09:23:10 +01:00
PseudoResonance e52323bf1d Fix @ prefixing domain rewrite and update localization 2025-02-24 22:36:17 -08:00
PseudoResonance f15ee39b63 Fix #2752: Domain recipient for address rewrite
(cherry picked from commit 40f6d691d8774d6f813153974f8fe462a8db9ab3)
2025-02-24 22:07:23 -08:00
FreddleSpl0it 6ec5e88793 Merge pull request #6309 from mailcow/fix/6308
[Dovecot][Netfilter] Fix dovecot failed login regex
2025-02-24 11:26:06 +01:00
FreddleSpl0it 7d35646342 [Netfilter] adjust dovecot failed login regex 2025-02-24 09:20:41 +01:00
FreddleSpl0it 321965adee [Netfilter] Fix dovecot password mismatch regex 2025-02-18 15:05:59 +01:00
Peter 7bce5d836b Move sed cmd to remove discontinued DNSBLs (#6315)
* Move sed cmd to remove discontinued DNSBLs

* compose: bump postfix version

---------

Co-authored-by: DerLinkman <niklas.meyer@servercow.de>
2025-02-18 11:20:03 +01:00
FreddleSpl0it 351f4ce787 [Redis] Add support for masterauth via env var 2025-02-18 11:16:06 +01:00
FreddleSpl0it a567d5dc31 [Nginx] Add support for trusted proxies via env var 2025-02-18 11:03:34 +01:00
DerLinkman 4ac541f671 [Mariadb] Update to 10.11 (LTS) (#5152)
* [Mariadb] Update to 10.11 (LTS)

* mysql: set default collation to general_ci
2025-02-17 15:48:25 +01:00
Dmitriy Alekseev f6dc0b463f Update Rspamd to 3.11.0 and enable SMTPUTF8 for outgoing mail (#6216)
* Update Rspamd to 3.11

* Enable SMTPUTF8 and hide it from SMTPD greeting

* Update options.inc

* compose: increased rspamd tag
2025-02-17 14:41:39 +01:00
DerLinkman 16e22e23dc sogo: switched apt source to sogo again (supports aarch64 now) 2025-02-17 14:31:50 +01:00
FreddleSpl0it d8afa6f393 [Dovecot][Netfilter] Fix dovecot failed login regex 2025-02-14 13:12:12 +01:00
milkmaker 836e3f15b7 [Web] Updated lang.es-es.json (#6307)
Co-authored-by: Julie GINESTIERE <julien.ginestiere+git@gmail.com>
2025-02-13 19:32:39 +01:00
FreddleSpl0it aaa7e4a184 [Web] Fix incorrect session lifetime in sogo-auth.php 2025-02-13 11:54:55 +01:00
FreddleSpl0it 3912341b32 [SOGo] rename custom logo 2025-02-12 11:31:14 +01:00
FreddleSpl0it 735d5f0e56 Merge pull request #6220 from Babybatrick/staging
Adding lines to docker-compose.yml to allow for simpler SOGo web client UI customisation
2025-02-12 10:54:16 +01:00
FreddleSpl0it f375794fb7 Merge pull request #6223 from mailcow/ffdhe2048
Ffdhe2048
2025-02-12 10:48:22 +01:00
renovate[bot] 4ed3017a02 chore(deps): update devops-infra/action-pull-request action to v0.6.0 (#6302) 2025-02-12 06:56:10 +01:00
FreddleSpl0it ef2f5f7be0 [Dovecot] Use Redis ACL user quota_notify with restricted access 2025-02-11 16:59:18 +01:00
Henry Williams 743e88fd67 Update generate_config.sh version checking for wider compatibility (#6270)
* Update generate_config.sh version checking for wider compatibility 

fix: replace `grep -oP` with `grep -oE` for broader compatibility

The `-P` option (Perl-compatible regex) is not supported in all versions of `grep`, particularly the default BSD `grep` on macOS. This change replaces `-P` with `-E` (extended regex), which is more widely available and ensures compatibility across different environments.

Tested on macOS and Linux.

* Update generate_config.sh to remove use of platform dependent grep

Replaced version checking using free-form text. Instead, uses Docker’s built-in templating instead of parsing free-form text. This gives cross-platform consistency without dependency on particular versions of grep.
2025-02-11 13:55:03 +01:00
DerLinkman ac2f0c7db1 Merge pull request #6286 from mailcow/fix-workflow-staging
Fix check_prs_if_on_staging workflow
2025-02-11 13:52:44 +01:00
FreddleSpl0it 120366fec7 Merge pull request #6291 from mailcow/staging
Update 2025-01a
2025-02-04 13:55:30 +01:00
FreddleSpl0it 3544a2246e [Nginx] fix ADDITIONAL_SERVER_NAMES array 2025-02-04 13:30:00 +01:00
FreddleSpl0it 97890b71f1 [Nginx] Invert SKIP container condition 2025-02-03 12:22:13 +01:00
FreddleSpl0it e645f931dc [Nginx] Add env var for HTTP to HTTPS redirection 2025-02-03 12:05:08 +01:00
FreddleSpl0it bbdec0960a Merge pull request #6290 from mailcow/fix/nginx-vhosts
[Nginx] Use vhosts for additional server names
2025-02-03 11:35:09 +01:00
milkmaker 41ba7d97fa update postscreen_access.cidr (#6287) 2025-02-01 17:06:07 +01:00
Peter 83fc2c6387 It's github-token now 2025-01-31 17:20:28 +01:00
DerLinkman aac4c6b5f4 postfix: added master.pid removal and startsecs to supervisord (#6284) 2025-01-31 12:49:39 +01:00
FreddleSpl0it 3c0f775e2f Merge pull request #6281 from mailcow/fix/6275
[Nginx] Fix
2025-01-31 10:49:21 +01:00
FreddleSpl0it 3a81b84cf7 [Nginx] Fix #6275 2025-01-30 14:49:18 +01:00
FreddleSpl0it a2e87e0880 [Web] Add validation for server_name against allow list 2025-01-30 11:47:55 +01:00
DerLinkman 2407aa7895 Merge branch 'feat/clamd-rebuild' into staging 2025-01-29 14:01:39 +01:00
DerLinkman 244d4b8c4c compose: rollback clamd version until next major... accidentally pushed 2025-01-29 13:46:53 +01:00
FreddleSpl0it 0ad327bbe5 [Nginx] Use separate vhosts for additional server names 2025-01-29 09:51:45 +01:00
DerLinkman f92ddd86c5 clamd: update to 1.4.2 + build from source instead using alpine packages (#6273)
* clamd: update to 1.4.2 + build from source instead using alpine packages

* clamd: remove exposed ports from buildfile

* clamd: cleanup dockerfile
2025-01-29 09:49:04 +01:00
DerLinkman 1a087bb2c8 clamd: cleanup dockerfile 2025-01-28 14:49:11 +01:00
DerLinkman 65bc581fab clamd: remove exposed ports from buildfile 2025-01-28 14:36:43 +01:00
DerLinkman 60a2270d1e clamd: update to 1.4.2 + build from source instead using alpine packages 2025-01-28 14:25:56 +01:00
FreddleSpl0it 8ed51e500f Merge pull request #6260 from mailcow/manitu
Remove discontinued Nixspam DNSBL
2025-01-27 16:21:29 +01:00
FreddleSpl0it 45d14254f2 [Postfix] Remove discontinued Nixspam DNSBL from existing dns_blocklists.cf 2025-01-24 10:06:50 +01:00
Michael Kuron 04116982a5 Remove discontinued Nixspam DNSBL 2025-01-23 22:16:54 +01:00
Dmitriy Alekseev d92aa4b15d Update dhparams.pem
Use https://ssl-config.mozilla.org/ffdhe2048.txt due to better security of the key
2024-12-20 15:39:41 +01:00
Amin ade20d79d4 Uploading of the necessary files, after new volumes were added to docker-compose.yml (sogo-mailcow container)
After new volumes were added to docker-compose.yml in the sogo-mailcow container, it is necessary to include the specified files in the path, in order for docker to correctly start after running `docker compose up` command, otherwise error will appear, as necessary files would be missing.
The files uploaded are original SOGo UI elements, obtained from the sogo-mailcow container. Whenever users will need to change the UI elements, they would just need to change these files. Hence simplifying the process.
2024-12-19 22:13:27 +08:00
Amin 65bc8f0972 Update docker-compose.yml (sogo-mailcow)
This commit includes the addition of 3 lines, in the volumes part of the sogo-mailcow container, to allow for better customisation of the user interface on the web client page.
2024-12-19 21:59:05 +08:00
55 changed files with 495 additions and 177 deletions
@@ -12,7 +12,7 @@ jobs:
- name: Send message - name: Send message
uses: thollander/actions-comment-pull-request@v3.0.1 uses: thollander/actions-comment-pull-request@v3.0.1
with: with:
GITHUB_TOKEN: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }} github-token: ${{ secrets.CHECKIFPRISSTAGING_ACTION_PAT }}
message: | message: |
Thanks for contributing! Thanks for contributing!
+1 -1
View File
@@ -12,7 +12,7 @@ jobs:
with: with:
fetch-depth: 0 fetch-depth: 0
- name: Run the Action - name: Run the Action
uses: devops-infra/action-pull-request@v0.5.5 uses: devops-infra/action-pull-request@v0.6.0
with: with:
github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }} github_token: ${{ secrets.PRTONIGHTLY_ACTION_PAT }}
title: Automatic PR to nightly from ${{ github.event.repository.updated_at}} title: Automatic PR to nightly from ${{ github.event.repository.updated_at}}
+9 -5
View File
@@ -9,6 +9,8 @@ on:
jobs: jobs:
docker_image_build: docker_image_build:
runs-on: ubuntu-latest runs-on: ubuntu-latest
permissions:
packages: write
steps: steps:
- name: Checkout - name: Checkout
uses: actions/checkout@v4 uses: actions/checkout@v4
@@ -19,17 +21,19 @@ jobs:
- name: Set up Docker Buildx - name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3 uses: docker/setup-buildx-action@v3
- name: Login to Docker Hub - name: Login to GHCR
if: github.event_name != 'pull_request'
uses: docker/login-action@v3 uses: docker/login-action@v3
with: with:
username: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_USERNAME }} registry: ghcr.io
password: ${{ secrets.BACKUPIMAGEBUILD_ACTION_DOCKERHUB_TOKEN }} username: ${{ github.repository_owner }}
password: ${{ secrets.GITHUB_TOKEN }}
- name: Build and push - name: Build and push
uses: docker/build-push-action@v6 uses: docker/build-push-action@v5
with: with:
context: . context: .
platforms: linux/amd64,linux/arm64 platforms: linux/amd64,linux/arm64
file: data/Dockerfiles/backup/Dockerfile file: data/Dockerfiles/backup/Dockerfile
push: true push: true
tags: mailcow/backup:latest tags: ghcr.io/mailcow/backup:latest
+3 -1
View File
@@ -47,7 +47,9 @@ data/conf/sogo/custom-theme.js
data/conf/sogo/plist_ldap data/conf/sogo/plist_ldap
data/conf/sogo/sieve.creds data/conf/sogo/sieve.creds
data/conf/sogo/cron.creds data/conf/sogo/cron.creds
data/conf/sogo/sogo-full.svg data/conf/sogo/custom-fulllogo.svg
data/conf/sogo/custom-shortlogo.svg
data/conf/sogo/custom-fulllogo.png
data/gitea/ data/gitea/
data/gogs/ data/gogs/
data/hooks/dovecot/* data/hooks/dovecot/*
+1 -1
View File
@@ -1,3 +1,3 @@
FROM debian:bookworm-slim FROM debian:bookworm-slim
RUN apt update && apt install pigz RUN apt update && apt install pigz -y --no-install-recommends
+91 -6
View File
@@ -1,14 +1,99 @@
FROM alpine:3.20 FROM alpine:3.21 AS builder
WORKDIR /src
ENV CLAMD_VERSION=1.4.2
RUN apk upgrade --no-cache \
&& apk add --update --no-cache \
g++ \
gcc \
gdb \
make \
cmake \
py3-pytest \
python3 \
valgrind \
bzip2-dev \
check-dev \
curl-dev \
json-c-dev \
libmilter-dev \
libxml2-dev \
linux-headers \
ncurses-dev \
openssl-dev \
pcre2-dev \
zlib-dev \
cargo \
rust
RUN wget -P /src https://www.clamav.net/downloads/production/clamav-${CLAMD_VERSION}.tar.gz \
&& tar xzfv /src/clamav-${CLAMD_VERSION}.tar.gz \
&& cd /src/clamav-${CLAMD_VERSION} \
&& cmake . \
-D CMAKE_BUILD_TYPE="Release" \
-D CMAKE_INSTALL_PREFIX="/usr" \
-D CMAKE_INSTALL_LIBDIR="/usr/lib" \
-D APP_CONFIG_DIRECTORY="/etc/clamav" \
-D DATABASE_DIRECTORY="/var/lib/clamav" \
-D ENABLE_CLAMONACC=OFF \
-D ENABLE_EXAMPLES=OFF \
-D ENABLE_MILTER=ON \
-D ENABLE_MAN_PAGES=OFF \
-D ENABLE_STATIC_LIB=OFF \
-D ENABLE_JSON_SHARED=ON \
&& cmake --build . \
&& make DESTDIR="/clamav" -j$(($(nproc) - 1)) install \
&& rm -r "/clamav/usr/lib/pkgconfig/" \
&& sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(LocalSocket\) .*|\1 /tmp/clamd.sock|" \
-e "s|.*\(TCPSocket\) .*|\1 3310|" \
-e "s|.*\(TCPAddr\) .*|#\1 0.0.0.0|" \
-e "s|.*\(User\) .*|\1 clamav|" \
-e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/clamd.log|" \
-e "s|^\#\(LogTime\).*|\1 yes|" \
"/clamav/etc/clamav/clamd.conf.sample" > "/clamav/etc/clamav/clamd.conf" \
&& sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(DatabaseOwner\) .*|\1 clamav|" \
-e "s|^\#\(UpdateLogFile\) .*|\1 /var/log/clamav/freshclam.log|" \
-e "s|^\#\(NotifyClamd\).*|\1 /etc/clamav/clamd.conf|" \
-e "s|^\#\(ScriptedUpdates\).*|\1 yes|" \
"/clamav/etc/clamav/freshclam.conf.sample" > "/clamav/etc/clamav/freshclam.conf" \
&& sed -e "s|^\(Example\)|\# \1|" \
-e "s|.*\(MilterSocket\) .*|\1 inet:7357|" \
-e "s|.*\(User\) .*|\1 clamav|" \
-e "s|^\#\(LogFile\) .*|\1 /var/log/clamav/milter.log|" \
-e "s|^\#\(LogTime\).*|\1 yes|" \
-e "s|.*\(\ClamdSocket\) .*|\1 unix:/tmp/clamd.sock|" \
"/clamav/etc/clamav/clamav-milter.conf.sample" > "/clamav/etc/clamav/clamav-milter.conf" || exit 1
FROM alpine:3.21
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
RUN apk upgrade --no-cache \ RUN apk upgrade --no-cache \
&& apk add --update --no-cache \ && apk add --update --no-cache \
rsync \ tzdata \
clamav \ rsync \
bind-tools \ bind-tools \
bash \ bash \
tini tini \
json-c \
libbz2 \
libcurl \
libmilter \
libxml2 \
ncurses-libs \
pcre2 \
zlib \
libgcc \
&& addgroup -S "clamav" && \
adduser -D -G "clamav" -h "/var/lib/clamav" -s "/bin/false" -S "clamav" && \
install -d -m 755 -g "clamav" -o "clamav" "/var/log/clamav" && \
chown -R clamav:clamav /var/lib/clamav
COPY --from=builder "/clamav" "/"
# init # init
COPY clamd.sh /clamd.sh COPY clamd.sh /clamd.sh
+1
View File
@@ -91,6 +91,7 @@ done
) & ) &
BACKGROUND_TASKS+=($!) BACKGROUND_TASKS+=($!)
echo "$(clamd -V) is starting... please wait a moment."
nice -n10 clamd & nice -n10 clamd &
BACKGROUND_TASKS+=($!) BACKGROUND_TASKS+=($!)
+1 -1
View File
@@ -23,7 +23,7 @@ else:
while True: while True:
try: try:
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS']) r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0, username='quota_notify', password='')
r.ping() r.ping()
except Exception as ex: except Exception as ex:
print('%s - trying again...' % (ex)) print('%s - trying again...' % (ex))
@@ -38,8 +38,13 @@ filter f_replica {
not match("User has no mail_replica in userdb" value("MESSAGE")); not match("User has no mail_replica in userdb" value("MESSAGE"));
not match("Error: sync: Unknown user in remote" value("MESSAGE")); not match("Error: sync: Unknown user in remote" value("MESSAGE"));
}; };
filter f_dovecot_auth_try {
not match("- trying the next passdb" value("MESSAGE")) and
not match("- trying the next userdb" value("MESSAGE"));
};
log { log {
source(s_dgram); source(s_dgram);
filter(f_dovecot_auth_try);
filter(f_replica); filter(f_replica);
destination(d_stdout); destination(d_stdout);
filter(f_mail); filter(f_mail);
+5
View File
@@ -38,8 +38,13 @@ filter f_replica {
not match("User has no mail_replica in userdb" value("MESSAGE")); not match("User has no mail_replica in userdb" value("MESSAGE"));
not match("Error: sync: Unknown user in remote" value("MESSAGE")); not match("Error: sync: Unknown user in remote" value("MESSAGE"));
}; };
filter f_dovecot_auth_try {
not match("- trying the next passdb" value("MESSAGE")) and
not match("- trying the next userdb" value("MESSAGE"));
};
log { log {
source(s_dgram); source(s_dgram);
filter(f_dovecot_auth_try);
filter(f_replica); filter(f_replica);
destination(d_stdout); destination(d_stdout);
filter(f_mail); filter(f_mail);
+4 -5
View File
@@ -85,11 +85,10 @@ def refreshF2bregex():
f2bregex[3] = r'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+' f2bregex[3] = r'warning: .*\[([0-9a-f\.:]+)\]: SASL .+ authentication failed: (?!.*Connection lost to authentication server).+'
f2bregex[4] = r'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+' f2bregex[4] = r'warning: non-SMTP command from .*\[([0-9a-f\.:]+)]:.+'
f2bregex[5] = r'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+' f2bregex[5] = r'NOQUEUE: reject: RCPT from \[([0-9a-f\.:]+)].+Protocol error.+'
f2bregex[6] = r'-login: Disconnected.+ \(auth failed, .+\): user=.*, method=.+, rip=([0-9a-f\.:]+),' f2bregex[6] = r'\w+\([^,]+,([0-9a-f\.:]+),<[^>]+>\): Password mismatch \(SHA1 of given password: [a-f0-9]+\)'
f2bregex[7] = r'-login: Aborted login.+ \(auth failed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' f2bregex[7] = r'\w+\([^,]+,([0-9a-f\.:]+),<[^>]+>\): unknown user \(SHA1 of given password: [a-f0-9]+\)'
f2bregex[8] = r'-login: Aborted login.+ \(tried to use disallowed .+\): user=.+, rip=([0-9a-f\.:]+), lip.+' f2bregex[8] = r'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked'
f2bregex[9] = r'SOGo.+ Login from \'([0-9a-f\.:]+)\' for user .+ might not have worked' f2bregex[9] = r'([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
f2bregex[10] = r'([0-9a-f\.:]+) \"GET \/SOGo\/.* HTTP.+\" 403 .+'
r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False)) r.set('F2B_REGEX', json.dumps(f2bregex, ensure_ascii=False))
else: else:
try: try:
+7 -3
View File
@@ -7,7 +7,7 @@ def includes_conf(env, template_vars):
listen_plain = "listen_plain.active" listen_plain = "listen_plain.active"
listen_ssl = "listen_ssl.active" listen_ssl = "listen_ssl.active"
server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {template_vars['ADDITIONAL_SERVER_NAMES']};" server_name_config = f"server_name {template_vars['MAILCOW_HOSTNAME']} autodiscover.* autoconfig.* {' '.join(template_vars['ADDITIONAL_SERVER_NAMES'])};"
listen_plain_config = f"listen {template_vars['HTTP_PORT']};" listen_plain_config = f"listen {template_vars['HTTP_PORT']};"
listen_ssl_config = f"listen {template_vars['HTTPS_PORT']};" listen_ssl_config = f"listen {template_vars['HTTPS_PORT']};"
if not template_vars['DISABLE_IPv6']: if not template_vars['DISABLE_IPv6']:
@@ -42,20 +42,24 @@ def nginx_conf(env, template_vars):
def prepare_template_vars(): def prepare_template_vars():
ipv4_network = os.getenv("IPV4_NETWORK", "172.22.1") ipv4_network = os.getenv("IPV4_NETWORK", "172.22.1")
additional_server_names = os.getenv("ADDITIONAL_SERVER_NAMES", "")
trusted_proxies = os.getenv("TRUSTED_PROXIES", "")
template_vars = { template_vars = {
'IPV4_NETWORK': ipv4_network, 'IPV4_NETWORK': ipv4_network,
'TRUSTED_NETWORK': os.getenv("TRUSTED_NETWORK", False), 'TRUSTED_PROXIES': [item.strip() for item in trusted_proxies.split(",") if item.strip()],
'SKIP_RSPAMD': os.getenv("SKIP_RSPAMD", "n").lower() in ("y", "yes"), 'SKIP_RSPAMD': os.getenv("SKIP_RSPAMD", "n").lower() in ("y", "yes"),
'SKIP_SOGO': os.getenv("SKIP_SOGO", "n").lower() in ("y", "yes"), 'SKIP_SOGO': os.getenv("SKIP_SOGO", "n").lower() in ("y", "yes"),
'NGINX_USE_PROXY_PROTOCOL': os.getenv("NGINX_USE_PROXY_PROTOCOL", "n").lower() in ("y", "yes"), 'NGINX_USE_PROXY_PROTOCOL': os.getenv("NGINX_USE_PROXY_PROTOCOL", "n").lower() in ("y", "yes"),
'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""), 'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""),
'ADDITIONAL_SERVER_NAMES': os.getenv("ADDITIONAL_SERVER_NAMES", "").replace(',', ' '), 'ADDITIONAL_SERVER_NAMES': [item.strip() for item in additional_server_names.split(",") if item.strip()],
'HTTP_PORT': os.getenv("HTTP_PORT", "80"), 'HTTP_PORT': os.getenv("HTTP_PORT", "80"),
'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"), 'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"),
'SOGOHOST': os.getenv("SOGOHOST", ipv4_network + ".248"), 'SOGOHOST': os.getenv("SOGOHOST", ipv4_network + ".248"),
'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"), 'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"),
'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"), 'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"),
'DISABLE_IPv6': os.getenv("DISABLE_IPv6", "n").lower() in ("y", "yes"), 'DISABLE_IPv6': os.getenv("DISABLE_IPv6", "n").lower() in ("y", "yes"),
'HTTP_REDIRECT': os.getenv("HTTP_REDIRECT", "n").lower() in ("y", "yes"),
} }
ssl_dir = '/etc/ssl/mail/' ssl_dir = '/etc/ssl/mail/'
+2 -2
View File
@@ -8,13 +8,13 @@ until ping ${PHPFPMHOST} -c1 > /dev/null; do
echo "Waiting for PHP..." echo "Waiting for PHP..."
sleep 1 sleep 1
done done
if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then if ! printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
until ping ${SOGOHOST} -c1 > /dev/null; do until ping ${SOGOHOST} -c1 > /dev/null; do
echo "Waiting for SOGo..." echo "Waiting for SOGo..."
sleep 1 sleep 1
done done
fi fi
if printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then if ! printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
until ping ${RSPAMDHOST} -c1 > /dev/null; do until ping ${RSPAMDHOST} -c1 > /dev/null; do
echo "Waiting for Rspamd..." echo "Waiting for Rspamd..."
sleep 1 sleep 1
+10 -2
View File
@@ -395,7 +395,7 @@ EOF
if [ ! -f /opt/postfix/conf/dns_blocklists.cf ]; then if [ ! -f /opt/postfix/conf/dns_blocklists.cf ]; then
cat <<EOF > /opt/postfix/conf/dns_blocklists.cf cat <<EOF > /opt/postfix/conf/dns_blocklists.cf
# This file can be edited. # This file can be edited.
# Delete this file and restart postfix container to revert any changes. # Delete this file and restart postfix container to revert any changes.
postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2 postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
hostkarma.junkemailfilter.com=127.0.0.1*-2 hostkarma.junkemailfilter.com=127.0.0.1*-2
@@ -403,7 +403,6 @@ postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
list.dnswl.org=127.0.[0..255].1*-4 list.dnswl.org=127.0.[0..255].1*-4
list.dnswl.org=127.0.[0..255].2*-6 list.dnswl.org=127.0.[0..255].2*-6
list.dnswl.org=127.0.[0..255].3*-8 list.dnswl.org=127.0.[0..255].3*-8
ix.dnsbl.manitu.net*2
bl.spamcop.net*2 bl.spamcop.net*2
bl.suomispam.net*2 bl.suomispam.net*2
hostkarma.junkemailfilter.com=127.0.0.2*3 hostkarma.junkemailfilter.com=127.0.0.2*3
@@ -417,6 +416,10 @@ postscreen_dnsbl_sites = wl.mailspike.net=127.0.0.[18;19;20]*-2
bl.mailspike.net=127.0.0.[10;11;12]*4 bl.mailspike.net=127.0.0.[10;11;12]*4
EOF EOF
fi fi
# Remove discontinued DNSBLs from existing dns_blocklists.cf
sed -i '/ix\.dnsbl\.manitu\.net\*2/d' /opt/postfix/conf/dns_blocklists.cf # Nixspam
DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S') DNSBL_CONFIG=$(grep -v '^#' /opt/postfix/conf/dns_blocklists.cf | grep '\S')
if [ ! -z "$DNSBL_CONFIG" ]; then if [ ! -z "$DNSBL_CONFIG" ]; then
@@ -507,6 +510,11 @@ chgrp -R postdrop /var/spool/postfix/public
chgrp -R postdrop /var/spool/postfix/maildrop chgrp -R postdrop /var/spool/postfix/maildrop
postfix set-permissions postfix set-permissions
# Checking if there is a leftover of a crashed postfix container before starting a new one
if [ -e /var/spool/postfix/pid/master.pid ]; then
rm -rf /var/spool/postfix/pid/master.pid
fi
# Check Postfix configuration # Check Postfix configuration
postconf -c /opt/postfix/conf > /dev/null postconf -c /opt/postfix/conf > /dev/null
@@ -18,6 +18,7 @@ stdout_logfile_maxbytes=0
stderr_logfile=/dev/stderr stderr_logfile=/dev/stderr
stderr_logfile_maxbytes=0 stderr_logfile_maxbytes=0
autorestart=true autorestart=true
startsecs=10
[eventlistener:processes] [eventlistener:processes]
command=/usr/local/sbin/stop-supervisor.sh command=/usr/local/sbin/stop-supervisor.sh
+1 -1
View File
@@ -2,7 +2,7 @@ FROM debian:bookworm-slim
LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ARG RSPAMD_VER=rspamd_3.10.2-1~b8a232043 ARG RSPAMD_VER=rspamd_3.11.0-2~90a175b45
ARG CODENAME=bookworm ARG CODENAME=bookworm
ENV LC_ALL=C ENV LC_ALL=C
+3 -4
View File
@@ -4,7 +4,7 @@ LABEL maintainer="The Infrastructure Company GmbH <info@servercow.de>"
ARG DEBIAN_FRONTEND=noninteractive ARG DEBIAN_FRONTEND=noninteractive
ARG DEBIAN_VERSION=bookworm ARG DEBIAN_VERSION=bookworm
ARG SOGO_DEBIAN_REPOSITORY=http://www.axis.cz/linux/debian ARG SOGO_DEBIAN_REPOSITORY=https://packagingv2.sogo.nu/sogo-nightly-debian/
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$ # renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=^(?<version>.*)$
ARG GOSU_VERSION=1.17 ARG GOSU_VERSION=1.17
ENV LC_ALL=C ENV LC_ALL=C
@@ -33,9 +33,8 @@ RUN echo "Building from repository $SOGO_DEBIAN_REPOSITORY" \
&& gosu nobody true \ && gosu nobody true \
&& mkdir /usr/share/doc/sogo \ && mkdir /usr/share/doc/sogo \
&& touch /usr/share/doc/sogo/empty.sh \ && touch /usr/share/doc/sogo/empty.sh \
&& wget http://www.axis.cz/linux/debian/axis-archive-keyring.deb -O /tmp/axis-archive-keyring.deb \ && wget -O- https://keys.openpgp.org/vks/v1/by-fingerprint/74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 | gpg --dearmor | apt-key add - \
&& apt install -y /tmp/axis-archive-keyring.deb \ && echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} ${DEBIAN_VERSION} main" > /etc/apt/sources.list.d/sogo.list \
&& echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} ${DEBIAN_VERSION} sogo-v5" > /etc/apt/sources.list.d/sogo.list \
&& apt-get update && apt-get install -y --no-install-recommends \ && apt-get update && apt-get install -y --no-install-recommends \
sogo \ sogo \
sogo-activesync \ sogo-activesync \
+3 -3
View File
@@ -30,7 +30,7 @@ if [[ "${MASTER}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view" mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} -e "DROP VIEW IF EXISTS sogo_view"
while [[ ${VIEW_OK} != 'OK' ]]; do while [[ ${VIEW_OK} != 'OK' ]]; do
mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF mysql --socket=/var/run/mysqld/mysqld.sock -u ${DBUSER} -p${DBPASS} ${DBNAME} << EOF
CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) AS CREATE VIEW sogo_view (c_uid, domain, c_name, c_password, c_cn, mail, aliases, ad_aliases, ext_acl, kind, multiple_bookings) AS
SELECT SELECT
mailbox.username, mailbox.username,
mailbox.domain, mailbox.domain,
@@ -240,8 +240,8 @@ chmod 600 /var/lib/sogo/GNUstep/Defaults/sogod.plist
# fi # fi
#fi #fi
# Copy logo, if any # Rename custom logo, if any
[[ -f /etc/sogo/sogo-full.svg ]] && cp /etc/sogo/sogo-full.svg /usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg [[ -f /etc/sogo/sogo-full.svg ]] && mv /etc/sogo/sogo-full.svg /etc/sogo/custom-fulllogo.svg
# Rsync web content # Rsync web content
echo "Syncing web content with named volume" echo "Syncing web content with named volume"
+6 -6
View File
@@ -1,8 +1,8 @@
-----BEGIN DH PARAMETERS----- -----BEGIN DH PARAMETERS-----
MIIBCAKCAQEA9iHB0CRDhV8wfBgqnmvuJpl0fzL3qL75R4ZvQHlfMNLrxuIz2x9D MIIBCAKCAQEA//////////+t+FRYortKmq/cViAnPTzx2LnFg84tNpWp4TZBFGQz
9zcDhPcBTVzV5Ay0AAkke4wP6r6wDQqXqBP4Y8IOkYAyLh3jM40jfHQzQt+5JdQl +8yTnc4kmz75fS/jY2MMddj2gbICrsRhetPfHtXV/WVhJDP1H18GbtCFY2VVPe0a
ond3kiscBsFOch/vMfSLMu3lAb0YhPNTvrxhMz7LcVAWYl82swASupdiKR+MgaQr 87VXE15/V8k1mE8McODmi3fipona8+/och3xWKE2rec1MKzKT0g6eXq8CrGCsyT7
XsugpmDKsHW60VmIM9B7K9Y+rNHwvMWkmISd0KxA8oOy1WJvsVEissMALZDE3c4w YdEIqUuyyOP7uWrat2DX9GgdT0Kj3jlN9K5W7edjcrsZCwenyO4KbXCeAvzhzffi
2xHmO2lXxgEx3aez28736t4m/KW3g9Zr31a1M0KusmfY//fGkPk4NUrLBOS2xrgp 7MA0BM0oNC9hkXL+nOmFg/+OTxIy7vKBg8P+OxtMb61zO7X8vC7CIAXFjvGDfRaD
Y/rG1qSBdcVyerM0Ki93qCyHKYu4ene0OwIBAg== ssbzSibBsu/6iGtCOGEoXJf//////////wIBAg==
-----END DH PARAMETERS----- -----END DH PARAMETERS-----
+1
View File
@@ -278,6 +278,7 @@ imap_max_line_length = 2 M
#auth_cache_negative_ttl = 0 #auth_cache_negative_ttl = 0
#auth_cache_ttl = 30 s #auth_cache_ttl = 30 s
#auth_cache_size = 2 M #auth_cache_size = 2 M
auth_verbose_passwords = sha1:6
service replicator { service replicator {
process_min_avail = 1 process_min_avail = 1
} }
+2 -2
View File
@@ -1,7 +1,7 @@
[mysqld] [mysqld]
character-set-client-handshake = FALSE character-set-client-handshake = FALSE
character-set-server = utf8mb4 character-set-server = utf8mb4
collation-server = utf8mb4_unicode_ci collation-server = utf8mb4_general_ci
#innodb_file_per_table = TRUE #innodb_file_per_table = TRUE
#innodb_file_format = barracuda #innodb_file_format = barracuda
#innodb_large_prefix = TRUE #innodb_large_prefix = TRUE
@@ -20,7 +20,7 @@ thread_cache_size = 8
query_cache_type = 0 query_cache_type = 0
query_cache_size = 0 query_cache_size = 0
max_heap_table_size = 48M max_heap_table_size = 48M
thread_stack = 192K thread_stack = 256K
skip-host-cache skip-host-cache
skip-name-resolve skip-name-resolve
log-warnings = 0 log-warnings = 0
+63 -2
View File
@@ -41,25 +41,80 @@ http {
https https; https https;
} }
# Default {% if HTTP_REDIRECT %}
# HTTP to HTTPS redirect
server {
root /web;
listen {{ HTTP_PORT }} default_server;
listen [::]:{{ HTTP_PORT }} default_server;
server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES | join(' ') }};
if ( $request_uri ~* "%0A|%0D" ) { return 403; }
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
location / {
return 301 https://$host$uri$is_args$args;
}
}
{%endif%}
# Default Server Name
server { server {
listen 127.0.0.1:65510; # sogo-auth verify internal listen 127.0.0.1:65510; # sogo-auth verify internal
{% if not HTTP_REDIRECT %}
listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{% if not DISABLE_IPv6 %} {% if not DISABLE_IPv6 %}
{% if not HTTP_REDIRECT %}
listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{%endif%} {%endif%}
http2 on; http2 on;
ssl_certificate /etc/ssl/mail/cert.pem; ssl_certificate /etc/ssl/mail/cert.pem;
ssl_certificate_key /etc/ssl/mail/key.pem; ssl_certificate_key /etc/ssl/mail/key.pem;
server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.* {{ ADDITIONAL_SERVER_NAMES }}; server_name {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.*;
include /etc/nginx/includes/sites-default.conf; include /etc/nginx/includes/sites-default.conf;
} }
# Additional Server Names
{% for SERVER_NAME in ADDITIONAL_SERVER_NAMES %}
server {
listen 127.0.0.1:65510; # sogo-auth verify internal
{% if not HTTP_REDIRECT %}
listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{% if not DISABLE_IPv6 %}
{% if not HTTP_REDIRECT %}
listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{%endif%}
http2 on;
ssl_certificate /etc/ssl/mail/cert.pem;
ssl_certificate_key /etc/ssl/mail/key.pem;
server_name {{ SERVER_NAME }};
include /etc/nginx/includes/sites-default.conf;
}
{% endfor %}
# rspamd dynmaps: # rspamd dynmaps:
server { server {
listen 8081; listen 8081;
@@ -106,12 +161,18 @@ http {
{% for cert in valid_cert_dirs %} {% for cert in valid_cert_dirs %}
server { server {
{% if not HTTP_REDIRECT %}
listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; listen {{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; listen {{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{% if not DISABLE_IPv6 %} {% if not DISABLE_IPv6 %}
{% if not HTTP_REDIRECT %}
listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%}; listen [::]:{{ HTTP_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%};
{%endif%}
listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl; listen [::]:{{ HTTPS_PORT }}{% if NGINX_USE_PROXY_PROTOCOL %} proxy_protocol{%endif%} ssl;
{%endif%} {%endif%}
http2 on; http2 on;
ssl_certificate {{ cert.cert_path }}cert.pem; ssl_certificate {{ cert.cert_path }}cert.pem;
@@ -52,10 +52,12 @@ set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12; set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16; set_real_ip_from 192.168.0.0/16;
set_real_ip_from fc00::/7; set_real_ip_from fc00::/7;
{% if not TRUSTED_NETWORK %} {% for TRUSTED_PROXY in TRUSTED_PROXIES %}
set_real_ip_from {{ TRUSTED_PROXY }};
{% endfor %}
{% if not NGINX_USE_PROXY_PROTOCOL %}
real_ip_header X-Forwarded-For; real_ip_header X-Forwarded-For;
{% else %} {% else %}
set_real_ip_from {{ TRUSTED_NETWORK }};
real_ip_header proxy_protocol; real_ip_header proxy_protocol;
{% endif %} {% endif %}
real_ip_recursive on; real_ip_recursive on;
@@ -137,13 +139,22 @@ location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
{% if not SKIP_RSPAMD %} {% if not SKIP_RSPAMD %}
location /rspamd/ { location /rspamd/ {
location /rspamd/auth {
# proxy_pass is not inherited
proxy_pass http://{{ RSPAMDHOST }}:11334/auth;
proxy_intercept_errors on;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
proxy_redirect off;
error_page 401 /_rspamderror.php;
}
proxy_pass http://{{ RSPAMDHOST }}:11334/; proxy_pass http://{{ RSPAMDHOST }}:11334/;
proxy_set_header Host $http_host; proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%}; proxy_set_header X-Forwarded-For {% if not NGINX_USE_PROXY_PROTOCOL %}$proxy_add_x_forwarded_for{% else %}$proxy_protocol_addr{%endif%};
proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%}; proxy_set_header X-Real-IP {% if not NGINX_USE_PROXY_PROTOCOL %}$remote_addr{% else %}$proxy_protocol_addr{%endif%};
proxy_redirect off; proxy_redirect off;
proxy_intercept_errors on;
error_page 401 /_rspamderror.php;
} }
{% endif %} {% endif %}
+2 -3
View File
@@ -162,10 +162,9 @@ transport_maps = pcre:/opt/postfix/conf/custom_transport.pcre,
proxy:mysql:/opt/postfix/conf/sql/mysql_relay_ne.cf, proxy:mysql:/opt/postfix/conf/sql/mysql_relay_ne.cf,
proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf proxy:mysql:/opt/postfix/conf/sql/mysql_transport_maps.cf
smtp_sasl_auth_soft_bounce = no smtp_sasl_auth_soft_bounce = no
postscreen_discard_ehlo_keywords = silent-discard, dsn, chunking postscreen_discard_ehlo_keywords = chunking, silent-discard, smtputf8, dsn
smtpd_discard_ehlo_keywords = chunking, silent-discard smtpd_discard_ehlo_keywords = chunking, silent-discard, smtputf8
compatibility_level = 3.7 compatibility_level = 3.7
smtputf8_enable = no
# Define protocols for SMTPS and submission service # Define protocols for SMTPS and submission service
submission_smtpd_tls_mandatory_protocols = >=TLSv1.2 submission_smtpd_tls_mandatory_protocols = >=TLSv1.2
smtps_smtpd_tls_mandatory_protocols = >=TLSv1.2 smtps_smtpd_tls_mandatory_protocols = >=TLSv1.2
+15 -18
View File
@@ -1,6 +1,6 @@
# Whitelist generated by Postwhite v3.4 on Wed Jan 1 00:18:52 UTC 2025 # Whitelist generated by Postwhite v3.4 on Sat Feb 1 00:18:03 UTC 2025
# https://github.com/stevejenkins/postwhite/ # https://github.com/stevejenkins/postwhite/
# 2014 total rules # 1984 total rules
2a00:1450:4000::/36 permit 2a00:1450:4000::/36 permit
2a01:111:f400::/48 permit 2a01:111:f400::/48 permit
2a01:111:f403:8000::/50 permit 2a01:111:f403:8000::/50 permit
@@ -19,10 +19,6 @@
8.20.114.31 permit 8.20.114.31 permit
8.25.194.0/23 permit 8.25.194.0/23 permit
8.25.196.0/23 permit 8.25.196.0/23 permit
8.39.54.0/23 permit
8.39.54.250/31 permit
8.40.222.0/23 permit
8.40.222.250/31 permit
10.162.0.0/16 permit 10.162.0.0/16 permit
12.130.86.238 permit 12.130.86.238 permit
13.110.208.0/21 permit 13.110.208.0/21 permit
@@ -98,6 +94,7 @@
27.123.206.76/30 permit 27.123.206.76/30 permit
27.123.206.80/28 permit 27.123.206.80/28 permit
31.25.48.222 permit 31.25.48.222 permit
31.47.251.17 permit
34.195.217.107 permit 34.195.217.107 permit
34.212.163.75 permit 34.212.163.75 permit
34.215.104.144 permit 34.215.104.144 permit
@@ -110,6 +107,7 @@
35.191.0.0/16 permit 35.191.0.0/16 permit
35.205.92.9 permit 35.205.92.9 permit
35.242.169.159 permit 35.242.169.159 permit
37.188.97.188 permit
37.218.248.47 permit 37.218.248.47 permit
37.218.249.47 permit 37.218.249.47 permit
37.218.251.62 permit 37.218.251.62 permit
@@ -448,6 +446,7 @@
69.171.244.0/23 permit 69.171.244.0/23 permit
70.37.151.128/25 permit 70.37.151.128/25 permit
70.42.149.35 permit 70.42.149.35 permit
72.3.185.0/24 permit
72.14.192.0/18 permit 72.14.192.0/18 permit
72.21.192.0/19 permit 72.21.192.0/19 permit
72.21.217.142 permit 72.21.217.142 permit
@@ -508,6 +507,9 @@
72.30.239.228/31 permit 72.30.239.228/31 permit
72.30.239.244/30 permit 72.30.239.244/30 permit
72.30.239.248/31 permit 72.30.239.248/31 permit
72.32.154.0/24 permit
72.32.217.0/24 permit
72.32.243.0/24 permit
72.52.72.32/28 permit 72.52.72.32/28 permit
74.6.128.0/24 permit 74.6.128.0/24 permit
74.6.129.0/24 permit 74.6.129.0/24 permit
@@ -623,6 +625,7 @@
89.22.108.0/24 permit 89.22.108.0/24 permit
91.211.240.0/22 permit 91.211.240.0/22 permit
94.169.2.0/23 permit 94.169.2.0/23 permit
94.236.119.0/26 permit
94.245.112.0/27 permit 94.245.112.0/27 permit
94.245.112.10/31 permit 94.245.112.10/31 permit
95.131.104.0/21 permit 95.131.104.0/21 permit
@@ -1121,6 +1124,7 @@
103.28.42.0/24 permit 103.28.42.0/24 permit
103.151.192.0/23 permit 103.151.192.0/23 permit
103.168.172.128/27 permit 103.168.172.128/27 permit
103.237.104.0/22 permit
104.43.243.237 permit 104.43.243.237 permit
104.44.112.128/25 permit 104.44.112.128/25 permit
104.47.0.0/17 permit 104.47.0.0/17 permit
@@ -1335,6 +1339,8 @@
130.61.9.72 permit 130.61.9.72 permit
130.162.39.83 permit 130.162.39.83 permit
130.211.0.0/22 permit 130.211.0.0/22 permit
130.248.172.0/24 permit
130.248.173.0/24 permit
131.253.30.0/24 permit 131.253.30.0/24 permit
131.253.121.0/26 permit 131.253.121.0/26 permit
132.145.13.209 permit 132.145.13.209 permit
@@ -1476,9 +1482,6 @@
163.114.135.16 permit 163.114.135.16 permit
164.152.23.32 permit 164.152.23.32 permit
164.177.132.168/30 permit 164.177.132.168/30 permit
165.173.128.0/24 permit
165.173.180.250/31 permit
165.173.182.250/31 permit
166.78.68.0/22 permit 166.78.68.0/22 permit
166.78.68.221 permit 166.78.68.221 permit
166.78.69.169 permit 166.78.69.169 permit
@@ -1507,12 +1510,6 @@
168.245.12.252 permit 168.245.12.252 permit
168.245.46.9 permit 168.245.46.9 permit
168.245.127.231 permit 168.245.127.231 permit
169.148.129.0/24 permit
169.148.131.0/24 permit
169.148.142.10 permit
169.148.144.0/25 permit
169.148.144.10 permit
169.148.146.0/23 permit
170.10.128.0/24 permit 170.10.128.0/24 permit
170.10.129.0/24 permit 170.10.129.0/24 permit
170.10.132.56/29 permit 170.10.132.56/29 permit
@@ -1553,6 +1550,7 @@
183.240.219.64/29 permit 183.240.219.64/29 permit
185.4.120.0/22 permit 185.4.120.0/22 permit
185.12.80.0/22 permit 185.12.80.0/22 permit
185.28.196.0/22 permit
185.58.84.93 permit 185.58.84.93 permit
185.80.93.204 permit 185.80.93.204 permit
185.80.93.227 permit 185.80.93.227 permit
@@ -1618,6 +1616,7 @@
192.18.139.154 permit 192.18.139.154 permit
192.18.145.36 permit 192.18.145.36 permit
192.18.152.58 permit 192.18.152.58 permit
192.28.128.0/18 permit
192.29.103.128/25 permit 192.29.103.128/25 permit
192.30.252.0/22 permit 192.30.252.0/22 permit
192.161.144.0/20 permit 192.161.144.0/20 permit
@@ -1658,6 +1657,7 @@
198.244.60.0/22 permit 198.244.60.0/22 permit
198.245.80.0/20 permit 198.245.80.0/20 permit
198.245.81.0/24 permit 198.245.81.0/24 permit
199.15.212.0/22 permit
199.15.213.187 permit 199.15.213.187 permit
199.15.226.37 permit 199.15.226.37 permit
199.16.156.0/22 permit 199.16.156.0/22 permit
@@ -1972,9 +1972,6 @@
2603:1030:20e:3::23c permit 2603:1030:20e:3::23c permit
2603:1030:b:3::152 permit 2603:1030:b:3::152 permit
2603:1030:c02:8::14 permit 2603:1030:c02:8::14 permit
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
2607:13c0:0004:0000:0000:0000:0000:0000/116 permit
2607:f8b0:4000::/36 permit 2607:f8b0:4000::/36 permit
2620:109:c003:104::/64 permit 2620:109:c003:104::/64 permit
2620:109:c003:104::215 permit 2620:109:c003:104::215 permit
+5
View File
@@ -2,6 +2,11 @@
cat <<EOF > /redis.conf cat <<EOF > /redis.conf
requirepass $REDISPASS requirepass $REDISPASS
user quota_notify on nopass ~QW_* -@all +get +hget +ping
EOF EOF
if [ -n "$REDISMASTERPASS" ]; then
echo "masterauth $REDISMASTERPASS" >> /redis.conf
fi
exec redis-server /redis.conf exec redis-server /redis.conf
+1
View File
@@ -3,6 +3,7 @@ dns {
} }
map_watch_interval = 30s; map_watch_interval = 30s;
task_timeout = 30s; task_timeout = 30s;
enable_mime_utf = true;
disable_monitoring = true; disable_monitoring = true;
# In case a task times out (like DNS lookup), soft reject the message # In case a task times out (like DNS lookup), soft reject the message
# instead of silently accepting the message without further processing. # instead of silently accepting the message without further processing.
Binary file not shown.

After

Width:  |  Height:  |  Size: 2.2 KiB

+44
View File
@@ -0,0 +1,44 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY st0 "fill:#50BD37;">
]>
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="640px" height="350px" viewBox="78.712 58.488 640 350" style="enable-background:new 78.712 58.488 640 350;"
xml:space="preserve">
<path style="&st0;" d="M648.541,145.679c-9.947,0-17.009-7.278-17.009-17.048c0-9.777,7.062-17.057,17.009-17.057
c10.024,0,17.086,7.279,17.086,17.057C665.627,138.401,658.565,145.679,648.541,145.679z M648.511,94.893
c-19.693,0-33.679,14.4-33.679,33.738c0,19.33,13.985,33.729,33.679,33.729c19.822,0,33.808-14.4,33.808-33.729
C682.318,109.293,668.333,94.893,648.511,94.893z M648.482,179.843c-29.889,0-51.123-21.868-51.123-51.212
c0-29.353,21.234-51.209,51.123-51.209c30.082,0,51.307,21.856,51.307,51.209C699.789,157.975,678.564,179.843,648.482,179.843z
M648.442,58.488c-40.929,0-69.995,29.946-69.995,70.143c0,40.189,29.066,70.125,69.995,70.125c41.194,0,70.27-29.937,70.27-70.125
C718.712,88.434,689.637,58.488,648.442,58.488z M158.166,183.902l-21.018-5.008c-19.131-4.396-28.849-9.413-28.849-23.21
c0-15.684,15.99-21.965,30.419-21.965c14.667,0,25.382,7.329,31.693,18.737c0.02,0.048,0.051,0.097,0.09,0.157
c0.127,0.247,0.276,0.484,0.403,0.731l0.03-0.02c1.985,3.002,5.323,5.008,8.919,5.008c6.122,0,10.558-4.425,10.558-10.547
c0-2.341-0.504-4.82-1.601-6.688c-10.764-18.302-28.513-26.192-48.838-26.192c-27.594,0-54.262,13.797-54.262,44.218
c0,27.921,27.605,36.079,37.64,38.578l20.069,4.71c15.368,3.763,27.912,8.791,27.912,23.517c0,16.938-17.561,23.943-34.499,23.943
c-17.245,0-30.015-9.37-38.814-22.37h-0.01c-1.956-3-4.988-4.328-8.702-4.328c-5.984,0-10.805,5.185-10.587,11.162
c0.098,2.438,0.909,4.637,2.153,6.405c13.787,20.633,33.728,28.41,55.96,28.41c28.543,0,57.085-13.143,57.085-45.132
C193.918,203.325,178.551,188.613,158.166,183.902z M298.479,250.312c-33.866,0-55.199-25.403-55.199-58.331
c0-32.939,21.333-58.343,55.199-58.343c34.192,0,55.516,25.403,55.516,58.343C353.996,224.91,332.672,250.312,298.479,250.312z
M298.479,114.823c-45.471,0-77.777,32.93-77.777,77.158c0,44.217,32.306,77.146,77.777,77.146
c45.786,0,78.093-32.929,78.093-77.146C376.572,147.753,344.266,114.823,298.479,114.823z M518.715,234.312
c-0.771,0.74-1.549,1.472-2.399,2.175c-1.106,1.014-2.391,2.112-3.854,3.208c-8.829,6.391-19.979,10.094-33.017,10.094
c-33.876,0-55.198-25.402-55.198-58.332c0-32.939,21.322-58.342,55.198-58.342c34.183,0,55.506,25.403,55.506,58.342
C534.951,208.653,529.135,223.774,518.715,234.312z M468.097,317.938c2.528,0,5.146-0.168,7.863-0.504
c5.018-0.631,9.588-0.909,13.729-0.909c19.24,0.109,29.036,5.7,34.943,12.158c5.895,6.499,8.168,15.311,8.158,22.796
c0.01,3.586-0.555,6.795-1.177,8.721c-2.944,8.93-8.888,15.002-17.996,19.576c-9.035,4.484-21.095,6.777-33.707,6.757
c-4.514,0-9.105-0.288-13.639-0.831c-8.573-0.987-19.911-4.671-28.13-11.093c-4.138-3.199-6.458-6.991-8.858-11.485
c-2.379-4.514-2.783-9.748-2.783-16.442v-0.742c0-12.346,4.84-20.544,11.051-26.5c3.07-2.904,5.69-5.064,7.99-6.438
c0.366-0.218,0.438-0.416,0.755-0.593C452.39,316.014,459.684,317.968,468.097,317.938z M479.445,114.301
c-45.471,0-77.786,32.929-77.786,77.157c0,29.887,14.765,54.598,38.378,67.489c-0.314,0.314-0.621,0.641-0.916,0.966
c-6.104,6.687-9.226,15.25-9.236,23.913c-0.008,3.821,0.624,7.741,1.977,11.494c-3.062,1.956-6.717,4.634-10.46,8.147
c-9.026,8.408-18.734,22.541-19.021,42.097c-0.01,0.454-0.01,0.829-0.01,1.118c-0.01,10.071,2.379,19.157,6.459,26.774
c6.133,11.466,15.683,19.445,25.539,24.77c9.917,5.334,20.257,8.166,29.273,9.274c5.373,0.643,10.826,0.988,16.268,0.988
c15.151-0.02,30.261-2.578,43.409-9.019c13.085-6.34,24.333-17.253,29.192-32.562c1.443-4.553,2.212-9.719,2.231-15.428
c-0.02-11.595-3.349-25.759-13.767-37.452c-10.421-11.734-27.654-19.566-51.288-19.459c-5.138,0-10.606,0.356-16.426,1.078
c-1.877,0.227-3.596,0.334-5.166,0.334c-7.239-0.048-10.872-2.053-13.036-4.098c-2.133-2.084-3.2-4.839-3.229-8.058
c-0.01-3.28,1.284-6.727,3.467-9.078c2.231-2.332,5.008-3.91,9.846-3.97c0.436,0,0.9,0.01,1.374,0.05
c3.101,0.216,6.112,0.325,9.037,0.325c24.188,0.047,42.38-7.448,54.756-17.759c12.415-10.312,18.971-22.854,22.071-32.76l-0.04-0.01
c3.37-8.899,5.197-18.715,5.197-29.166C557.539,147.229,525.234,114.301,479.445,114.301z"/>
</svg>

After

Width:  |  Height:  |  Size: 4.4 KiB

+16
View File
@@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 16.0.0, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd" [
<!ENTITY st0 "fill:#50BD37;">
]>
<svg version="1.1" id="SOGo" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
width="140.263px" height="140.269px" viewBox="499.737 0 140.263 140.269"
style="enable-background:new 499.737 0 140.263 140.269;" xml:space="preserve">
<path style="&st0;" d="M569.697,87.024c-9.928,0-16.975-7.264-16.975-17.017c0-9.757,7.047-17.022,16.975-17.022
c10.006,0,17.054,7.265,17.054,17.022C586.751,79.76,579.703,87.024,569.697,87.024z M569.667,36.335
c-19.657,0-33.614,14.372-33.614,33.673c0,19.294,13.955,33.667,33.614,33.667c19.787,0,33.745-14.372,33.745-33.667
C603.411,50.707,589.454,36.335,569.667,36.335z M569.639,121.123c-29.833,0-51.025-21.825-51.025-51.115
c0-29.296,21.192-51.111,51.025-51.111c30.025,0,51.213,21.815,51.213,51.111C620.852,99.298,599.664,121.123,569.639,121.123z
M569.602,0c-40.854,0-69.864,29.889-69.864,70.007c0,40.112,29.01,69.993,69.864,69.993c41.116,0,70.136-29.88,70.136-69.993
C639.737,29.889,610.719,0,569.602,0z"/>
</svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

+3
View File
@@ -166,6 +166,9 @@ if (isset($_SESSION['mailcow_cc_role'])) {
if (substr($result['recipient_map_old'], 0, 1) == '@') { if (substr($result['recipient_map_old'], 0, 1) == '@') {
$result['recipient_map_old'] = substr($result['recipient_map_old'], 1); $result['recipient_map_old'] = substr($result['recipient_map_old'], 1);
} }
if (substr($result['recipient_map_new'], 0, 1) == '@') {
$result['recipient_map_new'] = substr($result['recipient_map_new'], 1);
}
$template = 'edit/recipient_map.twig'; $template = 'edit/recipient_map.twig';
$template_data = ['map' => $map]; $template_data = ['map' => $map];
} }
@@ -270,6 +270,9 @@ function recipient_map($_action, $_data = null, $attr = null) {
$old_dest = substr($old_dest, 1); $old_dest = substr($old_dest, 1);
} }
$new_dest = strtolower(trim($_data['recipient_map_new'])); $new_dest = strtolower(trim($_data['recipient_map_new']));
if (substr($new_dest, 0, 1) == '@') {
$new_dest = substr($new_dest, 1);
}
$active = intval($_data['active']); $active = intval($_data['active']);
if (is_valid_domain_name($old_dest)) { if (is_valid_domain_name($old_dest)) {
$old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46); $old_dest_sane = '@' . idn_to_ascii($old_dest, 0, INTL_IDNA_VARIANT_UTS46);
@@ -285,7 +288,13 @@ function recipient_map($_action, $_data = null, $attr = null) {
); );
return false; return false;
} }
if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) { if (is_valid_domain_name($new_dest)) {
$new_dest_sane = '@' . idn_to_ascii($new_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
$new_dest_sane = $new_dest;
}
else {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
@@ -308,7 +317,7 @@ function recipient_map($_action, $_data = null, $attr = null) {
(:old_dest, :new_dest, :active)"); (:old_dest, :new_dest, :active)");
$stmt->execute(array( $stmt->execute(array(
':old_dest' => $old_dest_sane, ':old_dest' => $old_dest_sane,
':new_dest' => $new_dest, ':new_dest' => $new_dest_sane,
':active' => $active ':active' => $active
)); ));
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
@@ -325,6 +334,9 @@ function recipient_map($_action, $_data = null, $attr = null) {
$active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active']; $active = (isset($_data['active'])) ? intval($_data['active']) : $is_now['active'];
$new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new']; $new_dest = (!empty($_data['recipient_map_new'])) ? $_data['recipient_map_new'] : $is_now['recipient_map_new'];
$old_dest = (!empty($_data['recipient_map_old'])) ? $_data['recipient_map_old'] : $is_now['recipient_map_old']; $old_dest = (!empty($_data['recipient_map_old'])) ? $_data['recipient_map_old'] : $is_now['recipient_map_old'];
if (substr($new_dest, 0, 1) == '@') {
$new_dest = substr($new_dest, 1);
}
if (substr($old_dest, 0, 1) == '@') { if (substr($old_dest, 0, 1) == '@') {
$old_dest = substr($old_dest, 1); $old_dest = substr($old_dest, 1);
} }
@@ -351,7 +363,13 @@ function recipient_map($_action, $_data = null, $attr = null) {
); );
continue; continue;
} }
if (!filter_var($new_dest, FILTER_VALIDATE_EMAIL)) { if (is_valid_domain_name($new_dest)) {
$new_dest_sane = '@' . idn_to_ascii($new_dest, 0, INTL_IDNA_VARIANT_UTS46);
}
elseif (filter_var($new_dest, FILTER_VALIDATE_EMAIL)) {
$new_dest_sane = $new_dest;
}
else {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data, $_attr), 'log' => array(__FUNCTION__, $_action, $_data, $_attr),
@@ -378,7 +396,7 @@ function recipient_map($_action, $_data = null, $attr = null) {
WHERE `id`= :id"); WHERE `id`= :id");
$stmt->execute(array( $stmt->execute(array(
':old_dest' => $old_dest_sane, ':old_dest' => $old_dest_sane,
':new_dest' => $new_dest, ':new_dest' => $new_dest_sane,
':active' => $active, ':active' => $active,
':id' => $id ':id' => $id
)); ));
+19 -3
View File
@@ -2275,9 +2275,25 @@ function cors($action, $data = null) {
break; break;
} }
} }
function getBaseURL() { function getBaseURL($protocol = null) {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http'; // Get current server name
$host = $_SERVER['HTTP_HOST']; $host = strtolower($_SERVER['SERVER_NAME']);
// craft allowed server name list
$mailcow_hostname = strtolower(getenv("MAILCOW_HOSTNAME"));
$additional_server_names = strtolower(getenv("ADDITIONAL_SERVER_NAMES")) ?: "";
$additional_server_names = preg_replace('/\s+/', '', $additional_server_names);
$allowed_server_names = $additional_server_names !== "" ? explode(',', $additional_server_names) : array();
array_push($allowed_server_names, $mailcow_hostname);
// Fallback to MAILCOW HOSTNAME if current server name is not in allowed list
if (!in_array($host, $allowed_server_names)) {
$host = $mailcow_hostname;
}
if (!isset($protocol)) {
$protocol = isset($_SERVER['HTTPS']) && $_SERVER['HTTPS'] === 'on' ? 'https' : 'http';
}
$base_url = $protocol . '://' . $host; $base_url = $protocol . '://' . $host;
return $base_url; return $base_url;
+2 -2
View File
@@ -869,7 +869,7 @@
"recipient_map": "Mapa příjemce", "recipient_map": "Mapa příjemce",
"recipient_map_info": "Mapy příjemců slouží k nahrazení cílové adresy zprávy před doručením.", "recipient_map_info": "Mapy příjemců slouží k nahrazení cílové adresy zprávy před doručením.",
"recipient_map_new": "Nový přijemce", "recipient_map_new": "Nový přijemce",
"recipient_map_new_info": "Cílová adresa mapy příjemce musí být platná emailová adresa.", "recipient_map_new_info": "Cílová adresa mapy příjemce musí být emailová adresa nebo název domény.",
"recipient_map_old": "Původní příjemce", "recipient_map_old": "Původní příjemce",
"recipient_map_old_info": "Původní příjemce musí být platná emailová adresa nebo název domény.", "recipient_map_old_info": "Původní příjemce musí být platná emailová adresa nebo název domény.",
"recipient_maps": "Mapy příjemců", "recipient_maps": "Mapy příjemců",
@@ -1307,4 +1307,4 @@
"session_token": "Token formuláře není platný: Token mismatch", "session_token": "Token formuláře není platný: Token mismatch",
"session_ua": "Token formuláře není platný: User-Agent validation error" "session_ua": "Token formuláře není platný: User-Agent validation error"
} }
} }
+2 -2
View File
@@ -706,7 +706,7 @@
"recipient_map": "Modtagerkort", "recipient_map": "Modtagerkort",
"recipient_map_info": "Modtagerkort bruges til at erstatte destinationsadressen i en meddelelse, før den leveres.", "recipient_map_info": "Modtagerkort bruges til at erstatte destinationsadressen i en meddelelse, før den leveres.",
"recipient_map_new": "Ny modtager", "recipient_map_new": "Ny modtager",
"recipient_map_new_info": "Modtagerkortdestination skal være en gyldig e-mail-adresse.", "recipient_map_new_info": "Modtagerkortdestination skal være gyldige e-mail-adresser eller et domænenavn.",
"recipient_map_old": "Original modtager", "recipient_map_old": "Original modtager",
"recipient_map_old_info": "En modtager kortlægger den originale destination, skal være gyldige e-mail-adresser eller et domænenavn.", "recipient_map_old_info": "En modtager kortlægger den originale destination, skal være gyldige e-mail-adresser eller et domænenavn.",
"recipient_maps": "Modtagerkort", "recipient_maps": "Modtagerkort",
@@ -1089,4 +1089,4 @@
"first": "Først" "first": "Først"
} }
} }
} }
+2 -2
View File
@@ -881,7 +881,7 @@
"recipient_map": "Empfängerumschreibung", "recipient_map": "Empfängerumschreibung",
"recipient_map_info": "Empfängerumschreibung ersetzen den Empfänger einer E-Mail vor dem Versand.", "recipient_map_info": "Empfängerumschreibung ersetzen den Empfänger einer E-Mail vor dem Versand.",
"recipient_map_new": "Neuer Empfänger", "recipient_map_new": "Neuer Empfänger",
"recipient_map_new_info": "Der neue Empfänger muss eine E-Mail-Adresse sein.", "recipient_map_new_info": "Der neue Empfänger muss eine E-Mail-Adresse oder ein Domainname sein.",
"recipient_map_old": "Original-Empfänger", "recipient_map_old": "Original-Empfänger",
"recipient_map_old_info": "Der originale Empfänger muss eine E-Mail-Adresse oder ein Domainname sein.", "recipient_map_old_info": "Der originale Empfänger muss eine E-Mail-Adresse oder ein Domainname sein.",
"recipient_maps": "Empfängerumschreibungen", "recipient_maps": "Empfängerumschreibungen",
@@ -1336,4 +1336,4 @@
"hour": "Nachrichten / Stunde", "hour": "Nachrichten / Stunde",
"day": "Nachrichten / Tag" "day": "Nachrichten / Tag"
} }
} }
+3 -3
View File
@@ -887,9 +887,9 @@
"recipient_map": "Recipient map", "recipient_map": "Recipient map",
"recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.", "recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.",
"recipient_map_new": "New recipient", "recipient_map_new": "New recipient",
"recipient_map_new_info": "Recipient map destination must be a valid email address.", "recipient_map_new_info": "Recipient map destination must be a valid email addresses or a domain name.",
"recipient_map_old": "Original recipient", "recipient_map_old": "Original recipient",
"recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_map_old_info": "A recipient maps original destination must be a valid email addresses or a domain name.",
"recipient_maps": "Recipient maps", "recipient_maps": "Recipient maps",
"relay_all": "Relay all recipients", "relay_all": "Relay all recipients",
"relay_unknown": "Relay unknown mailboxes", "relay_unknown": "Relay unknown mailboxes",
@@ -1336,4 +1336,4 @@
"session_token": "Form token invalid: Token mismatch", "session_token": "Form token invalid: Token mismatch",
"session_ua": "Form token invalid: User-Agent validation error" "session_ua": "Form token invalid: User-Agent validation error"
} }
} }
+9 -4
View File
@@ -24,7 +24,9 @@
"protocol_access": "Cambiar protocolo de acceso", "protocol_access": "Cambiar protocolo de acceso",
"quarantine_category": "Cambiar categoría de las notificaciones de cuarentena", "quarantine_category": "Cambiar categoría de las notificaciones de cuarentena",
"domain_relayhost": "Cambiar relayhost por un dominio", "domain_relayhost": "Cambiar relayhost por un dominio",
"extend_sender_acl": "Permitir extender la ACL del remitente por direcciones externas" "extend_sender_acl": "Permitir extender la ACL del remitente por direcciones externas",
"pw_reset": "Permitir el reset de la contraseña del usario mailcow",
"sogo_access": "Permitir la gestión del acceso a SOGo"
}, },
"add": { "add": {
"activate_filter_warn": "Todos los demás filtros se desactivarán cuando este filtro se active.", "activate_filter_warn": "Todos los demás filtros se desactivarán cuando este filtro se active.",
@@ -95,7 +97,10 @@
"app_password": "Añadir contraseña para la app", "app_password": "Añadir contraseña para la app",
"public_comment": "Comentarios públicos", "public_comment": "Comentarios públicos",
"disable_login": "Desactivar login (el correo entrante seguirá activo)", "disable_login": "Desactivar login (el correo entrante seguirá activo)",
"comment_info": "Los comentarios privados no son visibles al usuario, mientras que los comentarios públicos aparecerán sobre la información general del usuario" "comment_info": "Los comentarios privados no son visibles al usuario, mientras que los comentarios públicos aparecerán sobre la información general del usuario",
"dry": "Simular la sincronización",
"private_comment": "Comentario privado",
"app_passwd_protocols": "Protocolos autorizados para la contraseña de la aplicación"
}, },
"admin": { "admin": {
"access": "Acceso", "access": "Acceso",
@@ -539,7 +544,7 @@
"recipient_map": "Regla de destinatario", "recipient_map": "Regla de destinatario",
"recipient_map_info": "Las reglas de destinatarios se utilizan para reemplazar la dirección de destino en un mensaje antes de que se entregue.", "recipient_map_info": "Las reglas de destinatarios se utilizan para reemplazar la dirección de destino en un mensaje antes de que se entregue.",
"recipient_map_new": "Destinatario nuevo", "recipient_map_new": "Destinatario nuevo",
"recipient_map_new_info": "El destino de la regla debe ser una dirección de correo válida.", "recipient_map_new_info": "El destino de la regla debe ser una dirección de correo electrónico válida o un nombre de dominio.",
"recipient_map_old": "Destinatario original", "recipient_map_old": "Destinatario original",
"recipient_map_old_info": "El destino original de una regla de destinatario debe ser una dirección de correo electrónico válida o un nombre de dominio.", "recipient_map_old_info": "El destino original de una regla de destinatario debe ser una dirección de correo electrónico válida o un nombre de dominio.",
"recipient_maps": "Reglas de destinatario", "recipient_maps": "Reglas de destinatario",
@@ -777,4 +782,4 @@
"fuzzy_learn_error": "Error aprendiendo hash: %s", "fuzzy_learn_error": "Error aprendiendo hash: %s",
"ip_invalid": "IP inválida omitida: %s" "ip_invalid": "IP inválida omitida: %s"
} }
} }
+2 -2
View File
@@ -607,7 +607,7 @@
"recipient_map": "Vastaanottajien yhdistämis määritykset", "recipient_map": "Vastaanottajien yhdistämis määritykset",
"recipient_map_info": "Vastaanottajan karttoja käytetään korvaamaan viestin kohde osoite ennen sen toimittamista.", "recipient_map_info": "Vastaanottajan karttoja käytetään korvaamaan viestin kohde osoite ennen sen toimittamista.",
"recipient_map_new": "Uusi vastaanottaja", "recipient_map_new": "Uusi vastaanottaja",
"recipient_map_new_info": "Vastaanottajan yhdistämis kartan kohteen on oltava kelvollinen sähköposti osoite.", "recipient_map_new_info": "Vastaanottajan yhdistämis kartan kohteen on oltava kelvollinen sähköposti osoite tai verkkotunnus alueen nimi.",
"recipient_map_old": "Alkuperäinen vastaanottaja", "recipient_map_old": "Alkuperäinen vastaanottaja",
"recipient_map_old_info": "Vastaanottajan yhdistämis määritysten alkuperäisen kohteen on oltava kelvollinen sähköposti osoite tai verkkotunnus alueen nimi.", "recipient_map_old_info": "Vastaanottajan yhdistämis määritysten alkuperäisen kohteen on oltava kelvollinen sähköposti osoite tai verkkotunnus alueen nimi.",
"recipient_maps": "Vastaanottajien yhdistämis määritykset", "recipient_maps": "Vastaanottajien yhdistämis määritykset",
@@ -906,4 +906,4 @@
"last": "Edellinen" "last": "Edellinen"
} }
} }
} }
+2 -2
View File
@@ -834,7 +834,7 @@
"recipient_map": "Carte du destinataire", "recipient_map": "Carte du destinataire",
"recipient_map_info": "Les cartes des destinataires sont utilisées pour remplacer ladresse de destination dun message avant sa livraison.", "recipient_map_info": "Les cartes des destinataires sont utilisées pour remplacer ladresse de destination dun message avant sa livraison.",
"recipient_map_new": "Nouveau destinataire", "recipient_map_new": "Nouveau destinataire",
"recipient_map_new_info": "La destination de la carte du destinataire doit être une adresse de courriel valide.", "recipient_map_new_info": "La destination de la carte du destinataire doit être une adresse de courriel valide ou un nom de domaine.",
"recipient_map_old": "Destinataire original", "recipient_map_old": "Destinataire original",
"recipient_map_old_info": "Une carte de destination originale doit être une adresse de courriel valide ou un nom de domaine.", "recipient_map_old_info": "Une carte de destination originale doit être une adresse de courriel valide ou un nom de domaine.",
"recipient_maps": "Cartes des bénéficiaires", "recipient_maps": "Cartes des bénéficiaires",
@@ -1335,4 +1335,4 @@
"hour": "msgs / heure", "hour": "msgs / heure",
"day": "msgs / jour" "day": "msgs / jour"
} }
} }
+3 -3
View File
@@ -822,9 +822,9 @@
"recipient_map": "Recipient map", "recipient_map": "Recipient map",
"recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.", "recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.",
"recipient_map_new": "New recipient", "recipient_map_new": "New recipient",
"recipient_map_new_info": "Recipient map destination must be a valid email address.", "recipient_map_new_info": "Recipient map destination must be a valid email addresses or a domain name.",
"recipient_map_old": "Original recipient", "recipient_map_old": "Original recipient",
"recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_map_old_info": "A recipient maps original destination must be a valid email addresses or a domain name.",
"recipient_maps": "Recipient maps", "recipient_maps": "Recipient maps",
"relay_all": "Trasmettere a tutti i destinatari", "relay_all": "Trasmettere a tutti i destinatari",
"remove": "Rimuovi", "remove": "Rimuovi",
@@ -1306,4 +1306,4 @@
}, },
"decimal": "." "decimal": "."
} }
} }
+1 -1
View File
@@ -887,7 +887,7 @@
"recipient_map": "受信者マップ", "recipient_map": "受信者マップ",
"recipient_map_info": "受信者マップは、メッセージが配信される前に宛先アドレスを置き換えるために使用されます。", "recipient_map_info": "受信者マップは、メッセージが配信される前に宛先アドレスを置き換えるために使用されます。",
"recipient_map_new": "新しい受信者", "recipient_map_new": "新しい受信者",
"recipient_map_new_info": "受信者マップの宛先は有効なメールアドレスである必要があります。", "recipient_map_new_info": "受信者マップの宛先は有効なメールアドレスまたはドメイン名である必要があります。",
"recipient_map_old": "元の受信者", "recipient_map_old": "元の受信者",
"recipient_map_old_info": "受信者マップの元の宛先は有効なメールアドレスまたはドメイン名である必要があります。", "recipient_map_old_info": "受信者マップの元の宛先は有効なメールアドレスまたはドメイン名である必要があります。",
"recipient_maps": "受信者マップ", "recipient_maps": "受信者マップ",
+3 -3
View File
@@ -673,9 +673,9 @@
"recipient_map": "Recipient map", "recipient_map": "Recipient map",
"recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.", "recipient_map_info": "Recipient maps are used to replace the destination address on a message before it is delivered.",
"recipient_map_new": "New recipient", "recipient_map_new": "New recipient",
"recipient_map_new_info": "Recipient map destination must be a valid email address.", "recipient_map_new_info": "Recipient map destination must be a valid email addresses or a domain name.",
"recipient_map_old": "Original recipient", "recipient_map_old": "Original recipient",
"recipient_map_old_info": "A recipient maps original destination must be valid email addresses or a domain name.", "recipient_map_old_info": "A recipient maps original destination must be a valid email addresses or a domain name.",
"recipient_maps": "Recipient maps", "recipient_maps": "Recipient maps",
"relay_all": "모든 수신자에게 릴레이", "relay_all": "모든 수신자에게 릴레이",
"remove": "Remove", "remove": "Remove",
@@ -1018,4 +1018,4 @@
"session_token": "Form token invalid: Token mismatch", "session_token": "Form token invalid: Token mismatch",
"session_ua": "Form token invalid: User-Agent validation error" "session_ua": "Form token invalid: User-Agent validation error"
} }
} }
+2 -2
View File
@@ -764,7 +764,7 @@
"recipient_map": "Ontvanger-map", "recipient_map": "Ontvanger-map",
"recipient_map_info": "Ontvanger-maps worden gebruikt om het doeladres van een bericht te vervangen voordat het in een mailbox terecht komt.", "recipient_map_info": "Ontvanger-maps worden gebruikt om het doeladres van een bericht te vervangen voordat het in een mailbox terecht komt.",
"recipient_map_new": "Nieuwe ontvanger", "recipient_map_new": "Nieuwe ontvanger",
"recipient_map_new_info": "De bestemming van een ontvanger-map dient een geldig mailadres te zijn.", "recipient_map_new_info": "De bestemming van een ontvanger-map dient een geldig mailadres of domeinnaam te zijn.",
"recipient_map_old": "Oorspronkelijke ontvanger", "recipient_map_old": "Oorspronkelijke ontvanger",
"recipient_map_old_info": "De oorspronkelijke bestemming van een ontvanger-map dient een geldig mailadres of domeinnaam te zijn.", "recipient_map_old_info": "De oorspronkelijke bestemming van een ontvanger-map dient een geldig mailadres of domeinnaam te zijn.",
"recipient_maps": "Ontvanger-maps", "recipient_maps": "Ontvanger-maps",
@@ -1165,4 +1165,4 @@
"search": "Zoeken:", "search": "Zoeken:",
"zeroRecords": "Geen overeenkomsten gevonden" "zeroRecords": "Geen overeenkomsten gevonden"
} }
} }
+2 -2
View File
@@ -882,7 +882,7 @@
"recipient_map": "Mapa do destinatário", "recipient_map": "Mapa do destinatário",
"recipient_map_info": "Os mapas de destinatários são usados para substituir o endereço de destino em uma mensagem antes que ela seja entregue.", "recipient_map_info": "Os mapas de destinatários são usados para substituir o endereço de destino em uma mensagem antes que ela seja entregue.",
"recipient_map_new": "Novo destinatário", "recipient_map_new": "Novo destinatário",
"recipient_map_new_info": "O destino do mapa do destinatário deve ser um endereço de e-mail válido.", "recipient_map_new_info": "O destino do mapa do destinatário deve ser um endereço de e-mail válido ou um nome de domínio.",
"recipient_map_old": "Destinatário original", "recipient_map_old": "Destinatário original",
"recipient_map_old_info": "O destino original do mapa de um destinatário deve ser um endereço de e-mail válido ou um nome de domínio.", "recipient_map_old_info": "O destino original do mapa de um destinatário deve ser um endereço de e-mail válido ou um nome de domínio.",
"recipient_maps": "Mapas de destinatários", "recipient_maps": "Mapas de destinatários",
@@ -1330,4 +1330,4 @@
"session_token": "Token de formulário inválido: incompatibilidade de token", "session_token": "Token de formulário inválido: incompatibilidade de token",
"session_ua": "Token de formulário inválido: erro de validação do agente de usuário" "session_ua": "Token de formulário inválido: erro de validação do agente de usuário"
} }
} }
+2 -2
View File
@@ -789,7 +789,7 @@
"recipient_map": "Hartă destinatar", "recipient_map": "Hartă destinatar",
"recipient_map_info": "Hărțile destinatarilor sunt folosite pentru a înlocui adresa de destinație a unui mesaj înainte de a fi livrat.", "recipient_map_info": "Hărțile destinatarilor sunt folosite pentru a înlocui adresa de destinație a unui mesaj înainte de a fi livrat.",
"recipient_map_new": "Destinatar nou", "recipient_map_new": "Destinatar nou",
"recipient_map_new_info": "Destinația hărții destinatarului trebuie să fie o adresă de email validă.", "recipient_map_new_info": "Destinația hărții destinatarului trebuie să fie adrese de email valide sau nume de domeniu.",
"recipient_map_old": "Destinatar original", "recipient_map_old": "Destinatar original",
"recipient_map_old_info": "Destinația originală a hărților destinatarilor trebuie să fie adrese de email valide sau nume de domeniu.", "recipient_map_old_info": "Destinația originală a hărților destinatarilor trebuie să fie adrese de email valide sau nume de domeniu.",
"recipient_maps": "Hărți destinatar", "recipient_maps": "Hărți destinatar",
@@ -1208,4 +1208,4 @@
"expand_all": "Expandează tot", "expand_all": "Expandează tot",
"decimal": "," "decimal": ","
} }
} }
+2 -2
View File
@@ -887,7 +887,7 @@
"recipient_map": "Перезапись получателя", "recipient_map": "Перезапись получателя",
"recipient_map_info": "Перезапись получателя используются для замены получателя в сообщении до его доставки.", "recipient_map_info": "Перезапись получателя используются для замены получателя в сообщении до его доставки.",
"recipient_map_new": "Перезапись на", "recipient_map_new": "Перезапись на",
"recipient_map_new_info": "Должен быть действующим почтовым ящиком.", "recipient_map_new_info": "Должен быть действующим почтовым ящиком или доменом.",
"recipient_map_old": "Получатель", "recipient_map_old": "Получатель",
"recipient_map_old_info": "Должен быть действующим почтовым ящиком или доменом.", "recipient_map_old_info": "Должен быть действующим почтовым ящиком или доменом.",
"recipient_maps": "Перезапись получателя", "recipient_maps": "Перезапись получателя",
@@ -1336,4 +1336,4 @@
"session_token": "Неверный токен формы: несоответствие токена", "session_token": "Неверный токен формы: несоответствие токена",
"session_ua": "Неверный токен формы: ошибка проверки User-Agent" "session_ua": "Неверный токен формы: ошибка проверки User-Agent"
} }
} }
+2 -2
View File
@@ -822,7 +822,7 @@
"recipient_map": "Mapa príjemcu", "recipient_map": "Mapa príjemcu",
"recipient_map_info": "Mapy príjemcov sú používané ako náhrada cieľovej adresy u správy pred doručením.", "recipient_map_info": "Mapy príjemcov sú používané ako náhrada cieľovej adresy u správy pred doručením.",
"recipient_map_new": "Nový príjemca", "recipient_map_new": "Nový príjemca",
"recipient_map_new_info": "Mapový cieľ príjemcu musí byť platná emailová adresa.", "recipient_map_new_info": "Mapový cieľ príjemcu musí byť platná emailová adresa alebo meno domény.",
"recipient_map_old": "Originálny príjemca", "recipient_map_old": "Originálny príjemca",
"recipient_map_old_info": "Originálny cieľ mapy príjemcu musí byť platná emailová adresa alebo meno domény.", "recipient_map_old_info": "Originálny cieľ mapy príjemcu musí byť platná emailová adresa alebo meno domény.",
"recipient_maps": "Mapy príjemcov", "recipient_maps": "Mapy príjemcov",
@@ -1256,4 +1256,4 @@
"session_token": "Formulárový token neplatný: Tokenová nezhoda", "session_token": "Formulárový token neplatný: Tokenová nezhoda",
"session_ua": "Formulárový token neplatný: User-Agent validation error" "session_ua": "Formulárový token neplatný: User-Agent validation error"
} }
} }
+2 -2
View File
@@ -726,7 +726,7 @@
"recipient_map": "Mottagaromskrivning", "recipient_map": "Mottagaromskrivning",
"recipient_map_info": "En omskrivning av mottagaradressen används för att ersätta destinationsadressen i ett meddelande innan den levereras.", "recipient_map_info": "En omskrivning av mottagaradressen används för att ersätta destinationsadressen i ett meddelande innan den levereras.",
"recipient_map_new": "Ny mottagare", "recipient_map_new": "Ny mottagare",
"recipient_map_new_info": "Den ursprungliga mottagaren måste vara en giltig e-postadress.", "recipient_map_new_info": "Den ursprungliga mottagaren måste vara en giltiga e-postadresser eller ett domännamn.",
"recipient_map_old": "Ursprunglig mottagaren", "recipient_map_old": "Ursprunglig mottagaren",
"recipient_map_old_info": "Den ursprungliga mottagaren måste vara en giltiga e-postadresser eller ett domännamn.", "recipient_map_old_info": "Den ursprungliga mottagaren måste vara en giltiga e-postadresser eller ett domännamn.",
"recipient_maps": "Skriv om mottagaradressen", "recipient_maps": "Skriv om mottagaradressen",
@@ -1110,4 +1110,4 @@
"session_token": "Formulär-nyckeln är ogiltig: Nyckeln matchar inte", "session_token": "Formulär-nyckeln är ogiltig: Nyckeln matchar inte",
"session_ua": "Formulär-nyckeln är ogiltig: User-Agenten kunde inte valideras" "session_ua": "Formulär-nyckeln är ogiltig: User-Agenten kunde inte valideras"
} }
} }
+6 -1
View File
@@ -72,7 +72,12 @@ elseif (isset($_GET['login'])) {
// only check for admin-login on sogo GUI requests // only check for admin-login on sogo GUI requests
elseif (isset($_SERVER['HTTP_X_ORIGINAL_URI']) && strcasecmp(substr($_SERVER['HTTP_X_ORIGINAL_URI'], 0, 9), "/SOGo/so/") === 0) { elseif (isset($_SERVER['HTTP_X_ORIGINAL_URI']) && strcasecmp(substr($_SERVER['HTTP_X_ORIGINAL_URI'], 0, 9), "/SOGo/so/") === 0) {
// this is an nginx auth_request call, we check for existing sogo-sso session variables // this is an nginx auth_request call, we check for existing sogo-sso session variables
session_start(); require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.inc.php';
if (file_exists($_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php')) {
include_once $_SERVER['DOCUMENT_ROOT'] . '/inc/vars.local.inc.php';
}
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/sessions.inc.php';
// extract email address from "/SOGo/so/user@domain/xy" // extract email address from "/SOGo/so/user@domain/xy"
$url_parts = explode("/", $_SERVER['HTTP_X_ORIGINAL_URI']); $url_parts = explode("/", $_SERVER['HTTP_X_ORIGINAL_URI']);
$email_list = array( $email_list = array(
+24 -16
View File
@@ -1,7 +1,7 @@
services: services:
unbound-mailcow: unbound-mailcow:
image: mailcow/unbound:1.23 image: ghcr.io/mailcow/unbound:1.23
environment: environment:
- TZ=${TZ} - TZ=${TZ}
- SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n} - SKIP_UNBOUND_HEALTHCHECK=${SKIP_UNBOUND_HEALTHCHECK:-n}
@@ -17,7 +17,7 @@ services:
- unbound - unbound
mysql-mailcow: mysql-mailcow:
image: mariadb:10.5 image: mariadb:10.11
depends_on: depends_on:
- unbound-mailcow - unbound-mailcow
- netfilter-mailcow - netfilter-mailcow
@@ -42,8 +42,8 @@ services:
- mysql - mysql
redis-mailcow: redis-mailcow:
image: redis:7-alpine image: redis:7.4.2-alpine
entrypoint: /redis-conf.sh entrypoint: ["/bin/sh","/redis-conf.sh"]
volumes: volumes:
- redis-vol-1:/data/ - redis-vol-1:/data/
- ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z - ./data/conf/redis/redis-conf.sh:/redis-conf.sh:z
@@ -55,6 +55,7 @@ services:
environment: environment:
- TZ=${TZ} - TZ=${TZ}
- REDISPASS=${REDISPASS} - REDISPASS=${REDISPASS}
- REDISMASTERPASS=${REDISMASTERPASS:-}
sysctls: sysctls:
- net.core.somaxconn=4096 - net.core.somaxconn=4096
networks: networks:
@@ -64,7 +65,7 @@ services:
- redis - redis
clamd-mailcow: clamd-mailcow:
image: mailcow/clamd:1.66 image: ghcr.io/mailcow/clamd:1.70
restart: always restart: always
depends_on: depends_on:
unbound-mailcow: unbound-mailcow:
@@ -83,7 +84,7 @@ services:
- clamd - clamd
rspamd-mailcow: rspamd-mailcow:
image: mailcow/rspamd:1.99 image: ghcr.io/mailcow/rspamd:2.0
stop_grace_period: 30s stop_grace_period: 30s
depends_on: depends_on:
- dovecot-mailcow - dovecot-mailcow
@@ -116,7 +117,7 @@ services:
- rspamd - rspamd
php-fpm-mailcow: php-fpm-mailcow:
image: mailcow/phpfpm:1.92 image: ghcr.io/mailcow/phpfpm:1.92
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0" command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
depends_on: depends_on:
- redis-mailcow - redis-mailcow
@@ -174,6 +175,7 @@ services:
- DEMO_MODE=${DEMO_MODE:-n} - DEMO_MODE=${DEMO_MODE:-n}
- WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n} - WEBAUTHN_ONLY_TRUSTED_VENDORS=${WEBAUTHN_ONLY_TRUSTED_VENDORS:-n}
- CLUSTERMODE=${CLUSTERMODE:-} - CLUSTERMODE=${CLUSTERMODE:-}
- ADDITIONAL_SERVER_NAMES=${ADDITIONAL_SERVER_NAMES:-}
restart: always restart: always
networks: networks:
mailcow-network: mailcow-network:
@@ -181,7 +183,7 @@ services:
- phpfpm - phpfpm
sogo-mailcow: sogo-mailcow:
image: mailcow/sogo:1.128 image: ghcr.io/mailcow/sogo:1.129
environment: environment:
- DBNAME=${DBNAME} - DBNAME=${DBNAME}
- DBUSER=${DBUSER} - DBUSER=${DBUSER}
@@ -206,6 +208,9 @@ services:
- ./data/conf/sogo/:/etc/sogo/:z - ./data/conf/sogo/:/etc/sogo/:z
- ./data/web/inc/init_db.inc.php:/init_db.inc.php:z - ./data/web/inc/init_db.inc.php:/init_db.inc.php:z
- ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z - ./data/conf/sogo/custom-favicon.ico:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo.ico:z
- ./data/conf/sogo/custom-shortlogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-compact.svg:z
- ./data/conf/sogo/custom-fulllogo.svg:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-full.svg:z
- ./data/conf/sogo/custom-fulllogo.png:/usr/lib/GNUstep/SOGo/WebServerResources/img/sogo-logo.png:z
- ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z - ./data/conf/sogo/custom-theme.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/theme.js:z
- ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z - ./data/conf/sogo/custom-sogo.js:/usr/lib/GNUstep/SOGo/WebServerResources/js/custom-sogo.js:z
- mysql-socket-vol-1:/var/run/mysqld/ - mysql-socket-vol-1:/var/run/mysqld/
@@ -229,7 +234,7 @@ services:
- sogo - sogo
dovecot-mailcow: dovecot-mailcow:
image: mailcow/dovecot:2.3 image: ghcr.io/mailcow/dovecot:2.31
depends_on: depends_on:
- mysql-mailcow - mysql-mailcow
- netfilter-mailcow - netfilter-mailcow
@@ -316,7 +321,7 @@ services:
- dovecot - dovecot
postfix-mailcow: postfix-mailcow:
image: mailcow/postfix:1.78 image: ghcr.io/mailcow/postfix:1.80
depends_on: depends_on:
mysql-mailcow: mysql-mailcow:
condition: service_started condition: service_started
@@ -372,7 +377,7 @@ services:
- php-fpm-mailcow - php-fpm-mailcow
- sogo-mailcow - sogo-mailcow
- rspamd-mailcow - rspamd-mailcow
image: mailcow/nginx:1.01 image: ghcr.io/mailcow/nginx:1.03
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
environment: environment:
@@ -384,11 +389,14 @@ services:
- SKIP_SOGO=${SKIP_SOGO:-n} - SKIP_SOGO=${SKIP_SOGO:-n}
- SKIP_RSPAMD=${SKIP_RSPAMD:-n} - SKIP_RSPAMD=${SKIP_RSPAMD:-n}
- DISABLE_IPv6=${DISABLE_IPv6:-n} - DISABLE_IPv6=${DISABLE_IPv6:-n}
- HTTP_REDIRECT=${HTTP_REDIRECT:-n}
- PHPFPMHOST=${PHPFPMHOST:-} - PHPFPMHOST=${PHPFPMHOST:-}
- SOGOHOST=${SOGOHOST:-} - SOGOHOST=${SOGOHOST:-}
- RSPAMDHOST=${RSPAMDHOST:-} - RSPAMDHOST=${RSPAMDHOST:-}
- REDISHOST=${REDISHOST:-} - REDISHOST=${REDISHOST:-}
- IPV4_NETWORK=${IPV4_NETWORK:-172.22.1} - IPV4_NETWORK=${IPV4_NETWORK:-172.22.1}
- NGINX_USE_PROXY_PROTOCOL=${NGINX_USE_PROXY_PROTOCOL:-n}
- TRUSTED_PROXIES=${TRUSTED_PROXIES:-}
volumes: volumes:
- ./data/web:/web:ro,z - ./data/web:/web:ro,z
- ./data/conf/rspamd/dynmaps:/dynmaps:ro,z - ./data/conf/rspamd/dynmaps:/dynmaps:ro,z
@@ -411,7 +419,7 @@ services:
condition: service_started condition: service_started
unbound-mailcow: unbound-mailcow:
condition: service_healthy condition: service_healthy
image: mailcow/acme:1.91 image: ghcr.io/mailcow/acme:1.91
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
environment: environment:
@@ -449,7 +457,7 @@ services:
- acme - acme
netfilter-mailcow: netfilter-mailcow:
image: mailcow/netfilter:1.60 image: ghcr.io/mailcow/netfilter:1.61
stop_grace_period: 30s stop_grace_period: 30s
restart: always restart: always
privileged: true privileged: true
@@ -469,7 +477,7 @@ services:
- /lib/modules:/lib/modules:ro - /lib/modules:/lib/modules:ro
watchdog-mailcow: watchdog-mailcow:
image: mailcow/watchdog:2.06 image: ghcr.io/mailcow/watchdog:2.06
dns: dns:
- ${IPV4_NETWORK:-172.22.1}.254 - ${IPV4_NETWORK:-172.22.1}.254
tmpfs: tmpfs:
@@ -541,7 +549,7 @@ services:
- watchdog - watchdog
dockerapi-mailcow: dockerapi-mailcow:
image: mailcow/dockerapi:2.10 image: ghcr.io/mailcow/dockerapi:2.10
security_opt: security_opt:
- label=disable - label=disable
restart: always restart: always
@@ -561,7 +569,7 @@ services:
- dockerapi - dockerapi
olefy-mailcow: olefy-mailcow:
image: mailcow/olefy:1.13 image: ghcr.io/mailcow/olefy:1.13
restart: always restart: always
environment: environment:
- TZ=${TZ} - TZ=${TZ}
+4 -1
View File
@@ -26,7 +26,7 @@ for bin in openssl curl docker git awk sha1sum grep cut; do
done done
# Check Docker Version (need at least 24.X) # Check Docker Version (need at least 24.X)
docker_version=$(docker -v | grep -oP '\d+\.\d+\.\d+' | head -n 1 | cut -d '.' -f 1) docker_version=$(docker version --format '{{.Server.Version}}' | cut -d '.' -f 1)
if [[ $docker_version -lt 24 ]]; then if [[ $docker_version -lt 24 ]]; then
echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m" echo -e "\e[31mCannot find Docker with a Version higher or equals 24.0.0\e[0m"
@@ -267,6 +267,9 @@ HTTP_BIND=
HTTPS_PORT=443 HTTPS_PORT=443
HTTPS_BIND= HTTPS_BIND=
# Redirect HTTP connections to HTTPS - y/n
HTTP_REDIRECT=n
# ------------------------------ # ------------------------------
# Other bindings # Other bindings
# ------------------------------ # ------------------------------
-40
View File
@@ -10,46 +10,6 @@ echo "If this script is run automatically by cron or a timer AND you are using b
echo "The snapshots of your backup destination should run AFTER the cold standby script finished to ensure consistent snapshots." echo "The snapshots of your backup destination should run AFTER the cold standby script finished to ensure consistent snapshots."
echo echo
function docker_garbage() {
IMGS_TO_DELETE=()
for container in $(grep -oP "image: \Kmailcow.+" docker-compose.yml); do
REPOSITORY=${container/:*}
TAG=${container/*:}
V_MAIN=${container/*.}
V_SUB=${container/*.}
EXISTING_TAGS=$(docker images | grep ${REPOSITORY} | awk '{ print $2 }')
for existing_tag in ${EXISTING_TAGS[@]}; do
V_MAIN_EXISTING=${existing_tag/*.}
V_SUB_EXISTING=${existing_tag/*.}
# Not an integer
[[ ! ${V_MAIN_EXISTING} =~ ^[0-9]+$ ]] && continue
[[ ! ${V_SUB_EXISTING} =~ ^[0-9]+$ ]] && continue
if [[ ${V_MAIN_EXISTING} == "latest" ]]; then
echo "Found deprecated label \"latest\" for repository ${REPOSITORY}, it should be deleted."
IMGS_TO_DELETE+=(${REPOSITORY}:${existing_tag})
elif [[ ${V_MAIN_EXISTING} -lt ${V_MAIN} ]]; then
echo "Found tag ${existing_tag} for ${REPOSITORY}, which is older than the current tag ${TAG} and should be deleted."
IMGS_TO_DELETE+=(${REPOSITORY}:${existing_tag})
elif [[ ${V_SUB_EXISTING} -lt ${V_SUB} ]]; then
echo "Found tag ${existing_tag} for ${REPOSITORY}, which is older than the current tag ${TAG} and should be deleted."
IMGS_TO_DELETE+=(${REPOSITORY}:${existing_tag})
fi
done
done
if [[ ! -z ${IMGS_TO_DELETE[*]} ]]; then
docker rmi ${IMGS_TO_DELETE[*]}
fi
}
function preflight_local_checks() { function preflight_local_checks() {
if [[ -z "${REMOTE_SSH_KEY}" ]]; then if [[ -z "${REMOTE_SSH_KEY}" ]]; then
>&2 echo -e "\e[31mREMOTE_SSH_KEY is not set\e[0m" >&2 echo -e "\e[31mREMOTE_SSH_KEY is not set\e[0m"
+1 -1
View File
@@ -1,6 +1,6 @@
#!/usr/bin/env bash #!/usr/bin/env bash
DEBIAN_DOCKER_IMAGE="mailcow/backup:latest" DEBIAN_DOCKER_IMAGE="ghcr.io/mailcow/backup:latest"
if [[ ! -z ${MAILCOW_BACKUP_LOCATION} ]]; then if [[ ! -z ${MAILCOW_BACKUP_LOCATION} ]]; then
BACKUP_LOCATION="${MAILCOW_BACKUP_LOCATION}" BACKUP_LOCATION="${MAILCOW_BACKUP_LOCATION}"
+56 -4
View File
@@ -36,13 +36,19 @@ docker_garbage() {
IMGS_TO_DELETE=() IMGS_TO_DELETE=()
declare -A IMAGES_INFO declare -A IMAGES_INFO
COMPOSE_IMAGES=($(grep -oP "image: \Kmailcow.+" "${SCRIPT_DIR}/docker-compose.yml")) COMPOSE_IMAGES=($(grep -oP "image: \K(ghcr\.io/)?mailcow.+" "${SCRIPT_DIR}/docker-compose.yml"))
for existing_image in $(docker images --format "{{.ID}}:{{.Repository}}:{{.Tag}}" | grep 'mailcow/'); do for existing_image in $(docker images --format "{{.ID}}:{{.Repository}}:{{.Tag}}" | grep -E '(mailcow/|ghcr\.io/mailcow/)'); do
ID=$(echo "$existing_image" | cut -d ':' -f 1) ID=$(echo "$existing_image" | cut -d ':' -f 1)
REPOSITORY=$(echo "$existing_image" | cut -d ':' -f 2) REPOSITORY=$(echo "$existing_image" | cut -d ':' -f 2)
TAG=$(echo "$existing_image" | cut -d ':' -f 3) TAG=$(echo "$existing_image" | cut -d ':' -f 3)
if [[ "$REPOSITORY" == "mailcow/backup" || "$REPOSITORY" == "ghcr.io/mailcow/backup" ]]; then
if [[ "$TAG" != "<none>" ]]; then
continue
fi
fi
if [[ " ${COMPOSE_IMAGES[@]} " =~ " ${REPOSITORY}:${TAG} " ]]; then if [[ " ${COMPOSE_IMAGES[@]} " =~ " ${REPOSITORY}:${TAG} " ]]; then
continue continue
else else
@@ -57,7 +63,7 @@ docker_garbage() {
echo " ${IMAGES_INFO[$id]} ($id)" echo " ${IMAGES_INFO[$id]} ($id)"
done done
if [ ! $FORCE ]; then if [ -z "$FORCE" ]; then
read -r -p "Do you want to delete them to free up some space? [y/N] " response read -r -p "Do you want to delete them to free up some space? [y/N] " response
if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then if [[ "$response" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
docker rmi ${IMGS_TO_DELETE[*]} docker rmi ${IMGS_TO_DELETE[*]}
@@ -352,6 +358,7 @@ adapt_new_options() {
"SPAMHAUS_DQS_KEY" "SPAMHAUS_DQS_KEY"
"SKIP_UNBOUND_HEALTHCHECK" "SKIP_UNBOUND_HEALTHCHECK"
"DISABLE_NETFILTER_ISOLATION_RULE" "DISABLE_NETFILTER_ISOLATION_RULE"
"HTTP_REDIRECT"
) )
sed -i --follow-symlinks '$a\' mailcow.conf sed -i --follow-symlinks '$a\' mailcow.conf
@@ -637,7 +644,13 @@ adapt_new_options() {
echo '# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n' >> mailcow.conf echo '# Prevent netfilter from setting an iptables/nftables rule to isolate the mailcow docker network - y/n' >> mailcow.conf
echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf echo '# CAUTION: Disabling this may expose container ports to other neighbors on the same subnet, even if the ports are bound to localhost' >> mailcow.conf
echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf echo 'DISABLE_NETFILTER_ISOLATION_RULE=n' >> mailcow.conf
fi fi
elif [[ ${option} == "HTTP_REDIRECT" ]]; then
if ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf"
echo '# Redirect HTTP connections to HTTPS - y/n' >> mailcow.conf
echo 'HTTP_REDIRECT=n' >> mailcow.conf
fi
elif ! grep -q ${option} mailcow.conf; then elif ! grep -q ${option} mailcow.conf; then
echo "Adding new option \"${option}\" to mailcow.conf" echo "Adding new option \"${option}\" to mailcow.conf"
echo "${option}=n" >> mailcow.conf echo "${option}=n" >> mailcow.conf
@@ -703,6 +716,44 @@ migrate_solr_config_options() {
fi fi
} }
detect_major_update() {
if [ ${BRANCH} == "master" ]; then
# Array with major versions
# Add major versions here
MAJOR_VERSIONS=(
"2025-02"
)
current_version=$(git describe --tags $(git rev-list --tags --max-count=1))
release_url="https://github.com/mailcow/mailcow-dockerized/releases/tag"
updates_to_apply=()
for version in "${MAJOR_VERSIONS[@]}"; do
if [[ "$current_version" < "$version" ]]; then
updates_to_apply+=("$version")
fi
done
if [[ ${#updates_to_apply[@]} -gt 0 ]]; then
echo -e "\e[33m\nMAJOR UPDATES to be applied:\e[0m"
for update in "${updates_to_apply[@]}"; do
echo "$update - $release_url/$update"
done
echo -e "\n⚠️ Please read the release notes before proceeding.\n"
read -p "Do you want to proceed with the update? [y/n] " response
if [[ "${response}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "Proceeding with the update..."
else
echo "Update canceled. Exiting."
exit 1
fi
fi
fi
}
############## End Function Section ############## ############## End Function Section ##############
# Check permissions # Check permissions
@@ -1338,6 +1389,7 @@ if [ ! "$FORCE" ]; then
echo "OK, exiting." echo "OK, exiting."
exit 0 exit 0
fi fi
detect_major_update
migrate_docker_nat migrate_docker_nat
fi fi