1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-06-14 02:20:28 +00:00

Compare commits

..

187 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
FreddleSpl0it ba0349a911 Merge pull request #6256 from mailcow/staging
[Nginx] move conf.d include to end of nginx.conf
2025-01-23 14:55:38 +01:00
FreddleSpl0it 04058ab06e [Nginx] move conf.d include to end of nginx.conf 2025-01-23 14:54:28 +01:00
FreddleSpl0it 8caf09cd80 Merge pull request #6253 from mailcow/staging
2025-01
2025-01-23 12:01:38 +01:00
FreddleSpl0it da02e26172 [Web] Delete old session_id after regenerate 2025-01-23 11:59:01 +01:00
DerLinkman 43f945fe01 dovecot: fix index timeout seconds 2025-01-23 11:51:41 +01:00
DerLinkman e76c0ba9a6 Merge branch 'staging' 2025-01-23 11:31:01 +01:00
DerLinkman d83111568e update.sh: remove accidentally added exit at end of solr volume removal 2025-01-23 11:30:05 +01:00
FreddleSpl0it 1b578caabb Merge pull request #6251 from mailcow/staging
2025-01
2025-01-23 11:16:38 +01:00
DerLinkman 1dac8f1f66 scripts: changed SKIP_FTS text to warn on lower threaded systems 2025-01-23 08:42:22 +01:00
DerLinkman 5a04942d89 update.sh: changed SKIP_FTS default to y instead n for updates 2025-01-23 08:38:14 +01:00
DerLinkman a30f6696a3 update.sh: fixed --force for solr-removal + code optimization 2025-01-23 08:30:48 +01:00
FreddleSpl0it 1fca328266 [Nginx] Disable IPv6 listener for Rspamd dynmaps when DISABLE_IPv6=y 2025-01-22 15:11:46 +01:00
FreddleSpl0it 7bcd61ecb5 [Nginx] Generate includes for custom configs 2025-01-22 14:30:47 +01:00
renovate[bot] ee7a8624fc chore(deps): update actions/stale action to v9.1.0 (#6247)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2025-01-21 06:38:13 +01:00
DerLinkman 4708b1398b update.sh: fix mailcow fts update versioning 2025-01-20 15:41:48 +01:00
DerLinkman 746915cbdd fts: change autoindex to occur on mailboxes of receiving 20 or more mails daily 2025-01-20 14:21:15 +01:00
Alyx 36db68677c Reduce sa rules download retry limit to 5 (#6225)
Reduces the retry limit for the sa rules download to a more reasonable 5 retries to prevent running in a timeout condition.
2025-01-20 14:10:29 +01:00
gwelch-contegix 08599c1960 Fix community support url (#6245) 2025-01-20 14:09:31 +01:00
DerLinkman 31e001ebee flatcurve: change default amount of processes to 1 2025-01-16 11:37:15 +01:00
FreddleSpl0it 8fea9fc21f Merge pull request #6211 from jan-oratowski/patch-1
Fix missing property in Create Sync Job request
2025-01-14 12:18:29 +01:00
FreddleSpl0it 2f1884e94b Merge pull request #6205 from PhoenixPeca/master
Improve the existing validation flow for sieve filter
2025-01-14 12:08:56 +01:00
FreddleSpl0it 24b3d8f850 Merge pull request #6001 from marekfilip/feat/temp-email-aliases
add temporary email description
2025-01-14 11:52:44 +01:00
FreddleSpl0it d280025b51 [Web] Regenerate session_id on successful login 2025-01-14 11:30:41 +01:00
FreddleSpl0it abd789f629 [Web] Escape mailbox name before querying aliases 2025-01-14 11:18:20 +01:00
milkmaker 69f6a82905 [Web] Updated lang.fr-fr.json (#6238)
Co-authored-by: Neuronnexion <support@nnx.com>
2025-01-09 06:51:42 +01:00
milkmaker 10328981b6 Translations update from Weblate (#6235)
* [Web] Updated lang.fr-fr.json

Co-authored-by: Neuronnexion <support@nnx.com>

* [Web] Updated lang.zh-cn.json

Co-authored-by: Easton Man <me@eastonman.com>

---------

Co-authored-by: Neuronnexion <support@nnx.com>
Co-authored-by: Easton Man <me@eastonman.com>
2025-01-05 15:25:45 +01:00
Filip Marek 150b2bbd9d Merge branch 'mailcow:master' into feat/temp-email-aliases 2025-01-03 11:40:01 +01:00
milkmaker 40a8bc808a update postscreen_access.cidr (#6232) 2025-01-01 03:26:18 +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
milkmaker 2d2dacb70e [Web] Updated lang.fr-fr.json (#6221)
[Web] Updated lang.fr-fr.json

Co-authored-by: Neuronnexion <support@nnx.com>
Co-authored-by: Peter <magic@kthx.at>
2024-12-19 17:10:43 +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
Jan Oratowski c6f6eda0bf Fix missing property in Create Sync Job request
In example there was property called "user1", but it was missing from request definition.

This resulted in nswagger generating incorrect C# API code.
2024-12-14 15:27:37 +01:00
milkmaker 357a4d7fb3 [Web] Updated lang.fr-fr.json (#6209)
Co-authored-by: Neuronnexion <support@nnx.com>
2024-12-13 12:21:12 +01:00
DerLinkman 1c6684a539 compose: fix dovecot tagging 2024-12-12 17:02:21 +01:00
DerLinkman de80c120c9 update.sh: added silent fix for removing old fts.conf in order to update properly 2024-12-12 16:57:32 +01:00
Niklas Meyer 3e8bb06a37 dovecot: replace solr fts with flatcurve (xapian) (#5680)
* fts-flatcurve: inital implementation

* fts: removed solr from compose.yml

* flatcurve: added heap and proc logic to dovecot

* added logic for update.sh & generate for Flatcurve

* delete old iteration of fts-flatcurve.conf

* updated default fts.conf

* updated .gitignore to exclude fts.conf for further git updates

* Remove autogeneration of fts.conf (disable override)

* cleanup all left solr stuff

* renamed SKIP_FLATCURVE to SKIP_FTS

* cleanup leftovers solr in lang files

* moved lazy_expunge plugin only to mail_plugins

* added fts timeout value

* compose: remove dev image of dovecot

* updated japanese translation
2024-12-12 16:44:42 +01:00
milkmaker b087ac9e27 Translations update from Weblate (#6206)
* [Web] Updated lang.fr-fr.json

Co-authored-by: Neuronnexion <support@nnx.com>

* [Web] Updated lang.si-si.json

Co-authored-by: Matjaž Tekavec <matjaz@moj-svet.si>

---------

Co-authored-by: Neuronnexion <support@nnx.com>
Co-authored-by: Matjaž Tekavec <matjaz@moj-svet.si>
2024-12-11 18:10:51 +01:00
Phoenix Eve Aspacio d09e4ff020 Convert AJAX to POST request
This AJAX request sends form data in $_GET request query. This is problematic and unreliable when validating superrrr loooooong conditions, especially in environments that use reverse-proxy.

Been having this problem and this PR solves it. :)
2024-12-11 10:06:10 +08:00
Phoenix Eve Aspacio f065842402 Updated to $_REQUEST.
tested from my end.
2024-12-11 10:03:47 +08:00
Niklas Meyer 3875e8377a sogo: added SOGoDisableOrganizerEventCheck value to sogo.conf (#6204) 2024-12-10 15:59:02 +01:00
Christian 🦄 7c8e5c10ca Add create command to prevent external: true warnings (#6203)
This is related to https://github.com/mailcow/mailcow-dockerized/issues/5970 and https://community.mailcow.email/d/2126-backup-restore/2

It adds `docker compose create` to the script which gets executed directly after the sync of the mailcow-dockerized directory. This way the Docker daemon on the remote side creates everything and we get rid of the warning "volume "XYZ" already exists but was not created by Docker Compose. Use `external: true` to use an existing volume"

This is helpful if you use the create-cold-standby.sh script to migrate your mailcow installation to another server and don't want to get those warnings after migration.

Co-authored-by: Niklas Meyer <niklas.meyer@servercow.de>
2024-12-10 09:25:29 +01:00
Filip Marek 1a8e1a2677 add escape html for description 2024-12-09 23:07:43 +01:00
Filip Marek 0d635e2658 increase migrations verion 2024-12-09 23:07:43 +01:00
Filip Marek 60ca25026d add temporary email description 2024-12-09 23:07:02 +01:00
Peter ed2837edd8 Remove legacy Nextcloud settings (#6050) 2024-12-09 13:49:24 +01:00
FreddleSpl0it fa3b789fbb [Web] fix issue #6185 2024-12-09 13:07:00 +01:00
FreddleSpl0it 49e05f5120 [Web] fix oauth2 redirect after login 2024-12-09 11:36:05 +01:00
FreddleSpl0it 24453993f3 Merge pull request #6186 from h3ssan/feat/search-mailbox-by-full-name
Implement search mailboxes by fullname
2024-12-09 10:21:39 +01:00
FreddleSpl0it 8853e2c44a [Nginx] Use SOGo IPv4 for upstream 2024-12-09 09:50:16 +01:00
Tatsuya Yokota d1af52b4e7 Add initial Japanese language files (#6198)
* Add initial Japanese language files

* Reordered language list: moved Japanese (日本語) below Italian (Italiano)

---------

Co-authored-by: Tatsuya Yokota <git@acoustype.com>
2024-12-06 09:44:16 +01:00
i-curve 6e8e13cebc fix: check docker version fail in generate_config.sh #6187 (#6188)
close #6187

Signed-off-by: i-curve <i-curve@qq.com>
Co-authored-by: Niklas Meyer <niklas.meyer@servercow.de>
2024-12-04 12:28:14 +01:00
milkmaker f3060b37a6 update postscreen_access.cidr (#6189) 2024-12-01 17:49:28 +01:00
milkmaker 59c68f2603 Translations update from Weblate (#6190) 2024-12-01 17:49:10 +01:00
Hassan A Hashim 31185e3de1 Implement search mailboxes by fullname 2024-11-27 14:47:57 +03:00
Habetdin 4dbfd3abad Update lang.ru-ru.json (#6184) 2024-11-25 16:01:17 +01:00
FreddleSpl0it b4e6002bcf Merge pull request #6076 from Habetdin/staging
Only show active protocols on "last login" in mailbox overview
2024-11-21 10:24:41 +01:00
FreddleSpl0it 6af907cff0 Merge pull request #6182 from mailcow/fix/4518
[Web] allow dots in dkim selectors
2024-11-20 13:11:34 +01:00
FreddleSpl0it ba282233ea [Web] allow dots in dkim selectors 2024-11-20 13:05:02 +01:00
FreddleSpl0it 6f4c2b3361 Merge pull request #6181 from mailcow/fix/5703
[Web] Add additional columns to _sogo_static_view
2024-11-20 11:15:35 +01:00
FreddleSpl0it d08b9aec32 [Web] Add additional columns to _sogo_static_view 2024-11-20 11:09:49 +01:00
FreddleSpl0it bb310600b2 Merge pull request #6180 from mailcow/fix/6046
[Web] add missing translation for ratelimit in templates overview
2024-11-20 10:02:34 +01:00
FreddleSpl0it fe7211f27f [Web] add missing translation for ratelimit in templates overview 2024-11-20 09:57:14 +01:00
FreddleSpl0it 8e9a9364a8 Merge pull request #6146 from mailcow/feat/redis-pw
Enable password protection for Redis
2024-11-19 15:32:36 +01:00
FreddleSpl0it 6831f94fdb [Redis] redis-cli suppress auth warning 2024-11-19 15:10:52 +01:00
FreddleSpl0it b0de756a7c [Redis] Rename docker-entrypoint.sh to redis-conf.sh 2024-11-19 14:54:36 +01:00
FreddleSpl0it 922f8777b0 Merge pull request #6168 from mailcow/fix/f2b-banlist
[Web] remove f2b banlist from json_api.php
2024-11-19 14:32:31 +01:00
FreddleSpl0it c1903f121d [Redis] set password via docker-entrypoint.sh 2024-11-19 14:25:31 +01:00
FreddleSpl0it 89fb1322c6 Enable password protection for Redis 2024-11-19 14:25:31 +01:00
FreddleSpl0it 852d944cfb [Web] remove f2b banlist from json_api.php 2024-11-19 14:13:37 +01:00
Niklas Meyer bca4e1a03d update.sh: precaution ask for deletion of dns_blocklists.cf if old format (#6154) 2024-11-19 14:13:37 +01:00
FreddleSpl0it 326a446f8b Merge pull request #6177 from mailcow/feat/jinja2-nginx
[Nginx] Use jinja2 for templating nginx configuration
2024-11-19 14:08:37 +01:00
FreddleSpl0it 70ca5fde95 [Nginx] Use jinja2 for templating nginx configuration 2024-11-19 08:39:52 +01:00
DerLinkman 5ad4ab5b60 update.sh: fixed typos 2024-11-15 16:39:06 +01:00
Niklas Meyer bd9f4ba0a5 Merge pull request #6173 from mailcow/staging
2024-11b
2024-11-15 16:21:17 +01:00
DerLinkman d10d64dd92 mysql: increased thread_stack to 192k since 10.5.27 2024-11-15 16:18:22 +01:00
FreddleSpl0it 6d1f7482ed [Web] broadcast maildir move to dovecot containers on mailbox_rename 2024-11-15 16:18:21 +01:00
FreddleSpl0it b9f52df3f1 [Web] update _sogo_static_view on password reset 2024-11-15 16:18:21 +01:00
Niklas Meyer 4d688c5500 2024-11a (#6160)
* update.sh: precaution ask for deletion of dns_blocklists.cf if old format (#6154)

* [Web] Updated lang.zh-cn.json (#6151)

[Web] Updated lang.zh-cn.json

Co-authored-by: Easton Man <me@eastonman.com>

* compose: bump sogo version to include 5.11.2 (#6156)

* php: use correct php image + workaround of #6149 (#6159)

* compose: bump php-fpm container to correctly use patched c-ares

* [Web] check $containers_info contains required fields

---------

Co-authored-by: FreddleSpl0it <patschul@posteo.de>

---------

Co-authored-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: Easton Man <me@eastonman.com>
Co-authored-by: FreddleSpl0it <patschul@posteo.de>
2024-11-12 15:57:17 +01:00
Habetdin 6550f0a3e8 Only show active protocols on "last login" in mailbox overview 2024-11-11 12:44:05 +03:00
FreddleSpl0it 0a58aa293a Merge pull request #6141 from mailcow/staging
2024-11
2024-11-07 11:41:45 +01:00
milkmaker be79f320d2 Translations update from Weblate (#6140)
* [Web] Updated lang.lv-lv.json

Co-authored-by: Edgars Andersons <Edgars+Mailcow+Weblate@gaitenis.id.lv>

* [Web] Updated lang.tr-tr.json

Co-authored-by: Furkan <furkan43500@gmail.com>

---------

Co-authored-by: Edgars Andersons <Edgars+Mailcow+Weblate@gaitenis.id.lv>
Co-authored-by: Furkan <furkan43500@gmail.com>
2024-11-06 19:08:53 +01:00
Niklas Meyer 6ec1e357c3 fix: broken sogo cron notifications (for appointments etc.) (#6128) 2024-11-05 16:21:14 +01:00
milkmaker 8b2f71f97e update postscreen_access.cidr (#6129) 2024-11-05 16:20:57 +01:00
renovate[bot] 93cf99cc9e chore(deps): update thollander/actions-comment-pull-request action to v3.0.1 (#6130)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-11-02 20:38:18 +01:00
FreddleSpl0it d8c8e4ab1b [DockerApi] Fix IMAP ACL migration issue when renaming mailbox 2024-10-31 11:00:03 +01:00
FreddleSpl0it 2d76ffc88c Merge pull request #6045 from mailcow/feat/rename-mbox
[Web][DockerApi] Add Feature to Rename Email Addresses
2024-10-25 10:49:58 +02:00
FreddleSpl0it 672bb345fd Fix mailbox_rename de-de translation 2024-10-25 10:47:53 +02:00
milkmaker 5c88030b5a Translations update from Weblate (#6123)
* [Web] Updated lang.lv-lv.json

Co-authored-by: Edgars Andersons <Edgars+Mailcow+Weblate@gaitenis.id.lv>

* [Web] Updated lang.zh-tw.json

[Web] Updated lang.zh-tw.json

Co-authored-by: SamWang8891 <g348.8891@gmail.com>
Co-authored-by: milkmaker <milkmaker@mailcow.de>

---------

Co-authored-by: Edgars Andersons <Edgars+Mailcow+Weblate@gaitenis.id.lv>
Co-authored-by: SamWang8891 <g348.8891@gmail.com>
2024-10-22 21:52:42 +02:00
Niklas Meyer b106945c73 Feat/rspamd 3.10.2 (#6122)
* rspamd: update to 3.10.2

* rspamd: fix broken archive_extension gz
2024-10-21 16:03:51 +02:00
milkmaker 502a7100ca [Web] Updated lang.zh-cn.json (#6120)
Co-authored-by: SamWang8891 <g348.8891@gmail.com>
2024-10-19 22:24:45 +02:00
Niklas Meyer ee2791d93a rspamd: update to 3.10.1 (#6115)
* rspamd: upgrade to 3.10.1

* rspamd: adapt 30s task timeout per default now
2024-10-18 15:50:45 +02:00
SamWang8891 399630cf34 Update lang.zh-tw.json (#6114) 2024-10-17 14:50:05 +02:00
Patrik Kernstock fce93609dd Update mime_types.conf configuration (#6013)
In the last months and years, the default `mime_types.conf` of rspamd has changed and it might be also useful to make some adjustments to the weight of certain file extensions.

This PR is removing all file extensions from `mime_types.conf` which are already in rspamd's default configuration at [rspamd/src/plugins/lua/mime_types.lua](https://github.com/rspamd/rspamd/blob/master/src/plugins/lua/mime_types.lua). If file extension is not present or has a different score compared to rspamd default, it is still in the list.

There are also a few major differences to certain file extensions, which might be useful to discuss and carefully adjust. For example, `.exe` files are rated very 'badly' due to high chance of being malicious, so are other extensions like `bat`, `cmd`, etc.

Current suggestion:
```lua
# Extensions that are treated as 'bad'
# Number is score multiply factor
bad_extensions = {
  apk = 4,
  appx = 4,
  appxbundle = 4,
  bat = 8,
  cab = 20,
  cmd = 8,
  com = 20,
  diagcfg = 4,
  diagpack = 4,
  dmg = 8,
  ex = 20,
  ex_ = 20,
  exe = 20,
  img = 4,
  jar = 8,
  jnlp = 8,
  js = 8,
  jse = 8,
  lnk = 20,
  mjs = 8,
  msi = 4,
  msix = 4,
  msixbundle = 4,
  ps1 = 8,
  scr = 20,
  sct = 20,
  vb = 20,
  vbe = 20,
  vbs = 20,
  vhd = 4,
  py = 4,
  reg = 8,
  scf = 8,
  vhdx = 4,
};

# Extensions that are particularly penalized for archives
bad_archive_extensions = {
  pptx = 0.5,
  docx = 0.5,
  xlsx = 0.5,
  pdf = 1.0,
  jar = 12,
  jnlp = 12,
  bat = 12,
  cmd = 12,
};

# Used to detect another archive in archive
archive_extensions = {
  tar = 1,
  ['tar.gz'] = 1,
};
```

**As a important reminder**: For all remaining and additional file extensions and score weights, please check above default rspamd configuration!
2024-10-17 09:11:55 +02:00
Niklas Meyer 38907b5032 dovecot: activate lazy_expunge plugin per default (unconfigured) (#6112) 2024-10-16 15:56:40 +02:00
Peter 5a0f20b9ea Update dependency twig/twig to v3.14.0 (#6071) 2024-10-16 15:29:16 +02:00
Niklas Meyer 8dcaffe925 php: upgrade to alpine 3.20 (base os) (#6106) 2024-10-16 10:35:54 +02:00
Niklas Meyer c53bf85480 postfix: add X-Original-To header per default (#6110) 2024-10-16 10:35:39 +02:00
Niklas Meyer 982e823c71 sogo: upgrade to 5.11.1 (#6109) 2024-10-15 16:13:51 +02:00
renovate[bot] 382056ec18 chore(deps): update dependency krakjoe/apcu to v5.1.24 (#6087)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 11:24:26 +02:00
renovate[bot] 4c9690e87c chore(deps): update dependency php/pecl-mail-mailparse to v3.1.8 (#6096)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 11:09:23 +02:00
renovate[bot] 9a58e5e35a chore(deps): update dependency phpredis/phpredis to v6.1.0 (#6098)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
2024-10-15 10:45:32 +02:00
renovate[bot] 932cf453de chore(deps): update dependency nextcloud/server to v28.0.11 (#6101)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 10:34:57 +02:00
milkmaker 1538fda71c update postscreen_access.cidr (#6093) 2024-10-15 10:34:39 +02:00
renovate[bot] 54a0d53deb chore(deps): update thollander/actions-comment-pull-request action to v3 (#6102)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-10-15 10:34:19 +02:00
Niklas Meyer fda95301ba fix: added tls1.0/1.1 patch for openssl when using older tls versions in override (#6105) 2024-10-15 10:32:08 +02:00
FreddleSpl0it 1528e8766a [DockerApi] correctly escape user input 2024-09-06 15:59:52 +02:00
Hassan A Hashim 220fdbb168 Add missing Russian translation (#6065) 2024-09-06 07:14:34 +02:00
milkmaker fe3d08515e [Web] Language file updated by 'Cleanup translation files' addon (#6064) 2024-09-06 07:13:59 +02:00
airon-assustadus 22f7f61ac9 feat/brazilian-translations (#6048)
# What
- Adding some brazilian translations that were missing

Co-authored-by: Airon Teixeira <airon@ymail.com>
2024-09-05 15:09:49 +02:00
FreddleSpl0it 29d8cfe2ba [Web] Set min-width and text-align for last login badges 2024-09-05 14:02:04 +02:00
FreddleSpl0it f2e35dff68 [Web] rename user in sender_acl table 2024-09-05 12:40:30 +02:00
FreddleSpl0it b1368d29d1 Merge pull request #5724 from q16marvin/master
show last sso login in mailbox table
2024-09-05 12:02:16 +02:00
FreddleSpl0it 0d704a57f5 Merge pull request #6057 from mailcow/fix/sogo-auto-reply
[SOGo] Fix vacation auto reply date shifting
2024-09-05 11:19:40 +02:00
FreddleSpl0it 462137ede7 Merge pull request #6044 from mailcow/feat/redis-session-store
[PHP-FPM] Use redis as session store
2024-09-05 10:55:07 +02:00
Niklas Meyer bb6f405841 compose: added clamd as depends_on to rspamd (#6062) 2024-09-04 14:42:30 +02:00
renovate[bot] 8b2d67169b chore(deps): update peter-evans/create-pull-request action to v7 (#6059)
Signed-off-by: milkmaker <milkmaker@mailcow.de>
Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com>
2024-09-03 19:42:10 +02:00
Finn Hoffhenke 710cec996c feat: Added check for newer version tags on remote (#6054) 2024-09-02 15:40:29 +02:00
Niklas Meyer 0129f84a32 Merge pull request #6056 from mailcow/update/postscreen_access.cidr
[Postfix] update postscreen_access.cidr
2024-09-02 15:37:24 +02:00
FreddleSpl0it ae3653a925 [SOGo] vacation auto reply date shifting #5394 2024-09-02 10:22:51 +02:00
milkmaker af0c61b90a update postscreen_access.cidr 2024-09-01 00:19:09 +00:00
milkmaker 7203735532 [Web] Updated lang.it-it.json (#6053)
Co-authored-by: Stefano <stefano.vassena@gmail.com>
2024-08-29 20:27:23 +02:00
FreddleSpl0it 4f9e37c0c3 [Web] rename user in bcc_maps, recipient_maps and imapsync table 2024-08-28 11:16:29 +02:00
FreddleSpl0it d21c1bfa72 [Web] add error handling for get_acl call 2024-08-28 10:48:44 +02:00
FreddleSpl0it 822d9a7de6 [Web] rename goto in alias table 2024-08-27 10:07:07 +02:00
milkmaker 0066040bdc Translations update from Weblate (#6049)
* [Web] Updated lang.cs-cz.json

Co-authored-by: Kristian Feldsam <feldsam@gmail.com>

* [Web] Updated lang.fr-fr.json

Co-authored-by: Samuel F <20537389+samuelfranzini@users.noreply.github.com>

---------

Co-authored-by: Kristian Feldsam <feldsam@gmail.com>
Co-authored-by: Samuel F <20537389+samuelfranzini@users.noreply.github.com>
2024-08-24 14:09:28 +02:00
FreddleSpl0it 8e7b27aae4 [DockerApi] rework doveadm__get_acl function 2024-08-23 09:30:23 +02:00
FreddleSpl0it c62b467ac4 [PHP-FPM] Use redis as session store 2024-08-22 11:16:01 +02:00
FreddleSpl0it be5a181be5 [Web][DockerApi] migrate imap acl on mbox rename 2024-08-22 10:10:05 +02:00
FreddleSpl0it 10dfd0a443 [Web][DockerApi] Add the ability to rename the local part of a mailbox 2024-08-21 10:10:34 +02:00
milkmaker cc5138da13 Translations update from Weblate (#6039)
* [Web] Updated lang.fr-fr.json

[Web] Updated lang.fr-fr.json

Co-authored-by: GeistFighter <lorentzjohan1@gmail.com>
Co-authored-by: Samuel F <20537389+samuelfranzini@users.noreply.github.com>

* [Web] Updated lang.fi-fi.json

Co-authored-by: Berttas <mika@tarh.fi>

* [Web] Updated lang.ru-ru.json

Co-authored-by: Habetdin <15926758+Habetdin@users.noreply.github.com>

* [Web] Updated lang.uk-ua.json

Co-authored-by: DRago_Angel <dragoangel@users.noreply.translate.mailcow.email>

* [Web] Updated lang.pt-br.json

Co-authored-by: xmacaba <lixo@macaba.com.br>

---------

Co-authored-by: GeistFighter <lorentzjohan1@gmail.com>
Co-authored-by: Samuel F <20537389+samuelfranzini@users.noreply.github.com>
Co-authored-by: Berttas <mika@tarh.fi>
Co-authored-by: Habetdin <15926758+Habetdin@users.noreply.github.com>
Co-authored-by: DRago_Angel <dragoangel@users.noreply.translate.mailcow.email>
Co-authored-by: xmacaba <lixo@macaba.com.br>
2024-08-20 21:34:04 +02:00
q16marvin 19deda31bc Update functions.mailbox.inc.php 2024-02-09 11:23:47 +01:00
q16marvin 4f47534824 Update mailbox.js 2024-02-09 11:23:09 +01:00
333 changed files with 11665 additions and 5995 deletions
+1 -1
View File
@@ -1,7 +1,7 @@
blank_issues_enabled: false blank_issues_enabled: false
contact_links: contact_links:
- name: ❓ Community-driven support (Free) - name: ❓ Community-driven support (Free)
url: https://docs.mailcow.email/#get-support url: https://docs.mailcow.email/#community-support-and-chat
about: Please use the community forum for questions or assistance about: Please use the community forum for questions or assistance
- name: 🔥 Premium Support (Paid) - name: 🔥 Premium Support (Paid)
url: https://www.servercow.de/mailcow?lang=en#support url: https://www.servercow.de/mailcow?lang=en#support
-6
View File
@@ -15,12 +15,6 @@
"data\/web\/inc\/lib\/vendor\/**" "data\/web\/inc\/lib\/vendor\/**"
], ],
"regexManagers": [ "regexManagers": [
{
"fileMatch": ["^helper-scripts\/nextcloud.sh$"],
"matchStrings": [
"#\\srenovate:\\sdatasource=(?<datasource>.*?) depName=(?<depName>.*?)( versioning=(?<versioning>.*?))?( extractVersion=(?<extractVersion>.*?))?\\s.*?_VERSION=(?<currentValue>.*)"
]
},
{ {
"fileMatch": ["(^|/)Dockerfile[^/]*$"], "fileMatch": ["(^|/)Dockerfile[^/]*$"],
"matchStrings": [ "matchStrings": [
@@ -10,9 +10,9 @@ jobs:
if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging if: github.event.pull_request.base.ref != 'staging' #check if the target branch is not staging
steps: steps:
- name: Send message - name: Send message
uses: thollander/actions-comment-pull-request@v2.5.0 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!
@@ -14,7 +14,7 @@ jobs:
pull-requests: write pull-requests: write
steps: steps:
- name: Mark/Close Stale Issues and Pull Requests 🗑️ - name: Mark/Close Stale Issues and Pull Requests 🗑️
uses: actions/stale@v9.0.0 uses: actions/stale@v9.1.0
with: with:
repo-token: ${{ secrets.STALE_ACTION_PAT }} repo-token: ${{ secrets.STALE_ACTION_PAT }}
days-before-stale: 60 days-before-stale: 60
-1
View File
@@ -23,7 +23,6 @@ jobs:
- "postfix-mailcow" - "postfix-mailcow"
- "rspamd-mailcow" - "rspamd-mailcow"
- "sogo-mailcow" - "sogo-mailcow"
- "solr-mailcow"
- "unbound-mailcow" - "unbound-mailcow"
- "watchdog-mailcow" - "watchdog-mailcow"
runs-on: ubuntu-latest runs-on: ubuntu-latest
+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
@@ -22,7 +22,7 @@ jobs:
bash helper-scripts/update_postscreen_whitelist.sh bash helper-scripts/update_postscreen_whitelist.sh
- name: Create Pull Request - name: Create Pull Request
uses: peter-evans/create-pull-request@v6 uses: peter-evans/create-pull-request@v7
with: with:
token: ${{ secrets.mailcow_action_Update_postscreen_access_cidr_pat }} token: ${{ secrets.mailcow_action_Update_postscreen_access_cidr_pat }}
commit-message: update postscreen_access.cidr commit-message: update postscreen_access.cidr
+5 -1
View File
@@ -23,6 +23,7 @@ data/conf/dovecot/sni.conf
data/conf/dovecot/sogo-sso.conf data/conf/dovecot/sogo-sso.conf
data/conf/dovecot/sogo_trusted_ip.conf data/conf/dovecot/sogo_trusted_ip.conf
data/conf/dovecot/sql data/conf/dovecot/sql
data/conf/dovecot/conf.d/fts.conf
data/conf/nextcloud-*.bak data/conf/nextcloud-*.bak
data/conf/nginx/*.active data/conf/nginx/*.active
data/conf/nginx/*.bak data/conf/nginx/*.bak
@@ -45,7 +46,10 @@ data/conf/rspamd/override.d/*
data/conf/sogo/custom-theme.js 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/sogo-full.svg data/conf/sogo/cron.creds
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/*
+2 -2
View File
@@ -4,9 +4,9 @@ exec 5>&1
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
export REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" export REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else else
export REDIS_CMDLINE="redis-cli -h redis -p 6379" export REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi fi
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
+1 -1
View File
@@ -124,7 +124,7 @@ case "$SUCCESS" in
;; ;;
*) # non-zero is non-fun *) # non-zero is non-fun
log_f "Failed to obtain certificate ${CERT} for domains '${CERT_DOMAINS[*]}'" log_f "Failed to obtain certificate ${CERT} for domains '${CERT_DOMAINS[*]}'"
redis-cli -h redis SET ACME_FAIL_TIME "$(date +%s)" redis-cli -h redis -a ${REDISPASS} --no-auth-warning SET ACME_FAIL_TIME "$(date +%s)"
exit 100${SUCCESS} exit 100${SUCCESS}
;; ;;
esac esac
+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+=($!)
+3 -3
View File
@@ -34,9 +34,9 @@ async def lifespan(app: FastAPI):
# Init redis client # Init redis client
if os.environ['REDIS_SLAVEOF_IP'] != "": if os.environ['REDIS_SLAVEOF_IP'] != "":
redis_client = redis = await aioredis.from_url(f"redis://{os.environ['REDIS_SLAVEOF_IP']}:{os.environ['REDIS_SLAVEOF_PORT']}/0") redis_client = redis = await aioredis.from_url(f"redis://{os.environ['REDIS_SLAVEOF_IP']}:{os.environ['REDIS_SLAVEOF_PORT']}/0", password=os.environ['REDISPASS'])
else: else:
redis_client = redis = await aioredis.from_url("redis://redis-mailcow:6379/0") redis_client = redis = await aioredis.from_url("redis://redis-mailcow:6379/0", password=os.environ['REDISPASS'])
# Init docker clients # Init docker clients
sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto') sync_docker_client = docker.DockerClient(base_url='unix://var/run/docker.sock', version='auto')
@@ -130,7 +130,7 @@ async def get_containers():
async def post_containers(container_id : str, post_action : str, request: Request): async def post_containers(container_id : str, post_action : str, request: Request):
global dockerapi global dockerapi
try : try:
request_json = await request.json() request_json = await request.json()
except Exception as err: except Exception as err:
request_json = {} request_json = {}
@@ -342,6 +342,30 @@ class DockerApi:
cmd = ["/bin/bash", "-c", cmd_vmail] cmd = ["/bin/bash", "-c", cmd_vmail]
maildir_cleanup = container.exec_run(cmd, user='vmail') maildir_cleanup = container.exec_run(cmd, user='vmail')
return self.exec_run_handler('generic', maildir_cleanup) return self.exec_run_handler('generic', maildir_cleanup)
# api call: container_post - post_action: exec - cmd: maildir - task: move
def container_post__exec__maildir__move(self, request_json, **kwargs):
if 'container_id' in kwargs:
filters = {"id": kwargs['container_id']}
elif 'container_name' in kwargs:
filters = {"name": kwargs['container_name']}
if 'old_maildir' in request_json and 'new_maildir' in request_json:
for container in self.sync_docker_client.containers.list(filters=filters):
vmail_name = request_json['old_maildir'].replace("'", "'\\''")
new_vmail_name = request_json['new_maildir'].replace("'", "'\\''")
cmd_vmail = f"if [[ -d '/var/vmail/{vmail_name}' ]]; then /bin/mv '/var/vmail/{vmail_name}' '/var/vmail/{new_vmail_name}'; fi"
index_name = request_json['old_maildir'].split("/")
new_index_name = request_json['new_maildir'].split("/")
if len(index_name) > 1 and len(new_index_name) > 1:
index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''")
new_index_name = new_index_name[1].replace("'", "'\\''") + "@" + new_index_name[0].replace("'", "'\\''")
cmd_vmail_index = f"if [[ -d '/var/vmail_index/{index_name}' ]]; then /bin/mv '/var/vmail_index/{index_name}' '/var/vmail_index/{new_index_name}_index'; fi"
cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index]
else:
cmd = ["/bin/bash", "-c", cmd_vmail]
maildir_move = container.exec_run(cmd, user='vmail')
return self.exec_run_handler('generic', maildir_move)
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password # api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
def container_post__exec__rspamd__worker_password(self, request_json, **kwargs): def container_post__exec__rspamd__worker_password(self, request_json, **kwargs):
if 'container_id' in kwargs: if 'container_id' in kwargs:
@@ -374,6 +398,121 @@ class DockerApi:
self.logger.error('failed changing Rspamd password') self.logger.error('failed changing Rspamd password')
res = { 'type': 'danger', 'msg': 'command did not complete' } res = { 'type': 'danger', 'msg': 'command did not complete' }
return Response(content=json.dumps(res, indent=4), media_type="application/json") return Response(content=json.dumps(res, indent=4), media_type="application/json")
# api call: container_post - post_action: exec - cmd: sogo - task: rename
def container_post__exec__sogo__rename_user(self, request_json, **kwargs):
if 'container_id' in kwargs:
filters = {"id": kwargs['container_id']}
elif 'container_name' in kwargs:
filters = {"name": kwargs['container_name']}
if 'old_username' in request_json and 'new_username' in request_json:
for container in self.sync_docker_client.containers.list(filters=filters):
old_username = request_json['old_username'].replace("'", "'\\''")
new_username = request_json['new_username'].replace("'", "'\\''")
sogo_return = container.exec_run(["/bin/bash", "-c", f"sogo-tool rename-user '{old_username}' '{new_username}'"], user='sogo')
return self.exec_run_handler('generic', sogo_return)
# api call: container_post - post_action: exec - cmd: doveadm - task: get_acl
def container_post__exec__doveadm__get_acl(self, request_json, **kwargs):
if 'container_id' in kwargs:
filters = {"id": kwargs['container_id']}
elif 'container_name' in kwargs:
filters = {"name": kwargs['container_name']}
for container in self.sync_docker_client.containers.list(filters=filters):
id = request_json['id'].replace("'", "'\\''")
shared_folders = container.exec_run(["/bin/bash", "-c", f"doveadm mailbox list -u '{id}'"])
shared_folders = shared_folders.output.decode('utf-8')
shared_folders = shared_folders.splitlines()
formatted_acls = []
mailbox_seen = []
for shared_folder in shared_folders:
if "Shared" not in shared_folder:
mailbox = shared_folder.replace("'", "'\\''")
if mailbox in mailbox_seen:
continue
acls = container.exec_run(["/bin/bash", "-c", f"doveadm acl get -u '{id}' '{mailbox}'"])
acls = acls.output.decode('utf-8').strip().splitlines()
if len(acls) >= 2:
for acl in acls[1:]:
user_id, rights = acl.split(maxsplit=1)
user_id = user_id.split('=')[1]
mailbox_seen.append(mailbox)
formatted_acls.append({ 'user': id, 'id': user_id, 'mailbox': mailbox, 'rights': rights.split() })
elif "Shared" in shared_folder and "/" in shared_folder:
shared_folder = shared_folder.split("/")
if len(shared_folder) < 3:
continue
user = shared_folder[1].replace("'", "'\\''")
mailbox = '/'.join(shared_folder[2:]).replace("'", "'\\''")
if mailbox in mailbox_seen:
continue
acls = container.exec_run(["/bin/bash", "-c", f"doveadm acl get -u '{user}' '{mailbox}'"])
acls = acls.output.decode('utf-8').strip().splitlines()
if len(acls) >= 2:
for acl in acls[1:]:
user_id, rights = acl.split(maxsplit=1)
user_id = user_id.split('=')[1].replace("'", "'\\''")
if user_id == id and mailbox not in mailbox_seen:
mailbox_seen.append(mailbox)
formatted_acls.append({ 'user': user, 'id': id, 'mailbox': mailbox, 'rights': rights.split() })
return Response(content=json.dumps(formatted_acls, indent=4), media_type="application/json")
# api call: container_post - post_action: exec - cmd: doveadm - task: delete_acl
def container_post__exec__doveadm__delete_acl(self, request_json, **kwargs):
if 'container_id' in kwargs:
filters = {"id": kwargs['container_id']}
elif 'container_name' in kwargs:
filters = {"name": kwargs['container_name']}
for container in self.sync_docker_client.containers.list(filters=filters):
user = request_json['user'].replace("'", "'\\''")
mailbox = request_json['mailbox'].replace("'", "'\\''")
id = request_json['id'].replace("'", "'\\''")
if user and mailbox and id:
acl_delete_return = container.exec_run(["/bin/bash", "-c", f"doveadm acl delete -u '{user}' '{mailbox}' 'user={id}'"])
return self.exec_run_handler('generic', acl_delete_return)
# api call: container_post - post_action: exec - cmd: doveadm - task: set_acl
def container_post__exec__doveadm__set_acl(self, request_json, **kwargs):
if 'container_id' in kwargs:
filters = {"id": kwargs['container_id']}
elif 'container_name' in kwargs:
filters = {"name": kwargs['container_name']}
for container in self.sync_docker_client.containers.list(filters=filters):
user = request_json['user'].replace("'", "'\\''")
mailbox = request_json['mailbox'].replace("'", "'\\''")
id = request_json['id'].replace("'", "'\\''")
rights = ""
available_rights = [
"admin",
"create",
"delete",
"expunge",
"insert",
"lookup",
"post",
"read",
"write",
"write-deleted",
"write-seen"
]
for right in request_json['rights']:
right = right.replace("'", "'\\''").lower()
if right in available_rights:
rights += right + " "
if user and mailbox and id and rights:
acl_set_return = container.exec_run(["/bin/bash", "-c", f"doveadm acl set -u '{user}' '{mailbox}' 'user={id}' {rights}"])
return self.exec_run_handler('generic', acl_set_return)
# Collect host stats # Collect host stats
async def get_host_stats(self, wait=5): async def get_host_stats(self, wait=5):
-1
View File
@@ -105,7 +105,6 @@ RUN addgroup -g 5000 vmail \
dovecot-submissiond \ dovecot-submissiond \
dovecot-pigeonhole-plugin \ dovecot-pigeonhole-plugin \
dovecot-pop3d \ dovecot-pop3d \
dovecot-fts-solr \
dovecot-fts-flatcurve \ dovecot-fts-flatcurve \
&& arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \ && arch=$(arch | sed s/aarch64/arm64/ | sed s/x86_64/amd64/) \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$arch" \ && wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$arch" \
+1 -1
View File
@@ -2,7 +2,7 @@
source /source_env.sh source /source_env.sh
MAX_AGE=$(redis-cli --raw -h redis-mailcow GET Q_MAX_AGE) MAX_AGE=$(redis-cli --raw -h redis-mailcow -a ${REDISPASS} --no-auth-warning GET Q_MAX_AGE)
if [[ -z ${MAX_AGE} ]]; then if [[ -z ${MAX_AGE} ]]; then
echo "Max age for quarantine items not defined" echo "Max age for quarantine items not defined"
+31 -59
View File
@@ -14,9 +14,9 @@ done
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else else
REDIS_CMDLINE="redis-cli -h redis -p 6379" REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi fi
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
@@ -110,21 +110,16 @@ EOF
echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone echo -n ${ACL_ANYONE} > /etc/dovecot/acl_anyone
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY]) ]]; then if [[ "${SKIP_FTS}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo -e "\e[33mActivating Flatcurve as FTS Backend...\e[0m" echo -e "\e[33mDetecting SKIP_FTS=y... not enabling Flatcurve (FTS) then...\e[0m"
echo -e "\e[33mDepending on your previous setup a full reindex might be needed... \e[0m" echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication lazy_expunge' > /etc/dovecot/mail_plugins
echo -e "\e[34mVisit https://docs.mailcow.email/manual-guides/Dovecot/u_e-dovecot-fts/#fts-related-dovecot-commands to learn how to reindex\e[0m"
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins_imap
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_flatcurve notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify listescape replication' > /etc/dovecot/mail_plugins
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify listescape replication mail_log' > /etc/dovecot/mail_plugins_imap echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify listescape replication mail_log' > /etc/dovecot/mail_plugins_imap
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl notify listescape replication' > /etc/dovecot/mail_plugins_lmtp echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
else else
echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_solr listescape replication' > /etc/dovecot/mail_plugins echo -e "\e[32mDetecting SKIP_FTS=n... enabling Flatcurve (FTS)\e[0m"
echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_solr listescape replication' > /etc/dovecot/mail_plugins_imap echo -n 'quota acl zlib mail_crypt mail_crypt_acl mail_log notify fts fts_flatcurve listescape replication lazy_expunge' > /etc/dovecot/mail_plugins
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_solr notify listescape replication' > /etc/dovecot/mail_plugins_lmtp echo -n 'quota imap_quota imap_acl acl zlib imap_zlib imap_sieve mail_crypt mail_crypt_acl notify mail_log fts fts_flatcurve listescape replication' > /etc/dovecot/mail_plugins_imap
echo -n 'quota sieve acl zlib mail_crypt mail_crypt_acl fts fts_flatcurve notify listescape replication' > /etc/dovecot/mail_plugins_lmtp
fi fi
chmod 644 /etc/dovecot/mail_plugins /etc/dovecot/mail_plugins_imap /etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl chmod 644 /etc/dovecot/mail_plugins /etc/dovecot/mail_plugins_imap /etc/dovecot/mail_plugins_lmtp /templates/quarantine.tpl
@@ -247,51 +242,6 @@ function script_deinit()
end end
EOF EOF
# Temporarily set FTS depending on user choice inside mailcow.conf. Will be removed as soon as Solr is dropped
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cat <<EOF > /etc/dovecot/conf.d/fts.conf
# Autogenerated by mailcow
plugin {
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
fts = flatcurve
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
fts_tokenizer_email_address = maxlen=100
fts_tokenizer_generic = algorithm=simple maxlen=30
# These are not flatcurve settings, but required for Dovecot FTS. See
# Dovecot FTS Configuration link above for further information.
fts_languages = en es de
fts_tokenizers = generic email-address
# OPTIONAL: Recommended default FTS core configuration
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
}
EOF
elif [[ ! "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])$ ]]; then
cat <<EOF > /etc/dovecot/conf.d/fts.conf
# Autogenerated by mailcow
plugin {
fts = solr
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
fts_solr = url=http://solr:8983/solr/dovecot-fts/
fts_tokenizers = generic email-address
fts_tokenizer_generic = algorithm=simple
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
}
EOF
fi
# Replace patterns in app-passdb.lua # Replace patterns in app-passdb.lua
sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua sed -i "s/__DBUSER__/${DBUSER}/g" /etc/dovecot/lua/passwd-verify.lua
sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua sed -i "s/__DBPASS__/${DBPASS}/g" /etc/dovecot/lua/passwd-verify.lua
@@ -371,6 +321,8 @@ EOF
# Create random master Password for SOGo SSO # Create random master Password for SOGo SSO
RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1) RAND_PASS=$(cat /dev/urandom | tr -dc 'a-z0-9' | fold -w 32 | head -n 1)
echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass echo -n ${RAND_PASS} > /etc/phpfpm/sogo-sso.pass
# Creating additional creds file for SOGo notify crons (calendars, etc)
echo -n ${RAND_USER}@mailcow.local:${RAND_PASS} > /etc/sogo/cron.creds
cat <<EOF > /etc/dovecot/sogo-sso.conf cat <<EOF > /etc/dovecot/sogo-sso.conf
# Autogenerated by mailcow # Autogenerated by mailcow
passdb { passdb {
@@ -396,6 +348,15 @@ mail_replica = tcp:${MAILCOW_REPLICA_IP}:${DOVEADM_REPLICA_PORT}
EOF EOF
fi fi
# Setting variables for indexer-worker inside fts.conf automatically according to mailcow.conf settings
if [[ "${SKIP_FTS}" =~ ^([nN][oO]|[nN])+$ ]]; then
echo -e "\e[94mConfiguring FTS Settings...\e[0m"
echo -e "\e[94mSetting FTS Memory Limit (per process) to ${FTS_HEAP} MB\e[0m"
sed -i "s/vsz_limit\s*=\s*[0-9]*\s*MB*/vsz_limit=${FTS_HEAP} MB/" /etc/dovecot/conf.d/fts.conf
echo -e "\e[94mSetting FTS Process Limit to ${FTS_PROCS}\e[0m"
sed -i "s/process_limit\s*=\s*[0-9]*/process_limit=${FTS_PROCS}/" /etc/dovecot/conf.d/fts.conf
fi
# 401 is user dovecot # 401 is user dovecot
if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then if [[ ! -s /mail_crypt/ecprivkey.pem || ! -s /mail_crypt/ecpubkey.pem ]]; then
openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem openssl ecparam -name prime256v1 -genkey | openssl pkey -out /mail_crypt/ecprivkey.pem
@@ -405,6 +366,17 @@ else
chown 401 /mail_crypt/ecprivkey.pem /mail_crypt/ecpubkey.pem chown 401 /mail_crypt/ecprivkey.pem /mail_crypt/ecpubkey.pem
fi fi
# Fix OpenSSL 3.X TLS1.0, 1.1 support (https://community.mailcow.email/d/4062-hi-all/20)
if grep -qE 'ssl_min_protocol\s*=\s*(TLSv1|TLSv1\.1)\s*$' /etc/dovecot/dovecot.conf /etc/dovecot/extra.conf; then
sed -i '/\[openssl_init\]/a ssl_conf = ssl_configuration' /etc/ssl/openssl.cnf
echo "[ssl_configuration]" >> /etc/ssl/openssl.cnf
echo "system_default = tls_system_default" >> /etc/ssl/openssl.cnf
echo "[tls_system_default]" >> /etc/ssl/openssl.cnf
echo "MinProtocol = TLSv1" >> /etc/ssl/openssl.cnf
echo "CipherString = DEFAULT@SECLEVEL=0" >> /etc/ssl/openssl.cnf
fi
# Compile sieve scripts # Compile sieve scripts
sievec /var/vmail/sieve/global_sieve_before.sieve sievec /var/vmail/sieve/global_sieve_before.sieve
sievec /var/vmail/sieve/global_sieve_after.sieve sievec /var/vmail/sieve/global_sieve_after.sieve
+1 -1
View File
@@ -1,6 +1,6 @@
#!/bin/bash #!/bin/bash
if [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ && ! "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then if [[ "${SKIP_FTS}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
exit 0 exit 0
else else
doveadm fts optimize -A doveadm fts optimize -A
@@ -31,7 +31,7 @@ try:
while True: while True:
try: try:
r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0) r = redis.StrictRedis(host='redis', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS'])
r.ping() r.ping()
except Exception as ex: except Exception as ex:
print('%s - trying again...' % (ex)) print('%s - trying again...' % (ex))
+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) 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))
+2 -2
View File
@@ -4,9 +4,9 @@ source /source_env.sh
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else else
REDIS_CMDLINE="redis-cli -h redis -p 6379" REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi fi
# Is replication active? # Is replication active?
+1 -1
View File
@@ -11,7 +11,7 @@ else
fi fi
# Deploy # Deploy
if curl --connect-timeout 15 --retry 10 --max-time 30 https://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"' | tr -dc '0-9').tar.gz --output /tmp/sa-rules-heinlein.tar.gz; then if curl --connect-timeout 15 --retry 5 --max-time 30 https://www.spamassassin.heinlein-support.de/$(dig txt 1.4.3.spamassassin.heinlein-support.de +short | tr -d '"' | tr -dc '0-9').tar.gz --output /tmp/sa-rules-heinlein.tar.gz; then
if gzip -t /tmp/sa-rules-heinlein.tar.gz; then if gzip -t /tmp/sa-rules-heinlein.tar.gz; then
tar xfvz /tmp/sa-rules-heinlein.tar.gz -C /tmp/sa-rules-heinlein tar xfvz /tmp/sa-rules-heinlein.tar.gz -C /tmp/sa-rules-heinlein
cat /tmp/sa-rules-heinlein/*cf > /etc/rspamd/custom/sa-rules cat /tmp/sa-rules-heinlein/*cf > /etc/rspamd/custom/sa-rules
@@ -20,6 +20,7 @@ destination d_redis_ui_log {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis1") persist-name("redis1")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis2") persist-name("redis2")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
@@ -36,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);
+7
View File
@@ -20,6 +20,7 @@ destination d_redis_ui_log {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis1") persist-name("redis1")
port(6379) port(6379)
auth("`REDISPASS`")
command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "DOVECOT_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis2") persist-name("redis2")
port(6379) port(6379)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
@@ -36,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);
+2 -2
View File
@@ -10,9 +10,9 @@ catch_non_zero() {
source /source_env.sh source /source_env.sh
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else else
REDIS_CMDLINE="redis-cli -h redis -p 6379" REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi fi
catch_non_zero "${REDIS_CMDLINE} LTRIM ACME_LOG 0 ${LOG_LINES}" catch_non_zero "${REDIS_CMDLINE} LTRIM ACME_LOG 0 ${LOG_LINES}"
catch_non_zero "${REDIS_CMDLINE} LTRIM POSTFIX_MAILLOG 0 ${LOG_LINES}" catch_non_zero "${REDIS_CMDLINE} LTRIM POSTFIX_MAILLOG 0 ${LOG_LINES}"
+6 -7
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:
@@ -434,9 +433,9 @@ if __name__ == '__main__':
redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '') redis_slaveof_ip = os.getenv('REDIS_SLAVEOF_IP', '')
redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '') redis_slaveof_port = os.getenv('REDIS_SLAVEOF_PORT', '')
if "".__eq__(redis_slaveof_ip): if "".__eq__(redis_slaveof_ip):
r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0) r = redis.StrictRedis(host=os.getenv('IPV4_NETWORK', '172.22.1') + '.249', decode_responses=True, port=6379, db=0, password=os.environ['REDISPASS'])
else: else:
r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0) r = redis.StrictRedis(host=redis_slaveof_ip, decode_responses=True, port=redis_slaveof_port, db=0, password=os.environ['REDISPASS'])
r.ping() r.ping()
pubsub = r.pubsub() pubsub = r.pubsub()
except Exception as ex: except Exception as ex:
+18
View File
@@ -0,0 +1,18 @@
FROM nginx:alpine
LABEL maintainer "The Infrastructure Company GmbH <info@servercow.de>"
ENV PIP_BREAK_SYSTEM_PACKAGES=1
RUN apk add --no-cache nginx \
python3 \
py3-pip && \
pip install --upgrade pip && \
pip install Jinja2
RUN mkdir -p /etc/nginx/includes
COPY ./bootstrap.py /
COPY ./docker-entrypoint.sh /
ENTRYPOINT ["/docker-entrypoint.sh"]
CMD ["nginx", "-g", "daemon off;"]
+100
View File
@@ -0,0 +1,100 @@
import os
import subprocess
from jinja2 import Environment, FileSystemLoader
def includes_conf(env, template_vars):
server_name = "server_name.active"
listen_plain = "listen_plain.active"
listen_ssl = "listen_ssl.active"
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_ssl_config = f"listen {template_vars['HTTPS_PORT']};"
if not template_vars['DISABLE_IPv6']:
listen_plain_config += f"\nlisten [::]:{template_vars['HTTP_PORT']};"
listen_ssl_config += f"\nlisten [::]:{template_vars['HTTPS_PORT']} ssl;"
listen_ssl_config += "\nhttp2 on;"
with open(f"/etc/nginx/conf.d/{server_name}", "w") as f:
f.write(server_name_config)
with open(f"/etc/nginx/conf.d/{listen_plain}", "w") as f:
f.write(listen_plain_config)
with open(f"/etc/nginx/conf.d/{listen_ssl}", "w") as f:
f.write(listen_ssl_config)
def sites_default_conf(env, template_vars):
config_name = "sites-default.conf"
template = env.get_template(f"{config_name}.j2")
config = template.render(template_vars)
with open(f"/etc/nginx/includes/{config_name}", "w") as f:
f.write(config)
def nginx_conf(env, template_vars):
config_name = "nginx.conf"
template = env.get_template(f"{config_name}.j2")
config = template.render(template_vars)
with open(f"/etc/nginx/{config_name}", "w") as f:
f.write(config)
def prepare_template_vars():
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 = {
'IPV4_NETWORK': ipv4_network,
'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_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"),
'MAILCOW_HOSTNAME': os.getenv("MAILCOW_HOSTNAME", ""),
'ADDITIONAL_SERVER_NAMES': [item.strip() for item in additional_server_names.split(",") if item.strip()],
'HTTP_PORT': os.getenv("HTTP_PORT", "80"),
'HTTPS_PORT': os.getenv("HTTPS_PORT", "443"),
'SOGOHOST': os.getenv("SOGOHOST", ipv4_network + ".248"),
'RSPAMDHOST': os.getenv("RSPAMDHOST", "rspamd-mailcow"),
'PHPFPMHOST': os.getenv("PHPFPMHOST", "php-fpm-mailcow"),
'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/'
template_vars['valid_cert_dirs'] = []
for d in os.listdir(ssl_dir):
full_path = os.path.join(ssl_dir, d)
if not os.path.isdir(full_path):
continue
cert_path = os.path.join(full_path, 'cert.pem')
key_path = os.path.join(full_path, 'key.pem')
domains_path = os.path.join(full_path, 'domains')
if os.path.isfile(cert_path) and os.path.isfile(key_path) and os.path.isfile(domains_path):
with open(domains_path, 'r') as file:
domains = file.read().strip()
domains_list = domains.split()
if domains_list and template_vars["MAILCOW_HOSTNAME"] not in domains_list:
template_vars['valid_cert_dirs'].append({
'cert_path': full_path + '/',
'domains': domains
})
return template_vars
def main():
env = Environment(loader=FileSystemLoader('./etc/nginx/conf.d/templates'))
# Render config
print("Render config")
template_vars = prepare_template_vars()
sites_default_conf(env, template_vars)
nginx_conf(env, template_vars)
includes_conf(env, template_vars)
if __name__ == "__main__":
main()
+26
View File
@@ -0,0 +1,26 @@
#!/bin/sh
PHPFPMHOST=${PHPFPMHOST:-"php-fpm-mailcow"}
SOGOHOST=${SOGOHOST:-"$IPV4_NETWORK.248"}
RSPAMDHOST=${RSPAMDHOST:-"rspamd-mailcow"}
until ping ${PHPFPMHOST} -c1 > /dev/null; do
echo "Waiting for PHP..."
sleep 1
done
if ! printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
until ping ${SOGOHOST} -c1 > /dev/null; do
echo "Waiting for SOGo..."
sleep 1
done
fi
if ! printf "%s\n" "${SKIP_RSPAMD}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
until ping ${RSPAMDHOST} -c1 > /dev/null; do
echo "Waiting for Rspamd..."
sleep 1
done
fi
python3 /bootstrap.py
exec "$@"
+5 -5
View File
@@ -1,17 +1,17 @@
FROM php:8.2-fpm-alpine3.18 FROM php:8.2-fpm-alpine3.20
LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>" LABEL maintainer = "The Infrastructure Company GmbH <info@servercow.de>"
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?<version>.*)$ # renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced extractVersion=^v(?<version>.*)$
ARG APCU_PECL_VERSION=5.1.23 ARG APCU_PECL_VERSION=5.1.24
# renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=Imagick/imagick versioning=semver-coerced extractVersion=(?<version>.*)$
ARG IMAGICK_PECL_VERSION=3.7.0 ARG IMAGICK_PECL_VERSION=3.7.0
# renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?<version>.*)$ # renovate: datasource=github-tags depName=php/pecl-mail-mailparse versioning=semver-coerced extractVersion=^v(?<version>.*)$
ARG MAILPARSE_PECL_VERSION=3.1.6 ARG MAILPARSE_PECL_VERSION=3.1.8
# renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$ # renovate: datasource=github-tags depName=php-memcached-dev/php-memcached versioning=semver-coerced extractVersion=^v(?<version>.*)$
ARG MEMCACHED_PECL_VERSION=3.2.0 ARG MEMCACHED_PECL_VERSION=3.2.0
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced extractVersion=(?<version>.*)$
ARG REDIS_PECL_VERSION=6.0.2 ARG REDIS_PECL_VERSION=6.1.0
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$ # renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced extractVersion=(?<version>.*)$
ARG COMPOSER_VERSION=2.6.6 ARG COMPOSER_VERSION=2.6.6
@@ -77,7 +77,7 @@ RUN apk add -U --no-cache autoconf \
--with-webp \ --with-webp \
--with-xpm \ --with-xpm \
--with-avif \ --with-avif \
&& docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets sysvsem zip bcmath gmp \ && docker-php-ext-install -j 4 exif gd gettext intl ldap opcache pcntl pdo pdo_mysql pspell soap sockets zip bcmath gmp \
&& docker-php-ext-configure imap --with-imap --with-imap-ssl \ && docker-php-ext-configure imap --with-imap --with-imap-ssl \
&& docker-php-ext-install -j 4 imap \ && docker-php-ext-install -j 4 imap \
&& curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \ && curl --silent --show-error https://getcomposer.org/installer | php -- --version=${COMPOSER_VERSION} \
+11 -2
View File
@@ -10,16 +10,25 @@ done
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" REDIS_HOST=$REDIS_SLAVEOF_IP
REDIS_PORT=$REDIS_SLAVEOF_PORT
else else
REDIS_CMDLINE="redis-cli -h redis -p 6379" REDIS_HOST="redis"
REDIS_PORT="6379"
fi fi
REDIS_CMDLINE="redis-cli -h ${REDIS_HOST} -p ${REDIS_PORT} -a ${REDISPASS} --no-auth-warning"
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
echo "Waiting for Redis..." echo "Waiting for Redis..."
sleep 2 sleep 2
done done
# Set redis session store
echo -n '
session.save_handler = redis
session.save_path = "tcp://'${REDIS_HOST}':'${REDIS_PORT}'?auth='${REDISPASS}'"
' > /usr/local/etc/php/conf.d/session_store.ini
# Check mysql_upgrade (master and slave) # Check mysql_upgrade (master and slave)
CONTAINER_ID= CONTAINER_ID=
until [[ ! -z "${CONTAINER_ID}" ]] && [[ "${CONTAINER_ID}" =~ ^[[:alnum:]]*$ ]]; do until [[ ! -z "${CONTAINER_ID}" ]] && [[ "${CONTAINER_ID}" =~ ^[[:alnum:]]*$ ]]; do
@@ -12,4 +12,15 @@ if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf
fi fi
# Fix OpenSSL 3.X TLS1.0, 1.1 support (https://community.mailcow.email/d/4062-hi-all/20)
if grep -qE '\!SSLv2|\!SSLv3|>=TLSv1(\.[0-1])?$' /opt/postfix/conf/main.cf /opt/postfix/conf/extra.cf; then
sed -i '/\[openssl_init\]/a ssl_conf = ssl_configuration' /etc/ssl/openssl.cnf
echo "[ssl_configuration]" >> /etc/ssl/openssl.cnf
echo "system_default = tls_system_default" >> /etc/ssl/openssl.cnf
echo "[tls_system_default]" >> /etc/ssl/openssl.cnf
echo "MinProtocol = TLSv1" >> /etc/ssl/openssl.cnf
echo "CipherString = DEFAULT@SECLEVEL=0" >> /etc/ssl/openssl.cnf
fi
exec "$@" exec "$@"
+9 -1
View File
@@ -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
@@ -20,6 +20,7 @@ destination d_redis_ui_log {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis1") persist-name("redis1")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis2") persist-name("redis2")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
+2
View File
@@ -20,6 +20,7 @@ destination d_redis_ui_log {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis1") persist-name("redis1")
port(6379) port(6379)
auth("`REDISPASS`")
command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "POSTFIX_MAILLOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -28,6 +29,7 @@ destination d_redis_f2b_channel {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis2") persist-name("redis2")
port(6379) port(6379)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
+2 -2
View File
@@ -1,8 +1,8 @@
FROM debian:bookworm-slim 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.9.1-1~82f43560f ARG RSPAMD_VER=rspamd_3.11.0-2~90a175b45
ARG CODENAME=bookworm ARG CODENAME=bookworm
ENV LC_ALL=C ENV LC_ALL=C
+7 -5
View File
@@ -56,27 +56,29 @@ if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
cat <<EOF > /etc/rspamd/local.d/redis.conf cat <<EOF > /etc/rspamd/local.d/redis.conf
read_servers = "redis:6379"; read_servers = "redis:6379";
write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}"; write_servers = "${REDIS_SLAVEOF_IP}:${REDIS_SLAVEOF_PORT}";
password = "${REDISPASS}";
timeout = 10; timeout = 10;
EOF EOF
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do until [[ $(redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
echo "Waiting for Redis @redis-mailcow..." echo "Waiting for Redis @redis-mailcow..."
sleep 2 sleep 2
done done
until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} PING) == "PONG" ]]; do until [[ $(redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..." echo "Waiting for Redis @${REDIS_SLAVEOF_IP}..."
sleep 2 sleep 2
done done
redis-cli -h redis-mailcow SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT} redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning SLAVEOF ${REDIS_SLAVEOF_IP} ${REDIS_SLAVEOF_PORT}
else else
cat <<EOF > /etc/rspamd/local.d/redis.conf cat <<EOF > /etc/rspamd/local.d/redis.conf
servers = "redis:6379"; servers = "redis:6379";
password = "${REDISPASS}";
timeout = 10; timeout = 10;
EOF EOF
until [[ $(redis-cli -h redis-mailcow PING) == "PONG" ]]; do until [[ $(redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning PING) == "PONG" ]]; do
echo "Waiting for Redis slave..." echo "Waiting for Redis slave..."
sleep 2 sleep 2
done done
redis-cli -h redis-mailcow SLAVEOF NO ONE redis-cli -h redis-mailcow -a ${REDISPASS} --no-auth-warning SLAVEOF NO ONE
fi fi
# Provide additional lua modules # Provide additional lua modules
+4 -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,13 +33,13 @@ 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 \
&& apt-key adv --keyserver keys.openpgp.org --recv-key 74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 \ && wget -O- https://keys.openpgp.org/vks/v1/by-fingerprint/74FFC6D72B925A34B5D356BDF8A27B36A6E2EAE9 | gpg --dearmor | apt-key add - \
&& echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} ${DEBIAN_VERSION} sogo-v5" > /etc/apt/sources.list.d/sogo.list \ && echo "deb [trusted=yes] ${SOGO_DEBIAN_REPOSITORY} ${DEBIAN_VERSION} main" > /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 \
&& apt-get autoclean \ && apt-get autoclean \
&& rm -rf /var/lib/apt/lists/* /etc/apt/sources.list.d/sogo.list \ && rm -rf /var/lib/apt/lists/* \
&& touch /etc/default/locale && touch /etc/default/locale
COPY ./bootstrap-sogo.sh /bootstrap-sogo.sh COPY ./bootstrap-sogo.sh /bootstrap-sogo.sh
+2 -2
View File
@@ -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"
@@ -10,6 +10,8 @@ if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf cp /etc/syslog-ng/syslog-ng-redis_slave.conf /etc/syslog-ng/syslog-ng.conf
fi fi
echo "$TZ" > /etc/timezone
# Run hooks # Run hooks
for file in /hooks/*; do for file in /hooks/*; do
if [ -x "${file}" ]; then if [ -x "${file}" ]; then
@@ -22,6 +22,7 @@ destination d_redis_ui_log {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis1") persist-name("redis1")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -30,6 +31,7 @@ destination d_redis_f2b_channel {
host("`REDIS_SLAVEOF_IP`") host("`REDIS_SLAVEOF_IP`")
persist-name("redis2") persist-name("redis2")
port(`REDIS_SLAVEOF_PORT`) port(`REDIS_SLAVEOF_PORT`)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
+2
View File
@@ -22,6 +22,7 @@ destination d_redis_ui_log {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis1") persist-name("redis1")
port(6379) port(6379)
auth("`REDISPASS`")
command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n") command("LPUSH" "SOGO_LOG" "$(format-json time=\"$S_UNIXTIME\" priority=\"$PRIORITY\" program=\"$PROGRAM\" message=\"$MESSAGE\")\n")
); );
}; };
@@ -30,6 +31,7 @@ destination d_redis_f2b_channel {
host("redis-mailcow") host("redis-mailcow")
persist-name("redis2") persist-name("redis2")
port(6379) port(6379)
auth("`REDISPASS`")
command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)") command("PUBLISH" "F2B_CHANNEL" "$(sanitize $MESSAGE)")
); );
}; };
-31
View File
@@ -1,31 +0,0 @@
FROM solr:7.7-slim
USER root
# renovate: datasource=github-releases depName=tianon/gosu versioning=semver-coerced extractVersion=(?<version>.*)$
ARG GOSU_VERSION=1.17
COPY solr.sh /
COPY solr-config-7.7.0.xml /
COPY solr-schema-7.7.0.xml /
RUN dpkgArch="$(dpkg --print-architecture | awk -F- '{ print $NF }')" \
&& wget -O /usr/local/bin/gosu "https://github.com/tianon/gosu/releases/download/$GOSU_VERSION/gosu-$dpkgArch" \
&& chmod +x /usr/local/bin/gosu \
&& gosu nobody true \
&& apt-get update && apt-get install -y --no-install-recommends \
tzdata \
curl \
bash \
zip \
&& apt-get autoclean \
&& rm -rf /var/lib/apt/lists/* \
&& chmod +x /solr.sh \
&& sync \
&& bash /solr.sh --bootstrap
RUN zip -q -d /opt/solr/server/lib/ext/log4j-core-*.jar org/apache/logging/log4j/core/lookup/JndiLookup.class
RUN apt remove zip -y
CMD ["/solr.sh"]
-289
View File
@@ -1,289 +0,0 @@
<?xml version="1.0" encoding="UTF-8" ?>
<!-- This is the default config with stuff non-essential to Dovecot removed. -->
<config>
<!-- Controls what version of Lucene various components of Solr
adhere to. Generally, you want to use the latest version to
get all bug fixes and improvements. It is highly recommended
that you fully re-index after changing this setting as it can
affect both how text is indexed and queried.
-->
<luceneMatchVersion>7.7.0</luceneMatchVersion>
<!-- A 'dir' option by itself adds any files found in the directory
to the classpath, this is useful for including all jars in a
directory.
When a 'regex' is specified in addition to a 'dir', only the
files in that directory which completely match the regex
(anchored on both ends) will be included.
If a 'dir' option (with or without a regex) is used and nothing
is found that matches, a warning will be logged.
The examples below can be used to load some solr-contribs along
with their external dependencies.
-->
<lib dir="${solr.install.dir:../../../..}/contrib/extraction/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-cell-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/clustering/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-clustering-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/langid/lib/" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-langid-\d.*\.jar" />
<lib dir="${solr.install.dir:../../../..}/contrib/velocity/lib" regex=".*\.jar" />
<lib dir="${solr.install.dir:../../../..}/dist/" regex="solr-velocity-\d.*\.jar" />
<!-- Data Directory
Used to specify an alternate directory to hold all index data
other than the default ./data under the Solr home. If
replication is in use, this should match the replication
configuration.
-->
<dataDir>${solr.data.dir:}</dataDir>
<!-- The default high-performance update handler -->
<updateHandler class="solr.DirectUpdateHandler2">
<!-- Enables a transaction log, used for real-time get, durability, and
and solr cloud replica recovery. The log can grow as big as
uncommitted changes to the index, so use of a hard autoCommit
is recommended (see below).
"dir" - the target directory for transaction logs, defaults to the
solr data directory.
"numVersionBuckets" - sets the number of buckets used to keep
track of max version values when checking for re-ordered
updates; increase this value to reduce the cost of
synchronizing access to version buckets during high-volume
indexing, this requires 8 bytes (long) * numVersionBuckets
of heap space per Solr core.
-->
<updateLog>
<str name="dir">${solr.ulog.dir:}</str>
<int name="numVersionBuckets">${solr.ulog.numVersionBuckets:65536}</int>
</updateLog>
<!-- AutoCommit
Perform a hard commit automatically under certain conditions.
Instead of enabling autoCommit, consider using "commitWithin"
when adding documents.
http://wiki.apache.org/solr/UpdateXmlMessages
maxDocs - Maximum number of documents to add since the last
commit before automatically triggering a new commit.
maxTime - Maximum amount of time in ms that is allowed to pass
since a document was added before automatically
triggering a new commit.
openSearcher - if false, the commit causes recent index changes
to be flushed to stable storage, but does not cause a new
searcher to be opened to make those changes visible.
If the updateLog is enabled, then it's highly recommended to
have some sort of hard autoCommit to limit the log size.
-->
<autoCommit>
<maxTime>${solr.autoCommit.maxTime:15000}</maxTime>
<openSearcher>false</openSearcher>
</autoCommit>
<!-- softAutoCommit is like autoCommit except it causes a
'soft' commit which only ensures that changes are visible
but does not ensure that data is synced to disk. This is
faster and more near-realtime friendly than a hard commit.
-->
<autoSoftCommit>
<maxTime>${solr.autoSoftCommit.maxTime:-1}</maxTime>
</autoSoftCommit>
<!-- Update Related Event Listeners
Various IndexWriter related events can trigger Listeners to
take actions.
postCommit - fired after every commit or optimize command
postOptimize - fired after every optimize command
-->
</updateHandler>
<!-- ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Query section - these settings control query time things like caches
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ -->
<query>
<!-- Solr Internal Query Caches
There are two implementations of cache available for Solr,
LRUCache, based on a synchronized LinkedHashMap, and
FastLRUCache, based on a ConcurrentHashMap.
FastLRUCache has faster gets and slower puts in single
threaded operation and thus is generally faster than LRUCache
when the hit ratio of the cache is high (> 75%), and may be
faster under other scenarios on multi-cpu systems.
-->
<!-- Filter Cache
Cache used by SolrIndexSearcher for filters (DocSets),
unordered sets of *all* documents that match a query. When a
new searcher is opened, its caches may be prepopulated or
"autowarmed" using data from caches in the old searcher.
autowarmCount is the number of items to prepopulate. For
LRUCache, the autowarmed items will be the most recently
accessed items.
Parameters:
class - the SolrCache implementation LRUCache or
(LRUCache or FastLRUCache)
size - the maximum number of entries in the cache
initialSize - the initial capacity (number of entries) of
the cache. (see java.util.HashMap)
autowarmCount - the number of entries to prepopulate from
and old cache.
maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
to occupy. Note that when this option is specified, the size
and initialSize parameters are ignored.
-->
<filterCache class="solr.FastLRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- Query Result Cache
Caches results of searches - ordered lists of document ids
(DocList) based on a query, a sort, and the range of documents requested.
Additional supported parameter by LRUCache:
maxRamMB - the maximum amount of RAM (in MB) that this cache is allowed
to occupy
-->
<queryResultCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- Document Cache
Caches Lucene Document objects (the stored fields for each
document). Since Lucene internal document ids are transient,
this cache will not be autowarmed.
-->
<documentCache class="solr.LRUCache"
size="512"
initialSize="512"
autowarmCount="0"/>
<!-- custom cache currently used by block join -->
<cache name="perSegFilter"
class="solr.search.LRUCache"
size="10"
initialSize="0"
autowarmCount="10"
regenerator="solr.NoOpRegenerator" />
<!-- Lazy Field Loading
If true, stored fields that are not requested will be loaded
lazily. This can result in a significant speed improvement
if the usual case is to not load all stored fields,
especially if the skipped fields are large compressed text
fields.
-->
<enableLazyFieldLoading>true</enableLazyFieldLoading>
<!-- Result Window Size
An optimization for use with the queryResultCache. When a search
is requested, a superset of the requested number of document ids
are collected. For example, if a search for a particular query
requests matching documents 10 through 19, and queryWindowSize is 50,
then documents 0 through 49 will be collected and cached. Any further
requests in that range can be satisfied via the cache.
-->
<queryResultWindowSize>20</queryResultWindowSize>
<!-- Maximum number of documents to cache for any entry in the
queryResultCache.
-->
<queryResultMaxDocsCached>200</queryResultMaxDocsCached>
<!-- Use Cold Searcher
If a search request comes in and there is no current
registered searcher, then immediately register the still
warming searcher and use it. If "false" then all requests
will block until the first searcher is done warming.
-->
<useColdSearcher>false</useColdSearcher>
</query>
<!-- Request Dispatcher
This section contains instructions for how the SolrDispatchFilter
should behave when processing requests for this SolrCore.
-->
<requestDispatcher>
<httpCaching never304="true" />
</requestDispatcher>
<!-- Request Handlers
http://wiki.apache.org/solr/SolrRequestHandler
Incoming queries will be dispatched to a specific handler by name
based on the path specified in the request.
If a Request Handler is declared with startup="lazy", then it will
not be initialized until the first request that uses it.
-->
<!-- SearchHandler
http://wiki.apache.org/solr/SearchHandler
For processing Search Queries, the primary Request Handler
provided with Solr is "SearchHandler" It delegates to a sequent
of SearchComponents (see below) and supports distributed
queries across multiple shards
-->
<requestHandler name="/select" class="solr.SearchHandler">
<!-- default values for query parameters can be specified, these
will be overridden by parameters in the request
-->
<lst name="defaults">
<str name="echoParams">explicit</str>
<int name="rows">10</int>
</lst>
</requestHandler>
<initParams path="/update/**,/select">
<lst name="defaults">
<str name="df">_text_</str>
</lst>
</initParams>
<!-- Response Writers
http://wiki.apache.org/solr/QueryResponseWriter
Request responses will be written using the writer specified by
the 'wt' request parameter matching the name of a registered
writer.
The "default" writer is the default and will be used if 'wt' is
not specified in the request.
-->
<queryResponseWriter name="xml"
default="true"
class="solr.XMLResponseWriter" />
</config>
@@ -1,49 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<schema name="dovecot-fts" version="2.0">
<fieldType name="string" class="solr.StrField" omitNorms="true" sortMissingLast="true"/>
<fieldType name="long" class="solr.LongPointField" positionIncrementGap="0"/>
<fieldType name="boolean" class="solr.BoolField" sortMissingLast="true"/>
<fieldType name="text" class="solr.TextField" autoGeneratePhraseQueries="true" positionIncrementGap="100">
<analyzer type="index">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.EdgeNGramFilterFactory" minGramSize="3" maxGramSize="20"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/>
<filter class="solr.FlattenGraphFilterFactory"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
<analyzer type="query">
<tokenizer class="solr.StandardTokenizerFactory"/>
<filter class="solr.SynonymGraphFilterFactory" expand="true" ignoreCase="true" synonyms="synonyms.txt"/>
<filter class="solr.FlattenGraphFilterFactory"/>
<filter class="solr.StopFilterFactory" words="stopwords.txt" ignoreCase="true"/>
<filter class="solr.WordDelimiterGraphFilterFactory" catenateNumbers="1" generateNumberParts="1" splitOnCaseChange="1" generateWordParts="1" splitOnNumerics="1" catenateAll="1" catenateWords="1"/>
<filter class="solr.LowerCaseFilterFactory"/>
<filter class="solr.KeywordMarkerFilterFactory" protected="protwords.txt"/>
<filter class="solr.PorterStemFilterFactory"/>
</analyzer>
</fieldType>
<field name="id" type="string" indexed="true" required="true" stored="true"/>
<field name="uid" type="long" indexed="true" required="true" stored="true"/>
<field name="box" type="string" indexed="true" required="true" stored="true"/>
<field name="user" type="string" indexed="true" required="true" stored="true"/>
<field name="hdr" type="text" indexed="true" stored="false"/>
<field name="body" type="text" indexed="true" stored="false"/>
<field name="from" type="text" indexed="true" stored="false"/>
<field name="to" type="text" indexed="true" stored="false"/>
<field name="cc" type="text" indexed="true" stored="false"/>
<field name="bcc" type="text" indexed="true" stored="false"/>
<field name="subject" type="text" indexed="true" stored="false"/>
<!-- Used by Solr internally: -->
<field name="_version_" type="long" indexed="true" stored="true"/>
<uniqueKey>id</uniqueKey>
</schema>
-75
View File
@@ -1,75 +0,0 @@
#!/bin/bash
if [[ "${FLATCURVE_EXPERIMENTAL}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "FLATCURVE_EXPERIMENTAL=y, skipping Solr but enabling Flatcurve as FTS for Dovecot!"
echo "Solr will be removed in the future!"
sleep 365d
exit 0
elif [[ "${SKIP_SOLR}" =~ ^([yY][eE][sS]|[yY])+$ ]]; then
echo "SKIP_SOLR=y, skipping Solr..."
echo "HINT: You could try the newer FTS Backend Flatcurve, which is currently in experimental state..."
echo "Simply set FLATCURVE_EXPERIMENTAL=y inside your mailcow.conf and restart the stack afterwards!"
echo "Solr will be removed in the future!"
sleep 365d
exit 0
fi
MEM_TOTAL=$(awk '/MemTotal/ {print $2}' /proc/meminfo)
if [[ "${1}" != "--bootstrap" ]]; then
if [ ${MEM_TOTAL} -lt "2097152" ]; then
echo "System memory less than 2 GB, skipping Solr..."
sleep 365d
exit 0
fi
fi
set -e
# run the optional initdb
. /opt/docker-solr/scripts/run-initdb
# fixing volume permission
[[ -d /opt/solr/server/solr/dovecot-fts/data ]] && chown -R solr:solr /opt/solr/server/solr/dovecot-fts/data
if [[ "${1}" != "--bootstrap" ]]; then
sed -i '/SOLR_HEAP=/c\SOLR_HEAP="'${SOLR_HEAP:-1024}'m"' /opt/solr/bin/solr.in.sh
else
sed -i '/SOLR_HEAP=/c\SOLR_HEAP="256m"' /opt/solr/bin/solr.in.sh
fi
if [[ "${1}" == "--bootstrap" ]]; then
echo "Creating initial configuration"
echo "Modifying default config set"
cp /solr-config-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/solrconfig.xml
cp /solr-schema-7.7.0.xml /opt/solr/server/solr/configsets/_default/conf/schema.xml
rm /opt/solr/server/solr/configsets/_default/conf/managed-schema
echo "Starting local Solr instance to setup configuration"
gosu solr start-local-solr
echo "Creating core \"dovecot-fts\""
gosu solr /opt/solr/bin/solr create -c "dovecot-fts"
# See https://github.com/docker-solr/docker-solr/issues/27
echo "Checking core"
while ! wget -O - 'http://localhost:8983/solr/admin/cores?action=STATUS' | grep -q instanceDir; do
echo "Could not find any cores, waiting..."
sleep 3
done
echo "Created core \"dovecot-fts\""
echo "Stopping local Solr"
gosu solr stop-local-solr
exit 0
fi
echo "Starting up Solr..."
echo -e "\e[31mSolr is deprecated! You can try the new FTS System now by enabling FLATCURVE_EXPERIMENTAL=y inside mailcow.conf and restarting the stack\e[0m"
echo -e "\e[31mSolr will be removed completely soon!\e[0m"
sleep 15
exec gosu solr solr-foreground
+10 -10
View File
@@ -40,9 +40,9 @@ done
# Do not attempt to write to slave # Do not attempt to write to slave
if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then if [[ ! -z ${REDIS_SLAVEOF_IP} ]]; then
REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT}" REDIS_CMDLINE="redis-cli -h ${REDIS_SLAVEOF_IP} -p ${REDIS_SLAVEOF_PORT} -a ${REDISPASS} --no-auth-warning"
else else
REDIS_CMDLINE="redis-cli -h redis -p 6379" REDIS_CMDLINE="redis-cli -h redis -p 6379 -a ${REDISPASS} --no-auth-warning"
fi fi
until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do until [[ $(${REDIS_CMDLINE} PING) == "PONG" ]]; do
@@ -330,7 +330,7 @@ redis_checks() {
touch /tmp/redis-mailcow; echo "$(tail -50 /tmp/redis-mailcow)" > /tmp/redis-mailcow touch /tmp/redis-mailcow; echo "$(tail -50 /tmp/redis-mailcow)" > /tmp/redis-mailcow
host_ip=$(get_container_ip redis-mailcow) host_ip=$(get_container_ip redis-mailcow)
err_c_cur=${err_count} err_c_cur=${err_count}
/usr/lib/nagios/plugins/check_tcp -4 -H redis-mailcow -p 6379 -E -s "PING\n" -q "QUIT" -e "PONG" 2>> /tmp/redis-mailcow 1>&2; err_count=$(( ${err_count} + $? )) /usr/lib/nagios/plugins/check_tcp -4 -H redis-mailcow -p 6379 -E -s "AUTH ${REDISPASS}\nPING\n" -q "QUIT" -e "PONG" 2>> /tmp/redis-mailcow 1>&2; err_count=$(( ${err_count} + $? ))
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
progress "Redis" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c} progress "Redis" ${THRESHOLD} $(( ${THRESHOLD} - ${err_count} )) ${diff_c}
@@ -503,12 +503,12 @@ dovecot_repl_checks() {
err_count=0 err_count=0
diff_c=0 diff_c=0
THRESHOLD=${DOVECOT_REPL_THRESHOLD} THRESHOLD=${DOVECOT_REPL_THRESHOLD}
D_REPL_STATUS=$(redis-cli -h redis -r GET DOVECOT_REPL_HEALTH) D_REPL_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning -r GET DOVECOT_REPL_HEALTH)
# Reduce error count by 2 after restarting an unhealthy container # Reduce error count by 2 after restarting an unhealthy container
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
while [ ${err_count} -lt ${THRESHOLD} ]; do while [ ${err_count} -lt ${THRESHOLD} ]; do
err_c_cur=${err_count} err_c_cur=${err_count}
D_REPL_STATUS=$(redis-cli --raw -h redis GET DOVECOT_REPL_HEALTH) D_REPL_STATUS=$(redis-cli --raw -h redis -a ${REDISPASS} --no-auth-warning GET DOVECOT_REPL_HEALTH)
if [[ "${D_REPL_STATUS}" != "1" ]]; then if [[ "${D_REPL_STATUS}" != "1" ]]; then
err_count=$(( ${err_count} + 1 )) err_count=$(( ${err_count} + 1 ))
fi fi
@@ -578,19 +578,19 @@ ratelimit_checks() {
err_count=0 err_count=0
diff_c=0 diff_c=0
THRESHOLD=${RATELIMIT_THRESHOLD} THRESHOLD=${RATELIMIT_THRESHOLD}
RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid) RL_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 0 | jq .qid)
# Reduce error count by 2 after restarting an unhealthy container # Reduce error count by 2 after restarting an unhealthy container
trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1 trap "[ ${err_count} -gt 1 ] && err_count=$(( ${err_count} - 2 ))" USR1
while [ ${err_count} -lt ${THRESHOLD} ]; do while [ ${err_count} -lt ${THRESHOLD} ]; do
err_c_cur=${err_count} err_c_cur=${err_count}
RL_LOG_STATUS_PREV=${RL_LOG_STATUS} RL_LOG_STATUS_PREV=${RL_LOG_STATUS}
RL_LOG_STATUS=$(redis-cli -h redis LRANGE RL_LOG 0 0 | jq .qid) RL_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 0 | jq .qid)
if [[ ${RL_LOG_STATUS_PREV} != ${RL_LOG_STATUS} ]]; then if [[ ${RL_LOG_STATUS_PREV} != ${RL_LOG_STATUS} ]]; then
err_count=$(( ${err_count} + 1 )) err_count=$(( ${err_count} + 1 ))
echo 'Last 10 applied ratelimits (may overlap with previous reports).' > /tmp/ratelimit echo 'Last 10 applied ratelimits (may overlap with previous reports).' > /tmp/ratelimit
echo 'Full ratelimit buckets can be emptied by deleting the ratelimit hash from within mailcow UI (see /debug -> Protocols -> Ratelimit):' >> /tmp/ratelimit echo 'Full ratelimit buckets can be emptied by deleting the ratelimit hash from within mailcow UI (see /debug -> Protocols -> Ratelimit):' >> /tmp/ratelimit
echo >> /tmp/ratelimit echo >> /tmp/ratelimit
redis-cli --raw -h redis LRANGE RL_LOG 0 10 | jq . >> /tmp/ratelimit redis-cli --raw -h redis -a ${REDISPASS} --no-auth-warning LRANGE RL_LOG 0 10 | jq . >> /tmp/ratelimit
fi fi
[ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1 [ ${err_c_cur} -eq ${err_count} ] && [ ! $((${err_count} - 1)) -lt 0 ] && err_count=$((${err_count} - 1)) diff_c=1
[ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} )) [ ${err_c_cur} -ne ${err_count} ] && diff_c=$(( ${err_c_cur} - ${err_count} ))
@@ -673,7 +673,7 @@ acme_checks() {
err_count=0 err_count=0
diff_c=0 diff_c=0
THRESHOLD=${ACME_THRESHOLD} THRESHOLD=${ACME_THRESHOLD}
ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME) ACME_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning GET ACME_FAIL_TIME)
if [[ -z "${ACME_LOG_STATUS}" ]]; then if [[ -z "${ACME_LOG_STATUS}" ]]; then
${REDIS_CMDLINE} SET ACME_FAIL_TIME 0 ${REDIS_CMDLINE} SET ACME_FAIL_TIME 0
ACME_LOG_STATUS=0 ACME_LOG_STATUS=0
@@ -685,7 +685,7 @@ acme_checks() {
ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS} ACME_LOG_STATUS_PREV=${ACME_LOG_STATUS}
ACME_LC=0 ACME_LC=0
until [[ ! -z ${ACME_LOG_STATUS} ]] || [ ${ACME_LC} -ge 3 ]; do until [[ ! -z ${ACME_LOG_STATUS} ]] || [ ${ACME_LC} -ge 3 ]; do
ACME_LOG_STATUS=$(redis-cli -h redis GET ACME_FAIL_TIME 2> /dev/null) ACME_LOG_STATUS=$(redis-cli -h redis -a ${REDISPASS} --no-auth-warning GET ACME_FAIL_TIME 2> /dev/null)
sleep 3 sleep 3
ACME_LC=$((ACME_LC+1)) ACME_LC=$((ACME_LC+1))
done done
-130
View File
@@ -1,130 +0,0 @@
map $http_x_forwarded_proto $client_req_scheme_nc {
default $scheme;
https https;
}
server {
include /etc/nginx/conf.d/listen_ssl.active;
include /etc/nginx/conf.d/listen_plain.active;
include /etc/nginx/mime.types;
charset utf-8;
override_charset on;
ssl_certificate /etc/ssl/mail/cert.pem;
ssl_certificate_key /etc/ssl/mail/key.pem;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "noindex, nofollow" always;
add_header X-XSS-Protection "1; mode=block" always;
fastcgi_hide_header X-Powered-By;
server_name NC_SUBD;
root /web/nextcloud/;
location = /robots.txt {
allow all;
log_not_found off;
access_log off;
}
location = /.well-known/carddav {
return 301 $client_req_scheme_nc://$host/remote.php/dav;
}
location = /.well-known/caldav {
return 301 $client_req_scheme_nc://$host/remote.php/dav;
}
location = /.well-known/webfinger {
return 301 $client_req_scheme_nc://$host/index.php/.well-known/webfinger;
}
location = /.well-known/nodeinfo {
return 301 $client_req_scheme_nc://$host/index.php/.well-known/nodeinfo;
}
location ^~ /.well-known/acme-challenge/ {
default_type "text/plain";
root /web;
}
fastcgi_buffers 64 4K;
gzip on;
gzip_vary on;
gzip_comp_level 4;
gzip_min_length 256;
gzip_proxied expired no-cache no-store private no_last_modified no_etag auth;
gzip_types application/atom+xml application/javascript application/json application/ld+json application/manifest+json application/rss+xml application/vnd.geo+json application/vnd.ms-fontobject application/x-font-ttf application/x-web-app-manifest+json application/xhtml+xml application/xml font/opentype image/bmp image/svg+xml image/x-icon text/cache-manifest text/css text/plain text/vcard text/vnd.rim.location.xloc text/vtt text/x-component text/x-cross-domain-policy;
set_real_ip_from fc00::/7;
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
location / {
rewrite ^ /index.php$uri;
}
location ~ ^\/(?:build|tests|config|lib|3rdparty|templates|data)\/ {
deny all;
}
location ~ ^\/(?:\.|autotest|occ|issue|indie|db_|console) {
deny all;
}
location ~ ^\/(?:index|remote|public|cron|core\/ajax\/update|status|ocs\/v[12]|updater\/.+|ocs-provider\/.+)\.php(?:$|\/) {
fastcgi_split_path_info ^(.+?\.php)(\/.*|)$;
set $path_info $fastcgi_path_info;
try_files $fastcgi_script_name =404;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $path_info;
fastcgi_param HTTPS on;
# Avoid sending the security headers twice
fastcgi_param modHeadersAvailable true;
# Enable pretty urls
fastcgi_param front_controller_active true;
fastcgi_pass phpfpm:9002;
fastcgi_intercept_errors on;
fastcgi_request_buffering off;
client_max_body_size 0;
fastcgi_read_timeout 1200;
}
location ~ ^\/(?:updater|ocs-provider)(?:$|\/) {
try_files $uri/ =404;
index index.php;
}
location ~ \.(?:css|js|woff2?|svg|gif|map)$ {
try_files $uri /index.php$request_uri;
add_header Cache-Control "public, max-age=15778463";
add_header Referrer-Policy "no-referrer" always;
add_header X-Content-Type-Options "nosniff" always;
add_header X-Download-Options "noopen" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies "none" always;
add_header X-Robots-Tag "none" always;
add_header X-XSS-Protection "1; mode=block" always;
access_log off;
}
location ~ \.(?:png|html|ttf|ico|jpg|jpeg|bcmap)$ {
try_files $uri /index.php$request_uri;
access_log off;
}
}
-2
View File
@@ -1,2 +0,0 @@
#!/bin/bash
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) php /web/nextcloud/occ ${@}
+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-----
+37
View File
@@ -0,0 +1,37 @@
# mailcow FTS Flatcurve Settings, change them as you like.
plugin {
fts_autoindex = yes
fts_autoindex_exclude = \Junk
fts_autoindex_exclude2 = \Trash
# Tweak this setting if you only want to ensure big and frequent folders are indexed, not all.
fts_autoindex_max_recent_msgs = 20
fts = flatcurve
# Maximum term length can be set via the 'maxlen' argument (maxlen is
# specified in bytes, not number of UTF-8 characters)
fts_tokenizer_email_address = maxlen=100
fts_tokenizer_generic = algorithm=simple maxlen=30
# These are not flatcurve settings, but required for Dovecot FTS. See
# Dovecot FTS Configuration link above for further information.
fts_languages = en es de
fts_tokenizers = generic email-address
# OPTIONAL: Recommended default FTS core configuration
fts_filters = normalizer-icu snowball stopwords
fts_filters_en = lowercase snowball english-possessive stopwords
fts_index_timeout = 300s
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###
service indexer-worker {
# Max amount of simultaniously running indexer jobs.
process_limit=1
# Max amount of RAM used by EACH indexer process.
vsz_limit=128 MB
}
### THIS PART WILL BE CHANGED BY MODIFYING mailcow.conf AUTOMATICALLY DURING RUNTIME! ###
+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 = 128K thread_stack = 256K
skip-host-cache skip-host-cache
skip-name-resolve skip-name-resolve
log-warnings = 0 log-warnings = 0
-3
View File
@@ -1,3 +0,0 @@
map_hash_max_size 256;
map_hash_bucket_size 256;
-19
View File
@@ -1,19 +0,0 @@
server {
listen 8081;
listen [::]:8081;
index index.php index.html;
server_name _;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /dynmaps;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9001;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
-242
View File
@@ -1,242 +0,0 @@
include /etc/nginx/mime.types;
charset utf-8;
override_charset on;
server_tokens off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=15768000;";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Referrer-Policy strict-origin;
index index.php index.html;
client_max_body_size 0;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied off;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
location ~ ^/(fonts|js|css|img)/ {
expires max;
add_header Cache-Control public;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
fastcgi_hide_header X-Powered-By;
absolute_redirect off;
root /web;
location / {
try_files $uri $uri/ @strip-ext;
}
location /qhandler {
rewrite ^/qhandler/(.*)/(.*) /qhandler.php?action=$1&hash=$2;
}
location /edit {
rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
}
location @strip-ext {
rewrite ^(.*)$ $1.php last;
}
location ~ ^/api/v1/(.*)$ {
try_files $uri $uri/ /json_api.php?query=$1&$args;
}
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
# If behind reverse proxy, forwards the correct IP
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from fc00::/7;
real_ip_header X-Forwarded-For;
real_ip_recursive on;
rewrite ^/.well-known/caldav$ /SOGo/dav/ permanent;
rewrite ^/.well-known/carddav$ /SOGo/dav/ permanent;
location ^~ /principals {
return 301 /SOGo/dav;
}
location ^~ /inc/lib/ {
deny all;
return 403;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9002;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
}
location /rspamd/ {
location /rspamd/auth {
# proxy_pass is not inherited
proxy_pass http://rspamd:11334/auth;
proxy_intercept_errors on;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
error_page 401 /_rspamderror.php;
}
proxy_pass http://rspamd:11334/;
proxy_set_header Host $http_host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Real-IP $remote_addr;
proxy_redirect off;
}
location ~* ^/Autodiscover/Autodiscover.xml {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autodiscover.php =404;
}
location ~* ^/Autodiscover/Autodiscover.json {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autodiscover-json.php =404;
}
location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autoconfig.php =404;
}
location /sogo-auth-verify {
internal;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Content-Length "";
proxy_pass http://127.0.0.1:65510/sogo-auth;
proxy_pass_request_body off;
}
location ^~ /Microsoft-Server-ActiveSync {
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
include /etc/nginx/conf.d/sogo_eas.active;
proxy_connect_timeout 75;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_buffer_size 128k;
proxy_buffers 64 512k;
proxy_busy_buffers_size 512k;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
client_body_buffer_size 512k;
client_max_body_size 0;
}
location ^~ /SOGo {
location ~* ^/SOGo/so/.*\.(xml|js|html|xhtml)$ {
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
include /etc/nginx/conf.d/sogo.active;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
proxy_set_header x-webobjects-remote-host $remote_addr;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
proxy_set_header x-webobjects-server-port $server_port;
proxy_hide_header Content-Type;
add_header Content-Type text/plain;
break;
}
include /etc/nginx/conf.d/includes/sogo_proxy_auth.conf;
include /etc/nginx/conf.d/sogo.active;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
proxy_set_header x-webobjects-remote-host $remote_addr;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
proxy_set_header x-webobjects-server-port $server_port;
proxy_buffer_size 128k;
proxy_buffers 64 512k;
proxy_busy_buffers_size 512k;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
client_body_buffer_size 128k;
client_max_body_size 0;
break;
}
location ~* /sogo$ {
return 301 $client_req_scheme://$http_host/SOGo;
}
location /SOGo.woa/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /.woa/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /SOGo/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
}
include /etc/nginx/conf.d/site.*.custom;
error_page 502 @awaitingupstream;
location @awaitingupstream {
rewrite ^(.*)$ /_status.502.html break;
}
location ~ ^/cache/(.*)$ {
try_files $uri $uri/ /resource.php?file=$1;
}
@@ -1,8 +0,0 @@
auth_request /sogo-auth-verify;
auth_request_set $user $upstream_http_x_user;
auth_request_set $auth $upstream_http_x_auth;
auth_request_set $auth_type $upstream_http_x_auth_type;
proxy_set_header x-webobjects-remote-user "$user";
proxy_set_header Authorization "$auth";
proxy_set_header x-webobjects-auth-type "$auth_type";
-19
View File
@@ -1,19 +0,0 @@
server {
listen 9081;
index index.php index.html;
server_name _;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /meta_exporter;
client_max_body_size 10M;
location ~ \.php$ {
client_max_body_size 10M;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass phpfpm:9001;
fastcgi_index pipe.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
-10
View File
@@ -1,10 +0,0 @@
proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g;
server_names_hash_max_size 512;
server_names_hash_bucket_size 128;
map $http_x_forwarded_proto $client_req_scheme {
default $scheme;
https https;
}
include /etc/nginx/conf.d/sites.active;
@@ -1,2 +0,0 @@
listen ${HTTP_PORT};
listen [::]:${HTTP_PORT};
@@ -1,3 +0,0 @@
listen ${HTTPS_PORT} ssl;
listen [::]:${HTTPS_PORT} ssl;
http2 on;
+188
View File
@@ -0,0 +1,188 @@
user nginx;
worker_processes auto;
error_log /var/log/nginx/error.log notice;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
# map-size.conf:
map_hash_max_size 256;
map_hash_bucket_size 256;
# site.conf:
proxy_cache_path /tmp levels=1:2 keys_zone=sogo:10m inactive=24h max_size=1g;
server_names_hash_max_size 512;
server_names_hash_bucket_size 128;
map $http_x_forwarded_proto $client_req_scheme {
default $scheme;
https https;
}
{% 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 {
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 {{ MAILCOW_HOSTNAME }} autodiscover.* autoconfig.*;
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:
server {
listen 8081;
{% if not DISABLE_IPv6 %}
listen [::]:8081;
{%endif%}
index index.php index.html;
server_name _;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /dynmaps;
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9001;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
# rspamd meta_exporter:
server {
listen 9081;
index index.php index.html;
server_name _;
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
root /meta_exporter;
client_max_body_size 10M;
location ~ \.php$ {
client_max_body_size 10M;
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9001;
fastcgi_index pipe.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
}
}
{% for cert in valid_cert_dirs %}
server {
{% 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 {{ cert.cert_path }}cert.pem;
ssl_certificate_key {{ cert.cert_path }}key.pem;
server_name {{ cert.domains }};
include /etc/nginx/includes/sites-default.conf;
}
{% endfor %}
include /etc/nginx/conf.d/*.conf;
}
@@ -1 +0,0 @@
echo "server_name ${MAILCOW_HOSTNAME} autodiscover.* autoconfig.* $(echo ${ADDITIONAL_SERVER_NAMES} | tr ',' ' ');"
@@ -0,0 +1,287 @@
include /etc/nginx/mime.types;
charset utf-8;
override_charset on;
server_tokens off;
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305;
ssl_ecdh_curve X25519:X448:secp384r1:secp256k1;
ssl_session_cache shared:SSL:50m;
ssl_session_timeout 1d;
ssl_session_tickets off;
add_header Strict-Transport-Security "max-age=15768000;";
add_header X-Content-Type-Options nosniff;
add_header X-XSS-Protection "1; mode=block";
add_header X-Robots-Tag none;
add_header X-Download-Options noopen;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header X-Permitted-Cross-Domain-Policies none;
add_header Referrer-Policy strict-origin;
index index.php index.html;
client_max_body_size 0;
gzip on;
gzip_disable "msie6";
gzip_vary on;
gzip_proxied off;
gzip_comp_level 6;
gzip_buffers 16 8k;
gzip_http_version 1.1;
gzip_min_length 256;
gzip_types text/plain text/css application/json application/javascript application/x-javascript text/xml application/xml application/xml+rss text/javascript application/vnd.ms-fontobject application/x-font-ttf font/opentype image/svg+xml image/x-icon;
location ~ ^/(fonts|js|css|img)/ {
expires max;
add_header Cache-Control public;
}
error_log /var/log/nginx/error.log;
access_log /var/log/nginx/access.log;
fastcgi_hide_header X-Powered-By;
absolute_redirect off;
root /web;
# If behind reverse proxy, forwards the correct IP
set_real_ip_from 10.0.0.0/8;
set_real_ip_from 172.16.0.0/12;
set_real_ip_from 192.168.0.0/16;
set_real_ip_from fc00::/7;
{% 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;
{% else %}
real_ip_header proxy_protocol;
{% endif %}
real_ip_recursive on;
location @strip-ext {
rewrite ^(.*)$ $1.php last;
}
location ^~ /inc/lib/ {
deny all;
return 403;
}
location ^~ /.well-known/acme-challenge/ {
allow all;
default_type "text/plain";
}
rewrite ^/.well-known/caldav$ /SOGo/dav/ permanent;
rewrite ^/.well-known/carddav$ /SOGo/dav/ permanent;
location / {
try_files $uri $uri/ @strip-ext;
}
location /qhandler {
rewrite ^/qhandler/(.*)/(.*) /qhandler.php?action=$1&hash=$2;
}
location /edit {
rewrite ^/edit/(.*)/(.*) /edit.php?$1=$2;
}
location ~ ^/api/v1/(.*)$ {
try_files $uri $uri/ /json_api.php?query=$1&$args;
}
location ~ ^/cache/(.*)$ {
try_files $uri $uri/ /resource.php?file=$1;
}
location ~ \.php$ {
try_files $uri =404;
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9002;
fastcgi_index index.php;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
fastcgi_param PATH_INFO $fastcgi_path_info;
fastcgi_read_timeout 3600;
fastcgi_send_timeout 3600;
}
location ~* ^/Autodiscover/Autodiscover.xml {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autodiscover.php =404;
}
location ~* ^/Autodiscover/Autodiscover.json {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autodiscover-json.php =404;
}
location ~ /(?:m|M)ail/(?:c|C)onfig-v1.1.xml {
fastcgi_split_path_info ^(.+\.php)(/.+)$;
fastcgi_pass {{ PHPFPMHOST }}:9002;
include /etc/nginx/fastcgi_params;
fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
try_files /autoconfig.php =404;
}
{% if not SKIP_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_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;
}
{% endif %}
{% if not SKIP_SOGO %}
location ^~ /principals {
return 301 /SOGo/dav;
}
location /sogo-auth-verify {
internal;
proxy_set_header X-Original-URI $request_uri;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header Host $http_host;
proxy_set_header Content-Length "";
proxy_pass http://127.0.0.1:65510/sogo-auth;
proxy_pass_request_body off;
}
location ^~ /Microsoft-Server-ActiveSync {
auth_request /sogo-auth-verify;
auth_request_set $user $upstream_http_x_user;
auth_request_set $auth $upstream_http_x_auth;
auth_request_set $auth_type $upstream_http_x_auth_type;
proxy_set_header x-webobjects-remote-user "$user";
proxy_set_header Authorization "$auth";
proxy_set_header x-webobjects-auth-type "$auth_type";
proxy_pass http://{{ SOGOHOST }}:20000/SOGo/Microsoft-Server-ActiveSync;
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_connect_timeout 75;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
proxy_buffer_size 128k;
proxy_buffers 64 512k;
proxy_busy_buffers_size 512k;
proxy_set_header Host $http_host;
client_body_buffer_size 512k;
client_max_body_size 0;
}
location ^~ /SOGo {
location ~* ^/SOGo/so/.*\.(xml|js|html|xhtml)$ {
auth_request /sogo-auth-verify;
auth_request_set $user $upstream_http_x_user;
auth_request_set $auth $upstream_http_x_auth;
auth_request_set $auth_type $upstream_http_x_auth_type;
proxy_set_header x-webobjects-remote-user "$user";
proxy_set_header Authorization "$auth";
proxy_set_header x-webobjects-auth-type "$auth_type";
proxy_pass http://{{ SOGOHOST }}:20000;
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 Host $http_host;
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
proxy_set_header x-webobjects-remote-host $remote_addr;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
proxy_set_header x-webobjects-server-port $server_port;
proxy_hide_header Content-Type;
add_header Content-Type text/plain;
break;
}
auth_request /sogo-auth-verify;
auth_request_set $user $upstream_http_x_user;
auth_request_set $auth $upstream_http_x_auth;
auth_request_set $auth_type $upstream_http_x_auth_type;
proxy_set_header x-webobjects-remote-user "$user";
proxy_set_header Authorization "$auth";
proxy_set_header x-webobjects-auth-type "$auth_type";
proxy_pass http://{{ SOGOHOST }}:20000;
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 Host $http_host;
proxy_set_header x-webobjects-server-protocol HTTP/1.0;
proxy_set_header x-webobjects-remote-host $remote_addr;
proxy_set_header x-webobjects-server-name $server_name;
proxy_set_header x-webobjects-server-url $client_req_scheme://$http_host;
proxy_set_header x-webobjects-server-port $server_port;
proxy_buffer_size 128k;
proxy_buffers 64 512k;
proxy_busy_buffers_size 512k;
proxy_send_timeout 3600;
proxy_read_timeout 3600;
client_body_buffer_size 128k;
client_max_body_size 0;
break;
}
location ~* /sogo$ {
return 301 $client_req_scheme://$http_host/SOGo;
}
location /SOGo.woa/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /.woa/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location /SOGo/WebServerResources/ {
alias /usr/lib/GNUstep/SOGo/WebServerResources/;
}
location (^/SOGo/so/ControlPanel/Products/[^/]*UI/Resources/.*\.(jpg|png|gif|css|js)$) {
alias /usr/lib/GNUstep/SOGo/$1.SOGo/Resources/$2;
}
{% endif %}
include /etc/nginx/conf.d/site.*.custom;
error_page 502 @awaitingupstream;
location @awaitingupstream {
rewrite ^(.*)$ /_status.502.html break;
}
location ~* \.php$ {
return 404;
}
location ~* \.twig$ {
return 404;
}
@@ -1,38 +0,0 @@
echo '
server {
listen 127.0.0.1:65510;
include /etc/nginx/conf.d/listen_plain.active;
include /etc/nginx/conf.d/listen_ssl.active;
ssl_certificate /etc/ssl/mail/cert.pem;
ssl_certificate_key /etc/ssl/mail/key.pem;
include /etc/nginx/conf.d/server_name.active;
include /etc/nginx/conf.d/includes/site-defaults.conf;
}
';
for cert_dir in /etc/ssl/mail/*/ ; do
if [[ ! -f ${cert_dir}domains ]] || [[ ! -f ${cert_dir}cert.pem ]] || [[ ! -f ${cert_dir}key.pem ]]; then
continue
fi
# do not create vhost for default-certificate. the cert is already in the default server listen
domains="$(cat ${cert_dir}domains | sed -e 's/^[[:space:]]*//')"
case "${domains}" in
"") continue;;
"${MAILCOW_HOSTNAME}"*) continue;;
esac
echo -n '
server {
include /etc/nginx/conf.d/listen_ssl.active;
ssl_certificate '${cert_dir}'cert.pem;
ssl_certificate_key '${cert_dir}'key.pem;
';
echo -n '
server_name '${domains}';
include /etc/nginx/conf.d/includes/site-defaults.conf;
}
';
done
-1
View File
@@ -1 +0,0 @@
proxy_pass http://${IPV4_NETWORK}.248:20000;
@@ -1,5 +0,0 @@
if printf "%s\n" "${SKIP_SOGO}" | grep -E '^([yY][eE][sS]|[yY])+$' >/dev/null; then
echo "return 410;"
else
echo "proxy_pass http://${IPV4_NETWORK}.248:20000/SOGo/Microsoft-Server-ActiveSync;"
fi
+4 -3
View File
@@ -162,14 +162,15 @@ 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
parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,qmqpd_authorized_clients parent_domain_matches_subdomains = debug_peer_list,fast_flush_domains,mynetworks,qmqpd_authorized_clients
# This Option is added to correctly set the X-Original-To Header when mails are send to lmtp (dovecot)
lmtp_destination_recipient_limit=1
# DO NOT EDIT ANYTHING BELOW # # DO NOT EDIT ANYTHING BELOW #
# Overrides # # Overrides #
+1 -1
View File
@@ -105,7 +105,7 @@ retry unix - - n - - error
discard unix - - n - - discard discard unix - - n - - discard
local unix - n n - - local local unix - n n - - local
virtual unix - n n - - virtual virtual unix - n n - - virtual
lmtp unix - - n - - lmtp lmtp unix - - n - - lmtp flags=O
anvil unix - - n - 1 anvil anvil unix - - n - 1 anvil
scache unix - - n - 1 scache scache unix - - n - 1 scache
maildrop unix - n n - - pipe flags=DRhu maildrop unix - n n - - pipe flags=DRhu
+68 -38
View File
@@ -1,6 +1,6 @@
# Whitelist generated by Postwhite v3.4 on Thu Aug 1 00:16:45 UTC 2024 # 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/
# 1954 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
@@ -35,6 +35,7 @@
17.57.156.0/24 permit 17.57.156.0/24 permit
17.58.0.0/16 permit 17.58.0.0/16 permit
17.142.0.0/15 permit 17.142.0.0/15 permit
17.143.234.140/30 permit
18.156.89.250 permit 18.156.89.250 permit
18.157.243.190 permit 18.157.243.190 permit
18.194.95.56 permit 18.194.95.56 permit
@@ -93,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
@@ -105,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
@@ -113,11 +116,14 @@
40.92.0.0/16 permit 40.92.0.0/16 permit
40.107.0.0/16 permit 40.107.0.0/16 permit
40.112.65.63 permit 40.112.65.63 permit
43.228.184.0/22 permit 40.233.64.216 permit
40.233.83.78 permit
40.233.88.28 permit
44.206.138.57 permit 44.206.138.57 permit
44.217.45.156 permit 44.217.45.156 permit
44.236.56.93 permit 44.236.56.93 permit
44.238.220.251 permit 44.238.220.251 permit
45.14.148.0/22 permit
46.19.170.16 permit 46.19.170.16 permit
46.226.48.0/21 permit 46.226.48.0/21 permit
46.228.36.37 permit 46.228.36.37 permit
@@ -179,7 +185,9 @@
50.18.126.162 permit 50.18.126.162 permit
50.31.32.0/19 permit 50.31.32.0/19 permit
50.31.36.205 permit 50.31.36.205 permit
50.56.130.220/30 permit 50.56.130.220 permit
50.56.130.221 permit
50.56.130.222 permit
52.1.14.157 permit 52.1.14.157 permit
52.5.230.59 permit 52.5.230.59 permit
52.27.5.72 permit 52.27.5.72 permit
@@ -200,17 +208,18 @@
52.96.91.34 permit 52.96.91.34 permit
52.96.111.82 permit 52.96.111.82 permit
52.96.172.98 permit 52.96.172.98 permit
52.96.214.50 permit
52.96.222.194 permit 52.96.222.194 permit
52.96.222.226 permit 52.96.222.226 permit
52.96.223.2 permit 52.96.223.2 permit
52.96.228.130 permit 52.96.228.130 permit
52.96.229.242 permit 52.96.229.242 permit
52.100.0.0/14 permit 52.100.0.0/15 permit
52.102.0.0/16 permit
52.103.0.0/17 permit 52.103.0.0/17 permit
52.119.213.144/28 permit 52.119.213.144/28 permit
52.185.106.240/28 permit 52.185.106.240/28 permit
52.200.59.0/24 permit 52.200.59.0/24 permit
52.205.61.79 permit
52.207.191.216 permit 52.207.191.216 permit
52.222.62.51 permit 52.222.62.51 permit
52.222.73.83 permit 52.222.73.83 permit
@@ -222,7 +231,6 @@
52.236.28.240/28 permit 52.236.28.240/28 permit
54.90.148.255 permit 54.90.148.255 permit
54.165.19.38 permit 54.165.19.38 permit
54.172.97.247 permit
54.174.52.0/24 permit 54.174.52.0/24 permit
54.174.57.0/24 permit 54.174.57.0/24 permit
54.174.59.0/24 permit 54.174.59.0/24 permit
@@ -239,16 +247,12 @@
54.244.54.130 permit 54.244.54.130 permit
54.244.242.0/24 permit 54.244.242.0/24 permit
54.255.61.23 permit 54.255.61.23 permit
57.103.64.0/18 permit
62.13.128.0/24 permit 62.13.128.0/24 permit
62.13.128.196 permit
62.13.129.128/25 permit 62.13.129.128/25 permit
62.13.136.0/22 permit 62.13.136.0/21 permit
62.13.140.0/22 permit 62.13.144.0/21 permit
62.13.144.0/22 permit 62.13.152.0/21 permit
62.13.148.0/23 permit
62.13.150.0/23 permit
62.13.152.0/23 permit
62.13.159.196 permit
62.17.146.128/26 permit 62.17.146.128/26 permit
62.179.121.0/24 permit 62.179.121.0/24 permit
62.201.172.0/27 permit 62.201.172.0/27 permit
@@ -270,7 +274,6 @@
64.127.115.252 permit 64.127.115.252 permit
64.132.88.0/23 permit 64.132.88.0/23 permit
64.132.92.0/24 permit 64.132.92.0/24 permit
64.147.123.128/27 permit
64.207.219.7 permit 64.207.219.7 permit
64.207.219.8 permit 64.207.219.8 permit
64.207.219.9 permit 64.207.219.9 permit
@@ -443,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
@@ -503,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
@@ -618,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
@@ -1112,12 +1120,11 @@
98.139.245.212/31 permit 98.139.245.212/31 permit
99.78.197.208/28 permit 99.78.197.208/28 permit
99.83.190.102 permit 99.83.190.102 permit
103.2.140.0/22 permit
103.9.96.0/22 permit 103.9.96.0/22 permit
103.28.42.0/24 permit 103.28.42.0/24 permit
103.47.204.0/22 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
@@ -1311,7 +1318,9 @@
129.41.77.70 permit 129.41.77.70 permit
129.41.169.249 permit 129.41.169.249 permit
129.80.5.164 permit 129.80.5.164 permit
129.80.64.36 permit
129.80.67.121 permit 129.80.67.121 permit
129.80.145.156 permit
129.145.74.12 permit 129.145.74.12 permit
129.146.88.28 permit 129.146.88.28 permit
129.146.147.105 permit 129.146.147.105 permit
@@ -1322,11 +1331,16 @@
129.153.168.146 permit 129.153.168.146 permit
129.153.190.200 permit 129.153.190.200 permit
129.153.194.228 permit 129.153.194.228 permit
129.154.255.129 permit
129.158.56.255 permit
129.159.22.159 permit
129.159.87.137 permit 129.159.87.137 permit
129.213.195.191 permit 129.213.195.191 permit
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
@@ -1354,6 +1368,7 @@
139.138.57.55 permit 139.138.57.55 permit
139.138.58.119 permit 139.138.58.119 permit
139.180.17.0/24 permit 139.180.17.0/24 permit
140.238.148.191 permit
141.148.159.229 permit 141.148.159.229 permit
141.193.32.0/23 permit 141.193.32.0/23 permit
141.193.184.32/27 permit 141.193.184.32/27 permit
@@ -1362,6 +1377,7 @@
141.193.185.32/27 permit 141.193.185.32/27 permit
141.193.185.64/26 permit 141.193.185.64/26 permit
141.193.185.128/25 permit 141.193.185.128/25 permit
143.47.120.152 permit
143.55.224.0/21 permit 143.55.224.0/21 permit
143.55.232.0/22 permit 143.55.232.0/22 permit
143.55.236.0/22 permit 143.55.236.0/22 permit
@@ -1375,13 +1391,17 @@
144.178.38.0/24 permit 144.178.38.0/24 permit
145.253.228.160/29 permit 145.253.228.160/29 permit
145.253.239.128/29 permit 145.253.239.128/29 permit
146.20.14.104/30 permit 146.20.14.104 permit
146.20.14.105 permit
146.20.14.106 permit
146.20.14.107 permit
146.20.112.0/26 permit 146.20.112.0/26 permit
146.20.113.0/24 permit 146.20.113.0/24 permit
146.20.191.0/24 permit 146.20.191.0/24 permit
146.20.215.0/24 permit 146.20.215.0/24 permit
146.20.215.182 permit 146.20.215.182 permit
146.88.28.0/24 permit 146.88.28.0/24 permit
147.154.32.0/25 permit
147.243.1.47 permit 147.243.1.47 permit
147.243.1.48 permit 147.243.1.48 permit
147.243.1.153 permit 147.243.1.153 permit
@@ -1394,10 +1414,14 @@
149.72.248.236 permit 149.72.248.236 permit
149.97.173.180 permit 149.97.173.180 permit
150.230.98.160 permit 150.230.98.160 permit
151.145.38.14 permit
152.67.105.195 permit 152.67.105.195 permit
152.69.200.236 permit 152.69.200.236 permit
152.70.155.126 permit 152.70.155.126 permit
155.248.208.51 permit 155.248.208.51 permit
155.248.220.138 permit
155.248.234.149 permit
155.248.237.141 permit
157.55.0.192/26 permit 157.55.0.192/26 permit
157.55.1.128/26 permit 157.55.1.128/26 permit
157.55.2.0/25 permit 157.55.2.0/25 permit
@@ -1418,7 +1442,6 @@
157.151.208.65 permit 157.151.208.65 permit
157.255.1.64/29 permit 157.255.1.64/29 permit
158.101.211.207 permit 158.101.211.207 permit
158.120.80.0/21 permit
158.247.16.0/20 permit 158.247.16.0/20 permit
159.92.154.0/24 permit 159.92.154.0/24 permit
159.92.155.0/24 permit 159.92.155.0/24 permit
@@ -1446,12 +1469,18 @@
161.38.204.0/22 permit 161.38.204.0/22 permit
161.71.32.0/19 permit 161.71.32.0/19 permit
161.71.64.0/20 permit 161.71.64.0/20 permit
162.88.4.0/23 permit
162.88.8.0/24 permit
162.88.24.0/24 permit
162.88.25.0/24 permit
162.88.36.0/24 permit
162.247.216.0/22 permit 162.247.216.0/22 permit
163.47.180.0/22 permit 163.47.180.0/22 permit
163.114.130.16 permit 163.114.130.16 permit
163.114.132.120 permit 163.114.132.120 permit
163.114.134.16 permit 163.114.134.16 permit
163.114.135.16 permit 163.114.135.16 permit
164.152.23.32 permit
164.177.132.168/30 permit 164.177.132.168/30 permit
166.78.68.0/22 permit 166.78.68.0/22 permit
166.78.68.221 permit 166.78.68.221 permit
@@ -1476,13 +1505,15 @@
167.220.67.232/29 permit 167.220.67.232/29 permit
168.138.5.36 permit 168.138.5.36 permit
168.138.73.51 permit 168.138.73.51 permit
168.138.77.31 permit
168.245.0.0/17 permit 168.245.0.0/17 permit
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
170.10.68.0/22 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.64/29 permit
170.10.133.0/24 permit 170.10.133.0/24 permit
172.217.0.0/19 permit 172.217.0.0/19 permit
172.217.32.0/20 permit 172.217.32.0/20 permit
@@ -1491,6 +1522,7 @@
172.217.192.0/19 permit 172.217.192.0/19 permit
172.253.56.0/21 permit 172.253.56.0/21 permit
172.253.112.0/20 permit 172.253.112.0/20 permit
173.0.84.0/29 permit
173.0.84.224/27 permit 173.0.84.224/27 permit
173.0.94.244/30 permit 173.0.94.244/30 permit
173.194.0.0/16 permit 173.194.0.0/16 permit
@@ -1509,7 +1541,6 @@
174.36.114.148/30 permit 174.36.114.148/30 permit
174.36.114.152/29 permit 174.36.114.152/29 permit
174.37.67.28/30 permit 174.37.67.28/30 permit
174.129.203.189 permit
175.41.215.51 permit 175.41.215.51 permit
176.32.105.0/24 permit 176.32.105.0/24 permit
176.32.127.0/24 permit 176.32.127.0/24 permit
@@ -1519,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
@@ -1582,6 +1614,10 @@
188.172.128.0/20 permit 188.172.128.0/20 permit
192.0.64.0/18 permit 192.0.64.0/18 permit
192.18.139.154 permit 192.18.139.154 permit
192.18.145.36 permit
192.18.152.58 permit
192.28.128.0/18 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
192.162.87.0/24 permit 192.162.87.0/24 permit
@@ -1607,14 +1643,6 @@
195.234.109.226 permit 195.234.109.226 permit
195.245.230.0/23 permit 195.245.230.0/23 permit
198.2.128.0/18 permit 198.2.128.0/18 permit
198.2.128.0/24 permit
198.2.132.0/22 permit
198.2.136.0/23 permit
198.2.145.0/24 permit
198.2.177.0/24 permit
198.2.178.0/23 permit
198.2.180.0/24 permit
198.2.186.0/23 permit
198.21.0.0/21 permit 198.21.0.0/21 permit
198.37.144.0/20 permit 198.37.144.0/20 permit
198.37.152.186 permit 198.37.152.186 permit
@@ -1629,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
@@ -1641,11 +1670,11 @@
199.122.123.0/24 permit 199.122.123.0/24 permit
199.127.232.0/22 permit 199.127.232.0/22 permit
199.255.192.0/22 permit 199.255.192.0/22 permit
202.12.124.128/27 permit
202.129.242.0/23 permit 202.129.242.0/23 permit
202.165.102.47 permit 202.165.102.47 permit
202.177.148.100 permit 202.177.148.100 permit
202.177.148.110 permit 202.177.148.110 permit
203.31.36.0/22 permit
203.32.4.25 permit 203.32.4.25 permit
203.55.21.0/24 permit 203.55.21.0/24 permit
203.81.17.0/24 permit 203.81.17.0/24 permit
@@ -1691,15 +1720,13 @@
204.92.114.187 permit 204.92.114.187 permit
204.92.114.203 permit 204.92.114.203 permit
204.92.114.204/31 permit 204.92.114.204/31 permit
204.220.160.0/20 permit 204.220.160.0/21 permit
204.220.168.0/21 permit
204.220.176.0/20 permit
204.232.168.0/24 permit 204.232.168.0/24 permit
205.139.110.0/24 permit 205.139.110.0/24 permit
205.201.128.0/20 permit 205.201.128.0/20 permit
205.201.131.128/25 permit
205.201.134.128/25 permit
205.201.136.0/23 permit
205.201.137.229 permit 205.201.137.229 permit
205.201.139.0/24 permit
205.207.104.0/22 permit 205.207.104.0/22 permit
205.220.167.17 permit 205.220.167.17 permit
205.220.167.98 permit 205.220.167.98 permit
@@ -1727,7 +1754,6 @@
207.46.132.128/27 permit 207.46.132.128/27 permit
207.46.198.0/25 permit 207.46.198.0/25 permit
207.46.200.0/27 permit 207.46.200.0/27 permit
207.58.147.64/28 permit
207.67.38.0/24 permit 207.67.38.0/24 permit
207.67.98.192/27 permit 207.67.98.192/27 permit
207.68.176.0/26 permit 207.68.176.0/26 permit
@@ -1774,6 +1800,8 @@
208.74.204.5 permit 208.74.204.5 permit
208.74.204.9 permit 208.74.204.9 permit
208.75.120.0/22 permit 208.75.120.0/22 permit
208.76.62.0/24 permit
208.76.63.0/24 permit
208.82.237.96/29 permit 208.82.237.96/29 permit
208.82.237.104/31 permit 208.82.237.104/31 permit
208.82.238.96/29 permit 208.82.238.96/29 permit
@@ -1873,7 +1901,6 @@
213.199.177.0/26 permit 213.199.177.0/26 permit
216.17.150.242 permit 216.17.150.242 permit
216.17.150.251 permit 216.17.150.251 permit
216.22.15.224/27 permit
216.24.224.0/20 permit 216.24.224.0/20 permit
216.39.60.154/31 permit 216.39.60.154/31 permit
216.39.60.156/30 permit 216.39.60.156/30 permit
@@ -1916,7 +1943,10 @@
216.136.162.65 permit 216.136.162.65 permit
216.136.162.120/29 permit 216.136.162.120/29 permit
216.136.168.80/28 permit 216.136.168.80/28 permit
216.139.64.0/19 permit
216.145.221.0/24 permit 216.145.221.0/24 permit
216.146.32.0/24 permit
216.146.33.0/24 permit
216.198.0.0/18 permit 216.198.0.0/18 permit
216.203.30.55 permit 216.203.30.55 permit
216.203.33.178/31 permit 216.203.33.178/31 permit
+12
View File
@@ -0,0 +1,12 @@
#!/bin/sh
cat <<EOF > /redis.conf
requirepass $REDISPASS
user quota_notify on nopass ~QW_* -@all +get +hget +ping
EOF
if [ -n "$REDISMASTERPASS" ]; then
echo "masterauth $REDISMASTERPASS" >> /redis.conf
fi
exec redis-server /redis.conf
+1
View File
@@ -25,6 +25,7 @@ catch (PDOException $e) {
// Init Redis // Init Redis
$redis = new Redis(); $redis = new Redis();
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
$redis->auth(getenv("REDISPASS"));
function parse_email($email) { function parse_email($email) {
if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false; if(!filter_var($email, FILTER_VALIDATE_EMAIL)) return false;
@@ -4,6 +4,7 @@ ini_set('error_reporting', 0);
$redis = new Redis(); $redis = new Redis();
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
$redis->auth(getenv("REDISPASS"));
function in_net($addr, $net) { function in_net($addr, $net) {
$net = explode('/', $net); $net = explode('/', $net);
+43 -29
View File
@@ -1,27 +1,45 @@
###############################################################################
# This list is added/merged with defined defaults in LUA module:
# https://github.com/rspamd/rspamd/blob/master/src/plugins/lua/mime_types.lua
###############################################################################
# Extensions that are treated as 'bad' # Extensions that are treated as 'bad'
# Number is score multiply factor # Number is score multiply factor
bad_extensions = { bad_extensions = {
scr = 20, apk = 4,
lnk = 20, appx = 4,
exe = 20, appxbundle = 4,
msi = 1, bat = 8,
msp = 1,
msu = 1,
jar = 2,
com = 20,
bat = 4,
cmd = 4,
ps1 = 4,
ace = 4,
arj = 4,
cab = 20, cab = 20,
cmd = 8,
com = 20,
diagcfg = 4,
diagpack = 4,
dmg = 8,
ex = 20,
ex_ = 20,
exe = 20,
img = 4,
jar = 8,
jnlp = 8,
js = 8,
jse = 8,
lnk = 20,
mjs = 8,
msi = 4,
msix = 4,
msixbundle = 4,
ps1 = 8,
scr = 20,
sct = 20,
vb = 20,
vbe = 20,
vbs = 20, vbs = 20,
hta = 4, vhd = 4,
shs = 4, py = 4,
wsc = 4, reg = 8,
wsf = 4, scf = 8,
iso = 8, vhdx = 4,
img = 8
}; };
# Extensions that are particularly penalized for archives # Extensions that are particularly penalized for archives
@@ -30,18 +48,14 @@ bad_archive_extensions = {
docx = 0.5, docx = 0.5,
xlsx = 0.5, xlsx = 0.5,
pdf = 1.0, pdf = 1.0,
jar = 3, jar = 12,
js = 0.5, jnlp = 12,
vbs = 20, bat = 12,
exe = 20 cmd = 12,
}; };
# Used to detect another archive in archive # Used to detect another archive in archive
archive_extensions = { archive_extensions = {
zip = 1, tar = 1,
arj = 1, gz = 1,
rar = 1,
ace = 1,
7z = 1,
cab = 1
}; };
+2
View File
@@ -2,6 +2,8 @@ dns {
enable_dnssec = true; enable_dnssec = true;
} }
map_watch_interval = 30s; map_watch_interval = 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.
+1
View File
@@ -24,6 +24,7 @@ catch (PDOException $e) {
// Init Redis // Init Redis
$redis = new Redis(); $redis = new Redis();
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
$redis->auth(getenv("REDISPASS"));
// Functions // Functions
function parse_email($email) { function parse_email($email) {
@@ -14,6 +14,7 @@ try {
else { else {
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
} }
$redis->auth(getenv("REDISPASS"));
} }
catch (Exception $e) { catch (Exception $e) {
exit; exit;
@@ -24,6 +24,7 @@ catch (PDOException $e) {
// Init Redis // Init Redis
$redis = new Redis(); $redis = new Redis();
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
$redis->auth(getenv("REDISPASS"));
// Functions // Functions
function parse_email($email) { function parse_email($email) {
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
@@ -16,6 +16,9 @@
SOGoFoldersSendEMailNotifications = YES; SOGoFoldersSendEMailNotifications = YES;
SOGoForwardEnabled = YES; SOGoForwardEnabled = YES;
// Fixes "MODIFICATION_FAILED" error (HTTP 412) in Clients when accepting invitations from external services
SOGoDisableOrganizerEventCheck = YES;
// Option to set Users as admin to globally manage calendar permissions etc. Disabled by default // Option to set Users as admin to globally manage calendar permissions etc. Disabled by default
// SOGoSuperUsernames = ("moo@example.com"); // SOGoSuperUsernames = ("moo@example.com");
+1
View File
@@ -7,6 +7,7 @@ try {
else { else {
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
} }
$redis->auth(getenv("REDISPASS"));
} }
catch (Exception $e) { catch (Exception $e) {
exit; exit;
+1 -1
View File
@@ -104,7 +104,7 @@ $template_data = [
'all_domains' => $all_domains, 'all_domains' => $all_domains,
'mailboxes' => $mailboxes, 'mailboxes' => $mailboxes,
'f2b_data' => $f2b_data, 'f2b_data' => $f2b_data,
'f2b_banlist_url' => getBaseUrl() . "/api/v1/get/fail2ban/banlist/" . $f2b_data['banlist_id'], 'f2b_banlist_url' => getBaseUrl() . "/f2b-banlist?id=" . $f2b_data['banlist_id'],
'q_data' => quarantine('settings'), 'q_data' => quarantine('settings'),
'qn_data' => quota_notification('get'), 'qn_data' => quota_notification('get'),
'pw_reset_data' => reset_password('get_notification'), 'pw_reset_data' => reset_password('get_notification'),
+3 -30
View File
@@ -1531,6 +1531,9 @@ paths:
port1: port1:
description: the smtp port of the target mail server description: the smtp port of the target mail server
type: string type: string
user1:
description: the username of the mailbox
type: string
password: password:
description: the password of the mailbox description: the password of the mailbox
type: string type: string
@@ -5415,12 +5418,6 @@ paths:
started_at: "2019-12-22T20:59:58.382274592Z" started_at: "2019-12-22T20:59:58.382274592Z"
state: running state: running
type: info type: info
solr-mailcow:
container: solr-mailcow
image: "mailcow/solr:1.7"
started_at: "2019-12-22T20:59:59.635413798Z"
state: running
type: info
unbound-mailcow: unbound-mailcow:
container: unbound-mailcow container: unbound-mailcow
image: "mailcow/unbound:1.10" image: "mailcow/unbound:1.10"
@@ -5442,30 +5439,6 @@ paths:
hey where started and a few other details. hey where started and a few other details.
operationId: Get container status operationId: Get container status
summary: Get container status summary: Get container status
/api/v1/get/status/solr:
get:
responses:
"401":
$ref: "#/components/responses/Unauthorized"
"200":
content:
application/json:
examples:
response:
value:
solr_documents: null
solr_enabled: false
solr_size: null
type: info
description: OK
headers: {}
tags:
- Status
description: >-
Using this endpoint you can get the status of all containers and when
hey where started and a few other details.
operationId: Get solr status
summary: Get solr status
/api/v1/get/status/vmail: /api/v1/get/status/vmail:
get: get:
responses: responses:
+1
View File
@@ -16,6 +16,7 @@ try {
else { else {
$redis->connect('redis-mailcow', 6379); $redis->connect('redis-mailcow', 6379);
} }
$redis->auth(getenv("REDISPASS"));
} }
catch (Exception $e) { catch (Exception $e) {
exit; exit;
+12 -12
View File
@@ -8,7 +8,6 @@ if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != "adm
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php'; require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/header.inc.php';
$_SESSION['return_to'] = $_SERVER['REQUEST_URI']; $_SESSION['return_to'] = $_SERVER['REQUEST_URI'];
$solr_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_SOLR"])) ? false : solr_status();
$clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true; $clamd_status = (preg_match("/^([yY][eE][sS]|[yY])+$/", $_ENV["SKIP_CLAMD"])) ? false : true;
@@ -23,11 +22,14 @@ $exec_fields = array('cmd' => 'system', 'task' => 'df', 'dir' => '/var/vmail');
$vmail_df = explode(',', (string)json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true)); $vmail_df = explode(',', (string)json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true));
// containers // containers
$containers = (array) docker('info'); $containers_info = (array) docker('info');
if ($clamd_status === false) unset($containers['clamd-mailcow']); if ($clamd_status === false) unset($containers_info['clamd-mailcow']);
if ($solr_status === false) unset($containers['solr-mailcow']); ksort($containers_info);
ksort($containers); $containers = array();
foreach ($containers as $container => $container_info) { foreach ($containers_info as $container => $container_info) {
if (!isset($container_info['State']) || !is_array($container_info['State']) || !isset($container_info['State']['StartedAt'])){
continue;
}
date_default_timezone_set('UTC'); date_default_timezone_set('UTC');
$StartedAt = date_parse($container_info['State']['StartedAt']); $StartedAt = date_parse($container_info['State']['StartedAt']);
if ($StartedAt['hour'] !== false) { if ($StartedAt['hour'] !== false) {
@@ -42,15 +44,15 @@ foreach ($containers as $container => $container_info) {
try { try {
$user_tz = new DateTimeZone(getenv('TZ')); $user_tz = new DateTimeZone(getenv('TZ'));
$date->setTimezone($user_tz); $date->setTimezone($user_tz);
$started = $date->format('r'); $container_info['State']['StartedAtHR'] = $date->format('r');
} catch(Exception $e) { } catch(Exception $e) {
$started = '?'; $container_info['State']['StartedAtHR'] = '?';
} }
} }
else { else {
$started = '?'; $container_info['State']['StartedAtHR'] = '?';
} }
$containers[$container]['State']['StartedAtHR'] = $started; $containers[$container] = $container_info;
} }
// get mailcow data // get mailcow data
@@ -65,8 +67,6 @@ $template_data = [
'timezone' => $timezone, 'timezone' => $timezone,
'gal' => @$_SESSION['gal'], 'gal' => @$_SESSION['gal'],
'license_guid' => license('guid'), 'license_guid' => license('guid'),
'solr_status' => $solr_status,
'solr_uptime' => round($solr_status['status']['dovecot-fts']['uptime'] / 1000 / 60 / 60),
'clamd_status' => $clamd_status, 'clamd_status' => $clamd_status,
'containers' => $containers, 'containers' => $containers,
'ip_check' => customize('get', 'ip_check'), 'ip_check' => customize('get', 'ip_check'),
+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];
} }
+11
View File
@@ -0,0 +1,11 @@
<?php
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
if (isset($_GET['id'])) {
header('Content-Type: text/plain');
echo fail2ban('banlist', 'get', $_GET['id']);
} else {
header('HTTP/1.1 404 Not Found');
exit;
}
+3 -3
View File
@@ -4,14 +4,14 @@ header('Content-Type: application/json');
if (!isset($_SESSION['mailcow_cc_role'])) { if (!isset($_SESSION['mailcow_cc_role'])) {
exit(); exit();
} }
if (isset($_GET['script'])) { if (isset($_REQUEST['script'])) {
$sieve = new Sieve\SieveParser(); $sieve = new Sieve\SieveParser();
try { try {
if (empty($_GET['script'])) { if (empty($_REQUEST['script'])) {
echo json_encode(array('type' => 'danger', 'msg' => $lang['danger']['script_empty'])); echo json_encode(array('type' => 'danger', 'msg' => $lang['danger']['script_empty']));
exit(); exit();
} }
$sieve->parse($_GET['script']); $sieve->parse($_REQUEST['script']);
} }
catch (Exception $e) { catch (Exception $e) {
echo json_encode(array('type' => 'danger', 'msg' => $e->getMessage())); echo json_encode(array('type' => 'danger', 'msg' => $e->getMessage()));
@@ -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
)); ));
+2 -2
View File
@@ -26,7 +26,7 @@ function dkim($_action, $_data = null, $privkey = false) {
); );
continue; continue;
} }
if (!ctype_alnum(str_replace(['-', '_'], '', $dkim_selector))) { if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data), 'log' => array(__FUNCTION__, $_action, $_data),
@@ -188,7 +188,7 @@ function dkim($_action, $_data = null, $privkey = false) {
return false; return false;
} }
} }
if (!ctype_alnum($dkim_selector)) { if (!ctype_alnum(str_replace(['-', '_', '.'], '', $dkim_selector))) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data), 'log' => array(__FUNCTION__, $_action, $_data),
+28 -54
View File
@@ -953,11 +953,6 @@ function check_login($user, $pass, $app_passwd_data = false) {
$_SESSION['pending_mailcow_cc_role'] = "user"; $_SESSION['pending_mailcow_cc_role'] = "user";
$_SESSION['pending_tfa_methods'] = $authenticators['additional']; $_SESSION['pending_tfa_methods'] = $authenticators['additional'];
unset($_SESSION['ldelay']); unset($_SESSION['ldelay']);
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
return "pending"; return "pending";
} else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) { } else if (!isset($authenticators['additional']) || !is_array($authenticators['additional']) || count($authenticators['additional']) == 0) {
// no authenticators found, login successfull // no authenticators found, login successfull
@@ -966,6 +961,11 @@ function check_login($user, $pass, $app_passwd_data = false) {
$stmt->execute(array(':user' => $user)); $stmt->execute(array(':user' => $user));
unset($_SESSION['ldelay']); unset($_SESSION['ldelay']);
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $user, '*'),
'msg' => array('logged_in_as', $user)
);
return "user"; return "user";
} }
} elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) { } elseif ($app_passwd_data['eas'] === true || $app_passwd_data['dav'] === true) {
@@ -1174,7 +1174,7 @@ function user_get_alias_details($username) {
AND `goto` != :username_goto2 AND `goto` != :username_goto2
AND `address` != :username_address"); AND `address` != :username_address");
$stmt->execute(array( $stmt->execute(array(
':username_goto' => '(^|,)'.$username.'($|,)', ':username_goto' => '(^|,)'.preg_quote($username, '/').'($|,)',
':username_goto2' => $username, ':username_goto2' => $username,
':username_address' => $username ':username_address' => $username
)); ));
@@ -1222,7 +1222,7 @@ function user_get_alias_details($username) {
$data['aliases_send_as_all'] = $row['send_as']; $data['aliases_send_as_all'] = $row['send_as'];
} }
$stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';"); $stmt = $pdo->prepare("SELECT IFNULL(GROUP_CONCAT(`address` SEPARATOR ', '), '') as `address` FROM `alias` WHERE `goto` REGEXP :username AND `address` LIKE '@%';");
$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); $stmt->execute(array(':username' => '(^|,)'.preg_quote($username, '/').'($|,)'));
$run = $stmt->fetchAll(PDO::FETCH_ASSOC); $run = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($run)) { while ($row = array_shift($run)) {
$data['is_catch_all'] = $row['address']; $data['is_catch_all'] = $row['address'];
@@ -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;
@@ -2515,6 +2531,8 @@ function reset_password($action, $data = null) {
':username' => $username ':username' => $username
)); ));
update_sogo_static_view($username);
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'success', 'type' => 'success',
'log' => array(__FUNCTION__, $action, $_data_log), 'log' => array(__FUNCTION__, $action, $_data_log),
@@ -2906,50 +2924,6 @@ function getGUID() {
.substr($charid,16, 4).$hyphen .substr($charid,16, 4).$hyphen
.substr($charid,20,12); .substr($charid,20,12);
} }
function solr_status() {
$curl = curl_init();
$endpoint = 'http://solr:8983/solr/admin/cores';
$params = array(
'action' => 'STATUS',
'core' => 'dovecot-fts',
'indexInfo' => 'true'
);
$url = $endpoint . '?' . http_build_query($params);
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$response_core = curl_exec($curl);
if ($response_core === false) {
$err = curl_error($curl);
curl_close($curl);
return false;
}
else {
curl_close($curl);
$curl = curl_init();
$status_core = json_decode($response_core, true);
$url = 'http://solr:8983/solr/admin/info/system';
curl_setopt($curl, CURLOPT_URL, $url);
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 0);
curl_setopt($curl, CURLOPT_TIMEOUT, 10);
$response_sysinfo = curl_exec($curl);
if ($response_sysinfo === false) {
$err = curl_error($curl);
curl_close($curl);
return false;
}
else {
curl_close($curl);
$status_sysinfo = json_decode($response_sysinfo, true);
$status = array_merge($status_core, $status_sysinfo);
return (!empty($status['status']['dovecot-fts']) && !empty($status['jvm']['memory'])) ? $status : false;
}
return (!empty($status['status']['dovecot-fts'])) ? $status['status']['dovecot-fts'] : false;
}
return false;
}
function cleanupJS($ignore = '', $folder = '/tmp/*.js') { function cleanupJS($ignore = '', $folder = '/tmp/*.js') {
$now = time(); $now = time();
+210 -23
View File
@@ -48,6 +48,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$_data["validity"] = 8760; $_data["validity"] = 8760;
} }
$domain = $_data['domain']; $domain = $_data['domain'];
$description = $_data['description'];
$valid_domains[] = mailbox('get', 'mailbox_details', $username)['domain']; $valid_domains[] = mailbox('get', 'mailbox_details', $username)['domain'];
$valid_alias_domains = user_get_alias_details($username)['alias_domains']; $valid_alias_domains = user_get_alias_details($username)['alias_domains'];
if (!empty($valid_alias_domains)) { if (!empty($valid_alias_domains)) {
@@ -62,10 +63,11 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
return false; return false;
} }
$validity = strtotime("+" . $_data["validity"] . " hour"); $validity = strtotime("+" . $_data["validity"] . " hour");
$stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `goto`, `validity`) VALUES $stmt = $pdo->prepare("INSERT INTO `spamalias` (`address`, `description`, `goto`, `validity`) VALUES
(:address, :goto, :validity)"); (:address, :description, :goto, :validity)");
$stmt->execute(array( $stmt->execute(array(
':address' => readable_random_string(rand(rand(3, 9), rand(3, 9))) . '.' . readable_random_string(rand(rand(3, 9), rand(3, 9))) . '@' . $domain, ':address' => readable_random_string(rand(rand(3, 9), rand(3, 9))) . '.' . readable_random_string(rand(rand(3, 9), rand(3, 9))) . '@' . $domain,
':description' => $description,
':goto' => $username, ':goto' => $username,
':validity' => $validity ':validity' => $validity
)); ));
@@ -3203,6 +3205,202 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
} }
return true; return true;
break; break;
case 'mailbox_rename':
$domain = $_data['domain'];
$old_local_part = $_data['old_local_part'];
$old_username = $old_local_part . "@" . $domain;
$new_local_part = $_data['new_local_part'];
$new_username = $new_local_part . "@" . $domain;
$create_alias = intval($_data['create_alias']);
if (!filter_var($old_username, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('username_invalid', $old_username)
);
return false;
}
if (!filter_var($new_username, FILTER_VALIDATE_EMAIL)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('username_invalid', $new_username)
);
return false;
}
$is_now = mailbox('get', 'mailbox_details', $old_username);
if (empty($is_now)) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
return false;
}
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $is_now['domain'])) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
return false;
}
// get imap acls
try {
$exec_fields = array(
'cmd' => 'doveadm',
'task' => 'get_acl',
'id' => $old_username
);
$imap_acls = json_decode(docker('post', 'dovecot-mailcow', 'exec', $exec_fields), true);
// delete imap acls
foreach ($imap_acls as $imap_acl) {
$exec_fields = array(
'cmd' => 'doveadm',
'task' => 'delete_acl',
'user' => $imap_acl['user'],
'mailbox' => $imap_acl['mailbox'],
'id' => $imap_acl['id']
);
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
}
} catch (Exception $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => $e->getMessage()
);
return false;
}
// rename username in sql
try {
$pdo->beginTransaction();
$pdo->exec('SET FOREIGN_KEY_CHECKS = 0');
// Update username in mailbox table
$pdo->prepare('UPDATE mailbox SET username = :new_username, local_part = :new_local_part WHERE username = :old_username')
->execute([
':new_username' => $new_username,
':new_local_part' => $new_local_part,
':old_username' => $old_username
]);
$pdo->prepare("UPDATE alias SET address = :new_username, goto = :new_username2 WHERE address = :old_username")
->execute([
':new_username' => $new_username,
':new_username2' => $new_username,
':old_username' => $old_username
]);
// Update the username in all related tables
$tables = [
'tags_mailbox' => ['username'],
'sieve_filters' => ['username'],
'app_passwd' => ['mailbox'],
'user_acl' => ['username'],
'da_acl' => ['username'],
'quota2' => ['username'],
'quota2replica' => ['username'],
'pushover' => ['username'],
'alias' => ['goto'],
"imapsync" => ['user2'],
'bcc_maps' => ['local_dest', 'bcc_dest'],
'recipient_maps' => ['old_dest', 'new_dest'],
'sender_acl' => ['logged_in_as', 'send_as']
];
foreach ($tables as $table => $columns) {
foreach ($columns as $column) {
$stmt = $pdo->prepare("UPDATE $table SET $column = :new_username WHERE $column = :old_username")
->execute([
':new_username' => $new_username,
':old_username' => $old_username
]);
}
}
// Update c_uid, c_name and mail in _sogo_static_view table
$pdo->prepare("UPDATE _sogo_static_view SET c_uid = :new_username, c_name = :new_username2, mail = :new_username3 WHERE c_uid = :old_username")
->execute([
':new_username' => $new_username,
':new_username2' => $new_username,
':new_username3' => $new_username,
':old_username' => $old_username
]);
// Re-enable foreign key checks
$pdo->exec('SET FOREIGN_KEY_CHECKS = 1');
$pdo->commit();
} catch (PDOException $e) {
// Rollback the transaction if something goes wrong
$pdo->rollBack();
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => $e->getMessage()
);
return false;
}
// move maildir
$exec_fields = array(
'cmd' => 'maildir',
'task' => 'move',
'old_maildir' => $domain . '/' . $old_local_part,
'new_maildir' => $domain . '/' . $new_local_part
);
if (getenv("CLUSTERMODE") == "replication") {
// broadcast to each dovecot container
docker('broadcast', 'dovecot-mailcow', 'exec', $exec_fields);
} else {
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
}
// rename username in sogo
$exec_fields = array(
'cmd' => 'sogo',
'task' => 'rename_user',
'old_username' => $old_username,
'new_username' => $new_username
);
docker('post', 'sogo-mailcow', 'exec', $exec_fields);
// set imap acls
foreach ($imap_acls as $imap_acl) {
$user_id = ($imap_acl['id'] == $old_username) ? $new_username : $imap_acl['id'];
$user = ($imap_acl['user'] == $old_username) ? $new_username : $imap_acl['user'];
$exec_fields = array(
'cmd' => 'doveadm',
'task' => 'set_acl',
'user' => $user,
'mailbox' => $imap_acl['mailbox'],
'id' => $user_id,
'rights' => $imap_acl['rights']
);
docker('post', 'dovecot-mailcow', 'exec', $exec_fields);
}
// create alias
if ($create_alias == 1) {
mailbox("add", "alias", array(
"address" => $old_username,
"goto" => $new_username,
"active" => 1,
"sogo_visible" => 1,
"private_comment" => sprintf($lang['success']['mailbox_renamed'], $old_username, $new_username)
));
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('mailbox_renamed', $old_username, $new_username)
);
break;
case 'mailbox_templates': case 'mailbox_templates':
if ($_SESSION['mailcow_cc_role'] != "admin") { if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
@@ -3572,7 +3770,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$data['external_sender_aliases'] = array(); $data['external_sender_aliases'] = array();
// Fixed addresses // Fixed addresses
$stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'"); $stmt = $pdo->prepare("SELECT `address` FROM `alias` WHERE `goto` REGEXP :goto AND `address` NOT LIKE '@%'");
$stmt->execute(array(':goto' => '(^|,)'.$_data.'($|,)')); $stmt->execute(array(':goto' => '(^|,)'.preg_quote($_data, '/').'($|,)'));
$rows = $stmt->fetchAll(PDO::FETCH_ASSOC); $rows = $stmt->fetchAll(PDO::FETCH_ASSOC);
while ($row = array_shift($rows)) { while ($row = array_shift($rows)) {
$data['fixed_sender_aliases'][] = $row['address']; $data['fixed_sender_aliases'][] = $row['address'];
@@ -4005,6 +4203,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
} }
$stmt = $pdo->prepare("SELECT `address`, $stmt = $pdo->prepare("SELECT `address`,
`goto`, `goto`,
`description`,
`validity`, `validity`,
`created`, `created`,
`modified` `modified`
@@ -4546,6 +4745,9 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
} }
else if ($SaslLogs['service'] == 'pop3') { else if ($SaslLogs['service'] == 'pop3') {
$last_pop3_login = strtotime($SaslLogs['datetime']); $last_pop3_login = strtotime($SaslLogs['datetime']);
}
else if ($SaslLogs['service'] == 'SSO') {
$last_sso_login = strtotime($SaslLogs['datetime']);
} }
} }
if (!isset($last_imap_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) { if (!isset($last_imap_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
@@ -4556,10 +4758,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
} }
if (!isset($last_pop3_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) { if (!isset($last_pop3_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
$last_pop3_login = 0; $last_pop3_login = 0;
}
if (!isset($last_sso_login) || $GLOBALS['SHOW_LAST_LOGIN'] === false) {
$last_sso_login = 0;
} }
$mailboxdata['last_imap_login'] = $last_imap_login; $mailboxdata['last_imap_login'] = $last_imap_login;
$mailboxdata['last_smtp_login'] = $last_smtp_login; $mailboxdata['last_smtp_login'] = $last_smtp_login;
$mailboxdata['last_pop3_login'] = $last_pop3_login; $mailboxdata['last_pop3_login'] = $last_pop3_login;
$mailboxdata['last_sso_login'] = $last_sso_login;
if (!isset($_extra) || $_extra != 'reduced') { if (!isset($_extra) || $_extra != 'reduced') {
$rl = ratelimit('get', 'mailbox', $_data); $rl = ratelimit('get', 'mailbox', $_data);
@@ -5231,25 +5437,6 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
'msg' => 'Could not move maildir to garbage collector: variables local_part and/or domain empty' 'msg' => 'Could not move maildir to garbage collector: variables local_part and/or domain empty'
); );
} }
if (strtolower(getenv('SKIP_SOLR')) == 'n' && strtolower(getenv('FLATCURVE_EXPERIMENTAL')) != 'y') {
$curl = curl_init();
curl_setopt($curl, CURLOPT_URL, 'http://solr:8983/solr/dovecot-fts/update?commit=true');
curl_setopt($curl, CURLOPT_HTTPHEADER,array('Content-Type: text/xml'));
curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
curl_setopt($curl, CURLOPT_POST, 1);
curl_setopt($curl, CURLOPT_POSTFIELDS, '<delete><query>user:' . $username . '</query></delete>');
curl_setopt($curl, CURLOPT_TIMEOUT, 30);
$response = curl_exec($curl);
if ($response === false) {
$err = curl_error($curl);
$_SESSION['return'][] = array(
'type' => 'warning',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'Could not remove Solr index: ' . print_r($err, true)
);
}
curl_close($curl);
}
$stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username"); $stmt = $pdo->prepare("DELETE FROM `alias` WHERE `goto` = :username");
$stmt->execute(array( $stmt->execute(array(
':username' => $username ':username' => $username
@@ -5350,7 +5537,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
)); ));
$stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias` $stmt = $pdo->prepare("SELECT `address`, `goto` FROM `alias`
WHERE `goto` REGEXP :username"); WHERE `goto` REGEXP :username");
$stmt->execute(array(':username' => '(^|,)'.$username.'($|,)')); $stmt->execute(array(':username' => '(^|,)'.preg_quote($username, '/').'($|,)'));
$GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC); $GotoData = $stmt->fetchAll(PDO::FETCH_ASSOC);
foreach ($GotoData as $gotos) { foreach ($GotoData as $gotos) {
$goto_exploded = explode(',', $gotos['goto']); $goto_exploded = explode(',', $gotos['goto']);
+32 -35
View File
@@ -1,9 +1,10 @@
<?php <?php
function init_db_schema() { function init_db_schema()
{
try { try {
global $pdo; global $pdo;
$db_version = "29072024_1000"; $db_version = "20112024_1105";
$stmt = $pdo->query("SHOW TABLES LIKE 'versions'"); $stmt = $pdo->query("SHOW TABLES LIKE 'versions'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
@@ -111,6 +112,10 @@ function init_db_schema() {
"c_name" => "VARCHAR(255) NOT NULL", "c_name" => "VARCHAR(255) NOT NULL",
"c_password" => "VARCHAR(255) NOT NULL DEFAULT ''", "c_password" => "VARCHAR(255) NOT NULL DEFAULT ''",
"c_cn" => "VARCHAR(255)", "c_cn" => "VARCHAR(255)",
"c_l" => "VARCHAR(255)",
"c_o" => "VARCHAR(255)",
"c_ou" => "VARCHAR(255)",
"c_telephonenumber" => "VARCHAR(255)",
"mail" => "VARCHAR(255) NOT NULL", "mail" => "VARCHAR(255) NOT NULL",
// TODO -> use TEXT and check if SOGo login breaks on empty aliases // TODO -> use TEXT and check if SOGo login breaks on empty aliases
"aliases" => "TEXT NOT NULL", "aliases" => "TEXT NOT NULL",
@@ -484,7 +489,7 @@ function init_db_schema() {
"quarantine_category" => "TINYINT(1) NOT NULL DEFAULT '1'", "quarantine_category" => "TINYINT(1) NOT NULL DEFAULT '1'",
"app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'", "app_passwds" => "TINYINT(1) NOT NULL DEFAULT '1'",
"pw_reset" => "TINYINT(1) NOT NULL DEFAULT '1'", "pw_reset" => "TINYINT(1) NOT NULL DEFAULT '1'",
), ),
"keys" => array( "keys" => array(
"primary" => array( "primary" => array(
"" => array("username") "" => array("username")
@@ -523,6 +528,7 @@ function init_db_schema() {
"cols" => array( "cols" => array(
"address" => "VARCHAR(255) NOT NULL", "address" => "VARCHAR(255) NOT NULL",
"goto" => "TEXT NOT NULL", "goto" => "TEXT NOT NULL",
"description" => "TEXT NOT NULL",
"created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)", "created" => "DATETIME(0) NOT NULL DEFAULT NOW(0)",
"modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP", "modified" => "DATETIME ON UPDATE CURRENT_TIMESTAMP",
"validity" => "INT(11)" "validity" => "INT(11)"
@@ -674,7 +680,7 @@ function init_db_schema() {
"mailbox_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'", "mailbox_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
"domain_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'", "domain_relayhost" => "TINYINT(1) NOT NULL DEFAULT '1'",
"domain_desc" => "TINYINT(1) NOT NULL DEFAULT '0'" "domain_desc" => "TINYINT(1) NOT NULL DEFAULT '0'"
), ),
"keys" => array( "keys" => array(
"primary" => array( "primary" => array(
"" => array("username") "" => array("username")
@@ -1147,7 +1153,7 @@ function init_db_schema() {
while ($row = array_shift($rows)) { while ($row = array_shift($rows)) {
$pdo->query($row['FKEY_DROP']); $pdo->query($row['FKEY_DROP']);
} }
foreach($properties['cols'] as $column => $type) { foreach ($properties['cols'] as $column => $type) {
$stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "` LIKE '" . $column . "'"); $stmt = $pdo->query("SHOW COLUMNS FROM `" . $table . "` LIKE '" . $column . "'");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results == 0) { if ($num_results == 0) {
@@ -1161,12 +1167,11 @@ function init_db_schema() {
} }
} }
$pdo->query("ALTER TABLE `" . $table . "` ADD `" . $column . "` " . $type); $pdo->query("ALTER TABLE `" . $table . "` ADD `" . $column . "` " . $type);
} } else {
else {
$pdo->query("ALTER TABLE `" . $table . "` MODIFY COLUMN `" . $column . "` " . $type); $pdo->query("ALTER TABLE `" . $table . "` MODIFY COLUMN `" . $column . "` " . $type);
} }
} }
foreach($properties['keys'] as $key_type => $key_content) { foreach ($properties['keys'] as $key_type => $key_content) {
if (strtolower($key_type) == 'primary') { if (strtolower($key_type) == 'primary') {
foreach ($key_content as $key_values) { foreach ($key_content as $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`"; $fields = "`" . implode("`, `", $key_values) . "`";
@@ -1223,18 +1228,18 @@ function init_db_schema() {
$keys_to_exist = array(); $keys_to_exist = array();
if (isset($properties['keys']['unique']) && is_array($properties['keys']['unique'])) { if (isset($properties['keys']['unique']) && is_array($properties['keys']['unique'])) {
foreach ($properties['keys']['unique'] as $key_name => $key_values) { foreach ($properties['keys']['unique'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name; $keys_to_exist[] = $key_name;
} }
} }
if (isset($properties['keys']['key']) && is_array($properties['keys']['key'])) { if (isset($properties['keys']['key']) && is_array($properties['keys']['key'])) {
foreach ($properties['keys']['key'] as $key_name => $key_values) { foreach ($properties['keys']['key'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name; $keys_to_exist[] = $key_name;
} }
} }
// Index for foreign key must exist // Index for foreign key must exist
if (isset($properties['keys']['fkey']) && is_array($properties['keys']['fkey'])) { if (isset($properties['keys']['fkey']) && is_array($properties['keys']['fkey'])) {
foreach ($properties['keys']['fkey'] as $key_name => $key_values) { foreach ($properties['keys']['fkey'] as $key_name => $key_values) {
$keys_to_exist[] = $key_name; $keys_to_exist[] = $key_name;
} }
} }
// Step 2: Drop all vanished indexes // Step 2: Drop all vanished indexes
@@ -1251,33 +1256,29 @@ function init_db_schema() {
$pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY"); $pdo->query("ALTER TABLE `" . $table . "` DROP PRIMARY KEY");
} }
} }
} } else {
else {
// Create table if it is missing // Create table if it is missing
$sql = "CREATE TABLE IF NOT EXISTS `" . $table . "` ("; $sql = "CREATE TABLE IF NOT EXISTS `" . $table . "` (";
foreach($properties['cols'] as $column => $type) { foreach ($properties['cols'] as $column => $type) {
$sql .= "`" . $column . "` " . $type . ","; $sql .= "`" . $column . "` " . $type . ",";
} }
foreach($properties['keys'] as $key_type => $key_content) { foreach ($properties['keys'] as $key_type => $key_content) {
if (strtolower($key_type) == 'primary') { if (strtolower($key_type) == 'primary') {
foreach ($key_content as $key_values) { foreach ($key_content as $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`"; $fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "PRIMARY KEY (" . $fields . ")" . ","; $sql .= "PRIMARY KEY (" . $fields . ")" . ",";
} }
} } elseif (strtolower($key_type) == 'key') {
elseif (strtolower($key_type) == 'key') {
foreach ($key_content as $key_name => $key_values) { foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`"; $fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "KEY `" . $key_name . "` (" . $fields . ")" . ","; $sql .= "KEY `" . $key_name . "` (" . $fields . ")" . ",";
} }
} } elseif (strtolower($key_type) == 'unique') {
elseif (strtolower($key_type) == 'unique') {
foreach ($key_content as $key_name => $key_values) { foreach ($key_content as $key_name => $key_values) {
$fields = "`" . implode("`, `", $key_values) . "`"; $fields = "`" . implode("`, `", $key_values) . "`";
$sql .= "UNIQUE KEY `" . $key_name . "` (" . $fields . ")" . ","; $sql .= "UNIQUE KEY `" . $key_name . "` (" . $fields . ")" . ",";
} }
} } elseif (strtolower($key_type) == 'fkey') {
elseif (strtolower($key_type) == 'fkey') {
foreach ($key_content as $key_name => $key_values) { foreach ($key_content as $key_name => $key_values) {
@list($table_ref, $field_ref) = explode('.', $key_values['ref']); @list($table_ref, $field_ref) = explode('.', $key_values['ref']);
$sql .= "FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`) $sql .= "FOREIGN KEY `" . $key_name . "` (" . $key_values['col'] . ") REFERENCES `" . $table_ref . "` (`" . $field_ref . "`)
@@ -1291,7 +1292,6 @@ function init_db_schema() {
} }
// Reset table attributes // Reset table attributes
$pdo->query("ALTER TABLE `" . $table . "` " . $properties['attr'] . ";"); $pdo->query("ALTER TABLE `" . $table . "` " . $properties['attr'] . ";");
} }
// Recreate SQL views // Recreate SQL views
@@ -1318,12 +1318,12 @@ function init_db_schema() {
$stmt = $pdo->query("SELECT NULL FROM `admin`"); $stmt = $pdo->query("SELECT NULL FROM `admin`");
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC)); $num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
if ($num_results == 0) { if ($num_results == 0) {
$pdo->query("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`) $pdo->query("INSERT INTO `admin` (`username`, `password`, `superadmin`, `created`, `modified`, `active`)
VALUES ('admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, NOW(), NOW(), 1)"); VALUES ('admin', '{SSHA256}K8eVJ6YsZbQCfuJvSUbaQRLr0HPLz5rC9IAp0PAFl0tmNDBkMDc0NDAyOTAxN2Rk', 1, NOW(), NOW(), 1)");
$pdo->query("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`) $pdo->query("INSERT INTO `domain_admins` (`username`, `domain`, `created`, `active`)
SELECT `username`, 'ALL', NOW(), 1 FROM `admin` SELECT `username`, 'ALL', NOW(), 1 FROM `admin`
WHERE superadmin='1' AND `username` NOT IN (SELECT `username` FROM `domain_admins`);"); WHERE superadmin='1' AND `username` NOT IN (SELECT `username` FROM `domain_admins`);");
$pdo->query("DELETE FROM `admin` WHERE `username` NOT IN (SELECT `username` FROM `domain_admins`);"); $pdo->query("DELETE FROM `admin` WHERE `username` NOT IN (SELECT `username` FROM `domain_admins`);");
} }
// Insert new DB schema version // Insert new DB schema version
$pdo->query("REPLACE INTO `versions` (`application`, `version`) VALUES ('db_schema', '" . $db_version . "');"); $pdo->query("REPLACE INTO `versions` (`application`, `version`) VALUES ('db_schema', '" . $db_version . "');");
@@ -1351,7 +1351,7 @@ function init_db_schema() {
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.mailbox_format', \"maildir:\") WHERE JSON_VALUE(`attributes`, '$.mailbox_format') IS NULL;"); $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.mailbox_format', \"maildir:\") WHERE JSON_VALUE(`attributes`, '$.mailbox_format') IS NULL;");
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.quarantine_notification', \"never\") WHERE JSON_VALUE(`attributes`, '$.quarantine_notification') IS NULL;"); $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.quarantine_notification', \"never\") WHERE JSON_VALUE(`attributes`, '$.quarantine_notification') IS NULL;");
$pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.quarantine_category', \"reject\") WHERE JSON_VALUE(`attributes`, '$.quarantine_category') IS NULL;"); $pdo->query("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.quarantine_category', \"reject\") WHERE JSON_VALUE(`attributes`, '$.quarantine_category') IS NULL;");
foreach($tls_options as $tls_user => $tls_options) { foreach ($tls_options as $tls_user => $tls_options) {
$stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_enforce_in), $stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`, '$.tls_enforce_in', :tls_enforce_in),
`attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_enforce_out) `attributes` = JSON_SET(`attributes`, '$.tls_enforce_out', :tls_enforce_out)
WHERE `username` = :username"); WHERE `username` = :username");
@@ -1430,7 +1430,7 @@ function init_db_schema() {
":template" => $default_domain_template["template"] ":template" => $default_domain_template["template"]
)); ));
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)){ if (empty($row)) {
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
VALUES (:type, :template, :attributes)"); VALUES (:type, :template, :attributes)");
$stmt->execute(array( $stmt->execute(array(
@@ -1445,7 +1445,7 @@ function init_db_schema() {
":template" => $default_mailbox_template["template"] ":template" => $default_mailbox_template["template"]
)); ));
$row = $stmt->fetch(PDO::FETCH_ASSOC); $row = $stmt->fetch(PDO::FETCH_ASSOC);
if (empty($row)){ if (empty($row)) {
$stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`) $stmt = $pdo->prepare("INSERT INTO `templates` (`type`, `template`, `attributes`)
VALUES (:type, :template, :attributes)"); VALUES (:type, :template, :attributes)");
$stmt->execute(array( $stmt->execute(array(
@@ -1464,8 +1464,7 @@ function init_db_schema() {
'msg' => 'db_init_complete' 'msg' => 'db_init_complete'
); );
} }
} } catch (PDOException $e) {
catch (PDOException $e) {
if (php_sapi_name() == "cli") { if (php_sapi_name() == "cli") {
echo "DB initialization failed: " . print_r($e, true) . PHP_EOL; echo "DB initialization failed: " . print_r($e, true) . PHP_EOL;
} else { } else {
@@ -1504,8 +1503,7 @@ if (php_sapi_name() == "cli") {
SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view"); SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view");
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');"); $stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
echo "Fixed _sogo_static_view" . PHP_EOL; echo "Fixed _sogo_static_view" . PHP_EOL;
} } catch (Exception $e) {
catch ( Exception $e ) {
// Dunno // Dunno
} }
} }
@@ -1513,9 +1511,8 @@ if (php_sapi_name() == "cli") {
$m = new Memcached(); $m = new Memcached();
$m->addServer('memcached', 11211); $m->addServer('memcached', 11211);
$m->flush(); $m->flush();
echo "Cleaned up memcached". PHP_EOL; echo "Cleaned up memcached" . PHP_EOL;
} } catch (Exception $e) {
catch ( Exception $e ) {
// Dunno // Dunno
} }
init_db_schema(); init_db_schema();
+162 -16
View File
@@ -1039,6 +1039,73 @@
}, },
"time": "2017-04-19T22:01:50+00:00" "time": "2017-04-19T22:01:50+00:00"
}, },
{
"name": "symfony/deprecation-contracts",
"version": "v3.5.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/deprecation-contracts.git",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/deprecation-contracts/zipball/0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"reference": "0e0d29ce1f20deffb4ab1b016a7257c4f1e789a1",
"shasum": ""
},
"require": {
"php": ">=8.1"
},
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "3.5-dev"
},
"thanks": {
"name": "symfony/contracts",
"url": "https://github.com/symfony/contracts"
}
},
"autoload": {
"files": [
"function.php"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "A generic function and convention to trigger deprecation notices",
"homepage": "https://symfony.com",
"support": {
"source": "https://github.com/symfony/deprecation-contracts/tree/v3.5.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-04-18T09:32:20+00:00"
},
{ {
"name": "symfony/polyfill-ctype", "name": "symfony/polyfill-ctype",
"version": "v1.24.0", "version": "v1.24.0",
@@ -1287,6 +1354,82 @@
], ],
"time": "2021-09-13T13:58:33+00:00" "time": "2021-09-13T13:58:33+00:00"
}, },
{
"name": "symfony/polyfill-php81",
"version": "v1.31.0",
"source": {
"type": "git",
"url": "https://github.com/symfony/polyfill-php81.git",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/symfony/polyfill-php81/zipball/4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"reference": "4a4cfc2d253c21a5ad0e53071df248ed48c6ce5c",
"shasum": ""
},
"require": {
"php": ">=7.2"
},
"type": "library",
"extra": {
"thanks": {
"name": "symfony/polyfill",
"url": "https://github.com/symfony/polyfill"
}
},
"autoload": {
"files": [
"bootstrap.php"
],
"psr-4": {
"Symfony\\Polyfill\\Php81\\": ""
},
"classmap": [
"Resources/stubs"
]
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "Nicolas Grekas",
"email": "p@tchwork.com"
},
{
"name": "Symfony Community",
"homepage": "https://symfony.com/contributors"
}
],
"description": "Symfony polyfill backporting some PHP 8.1+ features to lower PHP versions",
"homepage": "https://symfony.com",
"keywords": [
"compatibility",
"polyfill",
"portable",
"shim"
],
"support": {
"source": "https://github.com/symfony/polyfill-php81/tree/v1.31.0"
},
"funding": [
{
"url": "https://symfony.com/sponsor",
"type": "custom"
},
{
"url": "https://github.com/fabpot",
"type": "github"
},
{
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
"type": "tidelift"
}
],
"time": "2024-09-09T11:45:10+00:00"
},
{ {
"name": "symfony/translation", "name": "symfony/translation",
"version": "v6.0.5", "version": "v6.0.5",
@@ -1604,34 +1747,37 @@
}, },
{ {
"name": "twig/twig", "name": "twig/twig",
"version": "v3.4.3", "version": "v3.14.0",
"source": { "source": {
"type": "git", "type": "git",
"url": "https://github.com/twigphp/Twig.git", "url": "https://github.com/twigphp/Twig.git",
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58" "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72"
}, },
"dist": { "dist": {
"type": "zip", "type": "zip",
"url": "https://api.github.com/repos/twigphp/Twig/zipball/c38fd6b0b7f370c198db91ffd02e23b517426b58", "url": "https://api.github.com/repos/twigphp/Twig/zipball/126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
"reference": "c38fd6b0b7f370c198db91ffd02e23b517426b58", "reference": "126b2c97818dbff0cdf3fbfc881aedb3d40aae72",
"shasum": "" "shasum": ""
}, },
"require": { "require": {
"php": ">=7.2.5", "php": ">=8.0.2",
"symfony/deprecation-contracts": "^2.5|^3",
"symfony/polyfill-ctype": "^1.8", "symfony/polyfill-ctype": "^1.8",
"symfony/polyfill-mbstring": "^1.3" "symfony/polyfill-mbstring": "^1.3",
"symfony/polyfill-php81": "^1.29"
}, },
"require-dev": { "require-dev": {
"psr/container": "^1.0", "psr/container": "^1.0|^2.0",
"symfony/phpunit-bridge": "^4.4.9|^5.0.9|^6.0" "symfony/phpunit-bridge": "^5.4.9|^6.4|^7.0"
}, },
"type": "library", "type": "library",
"extra": {
"branch-alias": {
"dev-master": "3.4-dev"
}
},
"autoload": { "autoload": {
"files": [
"src/Resources/core.php",
"src/Resources/debug.php",
"src/Resources/escaper.php",
"src/Resources/string_loader.php"
],
"psr-4": { "psr-4": {
"Twig\\": "src/" "Twig\\": "src/"
} }
@@ -1664,7 +1810,7 @@
], ],
"support": { "support": {
"issues": "https://github.com/twigphp/Twig/issues", "issues": "https://github.com/twigphp/Twig/issues",
"source": "https://github.com/twigphp/Twig/tree/v3.4.3" "source": "https://github.com/twigphp/Twig/tree/v3.14.0"
}, },
"funding": [ "funding": [
{ {
@@ -1676,7 +1822,7 @@
"type": "tidelift" "type": "tidelift"
} }
], ],
"time": "2022-09-28T08:42:51+00:00" "time": "2024-09-09T17:55:12+00:00"
}, },
{ {
"name": "yubico/u2flib-server", "name": "yubico/u2flib-server",
@@ -1728,5 +1874,5 @@
"prefer-lowest": false, "prefer-lowest": false,
"platform": [], "platform": [],
"platform-dev": [], "platform-dev": [],
"plugin-api-version": "2.3.0" "plugin-api-version": "2.6.0"
} }
+15 -2
View File
@@ -3,8 +3,21 @@
// autoload.php @generated by Composer // autoload.php @generated by Composer
if (PHP_VERSION_ID < 50600) { if (PHP_VERSION_ID < 50600) {
echo 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL; if (!headers_sent()) {
exit(1); header('HTTP/1.1 500 Internal Server Error');
}
$err = 'Composer 2.3.0 dropped support for autoloading on PHP <5.6 and you are running '.PHP_VERSION.', please upgrade PHP or use Composer 2.2 LTS via "composer self-update --2.2". Aborting.'.PHP_EOL;
if (!ini_get('display_errors')) {
if (PHP_SAPI === 'cli' || PHP_SAPI === 'phpdbg') {
fwrite(STDERR, $err);
} elseif (!headers_sent()) {
echo $err;
}
}
trigger_error(
$err,
E_USER_ERROR
);
} }
require_once __DIR__ . '/composer/autoload_real.php'; require_once __DIR__ . '/composer/autoload_real.php';

Some files were not shown because too many files have changed in this diff Show More