Squashed commit of the following:
commit8f28666916
Merge:428b9175
3eaa5a62
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 16:49:17 2023 +0200 Merge pull request #5195 from mailcow/staging 2023-04b commit3eaa5a626c
Merge:8c79056a
22a0479f
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 14:20:03 2023 +0200 Merge pull request #5187 from mailcow/fix-5185 Nextcloud helperscript - redo PHP check commit8c79056a94
Merge:ed076dc2
0e24c3d3
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 14:19:19 2023 +0200 Merge pull request #5194 from mailcow/renovate/nextcloud-server-26.x Update dependency nextcloud/server to v26.0.1 commited076dc23e
Merge:be2286c1
3510d561
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 13:50:57 2023 +0200 Merge pull request #5186 from goodygh/datatables_sorting [Web] Datatables sorting commitbe2286c11c
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Apr 20 13:41:11 2023 +0200 [Dockerapi] fix maildir cleanup for domains commit0e24c3d300
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Date: Thu Apr 20 11:36:01 2023 +0000 Update dependency nextcloud/server to v26.0.1 Signed-off-by: milkmaker <milkmaker@mailcow.de> commite1d8df6580
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Apr 20 13:20:51 2023 +0200 [Web] check mailbox before replacing sogo_static_view commit04a08a7d69
Merge:026b2783
3c0c8aa0
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 12:32:42 2023 +0200 Merge pull request #5193 from mailcow/feat/update-sogo [SOGo] update sogo 5.8.2.20230419 commit3c0c8aa01f
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Apr 20 12:07:21 2023 +0200 [SOGo] update sogo 5.8.2.20230419 commit026b278357
Merge:00ac61f0
4121509c
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Apr 20 11:34:41 2023 +0200 Merge pull request #5183 from mailcow/fix/add-mbox-performance [Web] optimizing mailbox add/edit/delete performance commit4121509ceb
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Apr 20 11:28:59 2023 +0200 [Web] optimizing update_sogo_static_view function commit00ac61f0a4
Merge:4bb0dbb2
6986e775
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Wed Apr 19 17:31:05 2023 +0200 Merge pull request #5184 from bdwebnet/fix/ui-allowed-protocols Added dropdown divider to "allowed protocols" selection on mailbox page commit4bb0dbb2f7
Merge:13b6df74
20fc9eaf
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Wed Apr 19 17:26:54 2023 +0200 Merge pull request #5191 from shiz0/patch-1 Fix Typo commit13b6df74af
Merge:5c025bf8
b4a9df76
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Wed Apr 19 17:23:26 2023 +0200 Merge pull request #5174 from bdwebnet/staging Fix error "Deprecated: Using ${var} in strings is deprecated, use {$… commit5c025bf865
Author: FreddleSpl0it <patschul@posteo.de> Date: Wed Apr 19 17:03:04 2023 +0200 [Rspamd] rollback to 3.4 commit20fc9eaf84
Author: Hannes Happle <info@h2-it.de> Date: Sun Apr 16 14:32:44 2023 +0200 Fix Typo commit22a0479fab
Author: Peter <magic@kthx.at> Date: Thu Apr 13 21:11:40 2023 +0200 Redo the PHP check grep commit3510d5617d
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 19:18:04 2023 +0200 Fix sorting for active relayhost commit236d627fbd
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 19:14:20 2023 +0200 Fix sorting for active transport map commit99739eada0
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 19:01:03 2023 +0200 Fix sorting for active fowrardinghoststable commit7bfef57894
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 18:54:59 2023 +0200 Fix sorting for active and tla on admins commitd9dfe15253
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 18:54:08 2023 +0200 Fix sorting for active and tla on domain-admins commit3fe8aaa719
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 18:14:18 2023 +0200 Fix sorting for active tls-policy-map commit78a8fac6af
Author: goodygh <github@goodi.ch> Date: Thu Apr 13 18:10:21 2023 +0200 Fix sorting for active bcc-map and recipient-map commit6986e7758f
Author: bd <51322242+bdwebnet@users.noreply.github.com> Date: Thu Apr 13 17:33:28 2023 +0200 Added dropdown divider to "allowed protocols" selection on mailbox page commitb4a9df76b8
Merge:bdb07061
f681fcf1
Author: BD <51322242+bdwebnet@users.noreply.github.com> Date: Thu Apr 13 17:22:13 2023 +0200 Merge branch 'mailcow:staging' into staging commitd9d958356a
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Apr 13 14:35:55 2023 +0200 [Web] optimizing update_sogo_static_view function commit96f954a4e2
Author: goodygh <github@goodi.ch> Date: Wed Apr 12 00:36:46 2023 +0200 Fix sorting for active syncjobs commit44585e1c15
Author: goodygh <github@goodi.ch> Date: Wed Apr 12 00:23:53 2023 +0200 Fix sorting datatable in domain aliases commitc737ff4180
Author: goodygh <github@goodi.ch> Date: Wed Apr 12 00:21:27 2023 +0200 Fix sorting datatable in aliases commit025279009d
Author: goodygh <github@goodi.ch> Date: Wed Apr 12 00:17:41 2023 +0200 Fix sorting for active resources commita9dc13d567
Author: goodygh <github@goodi.ch> Date: Wed Apr 12 00:15:16 2023 +0200 Fix sorting datatable in mailbox templates commitc3ed01c9b5
Author: goodygh <github@goodi.ch> Date: Tue Apr 11 23:49:50 2023 +0200 Fix sorting for active mailboxes commitbd0b4a521e
Author: goodygh <github@goodi.ch> Date: Tue Apr 11 23:42:43 2023 +0200 Fix sorting datatable in domain templates commit800a0ace71
Author: goodygh <github@goodi.ch> Date: Tue Apr 11 23:19:56 2023 +0200 Fix sorting for active domain in domains table commitdb97869472
Author: goodygh <github@goodi.ch> Date: Tue Apr 11 23:18:13 2023 +0200 Datatable hide sorting value commitf681fcf154
Author: milkmaker <milkmaker@mailcow.de> Date: Tue Apr 11 17:38:39 2023 +0200 [Web] Updated lang.cs-cz.json (#5177) Co-authored-by: utaxiu <kontakt@malyjakub.cz> commitdb1b5956fc
Merge:469f959e
80dacc01
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Tue Apr 11 06:35:41 2023 +0200 Merge pull request #5133 from FELDSAM-INC/feldsam/bs5-related-fixes BS5 related fixes commitbdb07061ed
Author: BD <51322242+bdwebnet@users.noreply.github.com> Date: Sat Apr 8 17:29:34 2023 +0200 Fix error "Deprecated: Using ${var} in strings is deprecated, use {$var} instead in /web/sogo-auth.php on line 63" commit428b917579
Merge:028ef228
469f959e
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Apr 3 20:15:46 2023 +0200 Merge pull request #5166 from mailcow/staging Hotfix php8.2 nextcloud < 26 commit469f959e96
Merge:0194c39b
b68e189d
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Apr 3 20:10:05 2023 +0200 Merge pull request #5164 from mailcow/fix-5163 Add a check for PHP>=8.2 errormsg commitb68e189d97
Author: Peter <magic@kthx.at> Date: Mon Apr 3 19:03:13 2023 +0200 Add a check for PHP>=8.2 errormsg commit028ef22878
Merge:229303c1
0194c39b
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Apr 3 14:55:55 2023 +0200 Merge pull request #5162 from mailcow/staging Update 2023-04 commit80dacc015a
Author: Kristian Feldsam <feldsam@gmail.com> Date: Mon Mar 20 01:37:49 2023 +0100 [web] fixed mailbox/user settings buttons styling Signed-off-by: Kristian Feldsam <feldsam@gmail.com> [web] fixed mailbox/user settings buttons styling Signed-off-by: Kristian Feldsam <feldsam@gmail.com> commit0194c39bd5
Merge:ae46a877
f53ca24b
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Fri Mar 31 08:16:57 2023 +0200 Merge pull request #5158 from mailcow/feat/sogo-5.8.2 [SOGo] Update to 5.8.2 commitf53ca24bb0
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Mar 30 16:00:21 2023 +0200 [SOGo] Update to 5.8.2 commitae46a877d3
Merge:fd0205aa
400939fa
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Mar 30 09:05:52 2023 +0200 Merge pull request #5157 from mailcow/feat/netfilter-1.52 [Netfilter] Update to 1.52 commit400939faf6
Author: FreddleSpl0it <patschul@posteo.de> Date: Thu Mar 30 08:44:38 2023 +0200 [Netfilter] Update to 1.52 commitfd0205aafd
Merge:e367a8ce
096e2a41
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Mar 30 07:53:33 2023 +0200 Merge pull request #5127 from th-joerger/feature/bantime-increment [Netfilter] Implemented exponentially incrementing bantime commite367a8ce24
Merge:3d2483ca
26c34b48
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Thu Mar 30 07:52:00 2023 +0200 Merge pull request #5153 from mailcow/fix/del-vmail-index [Dockerapi] delete vmail_index on maildir cleanup commit096e2a41e9
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Wed Mar 29 17:09:25 2023 +0200 Push verified options to redis after each check commite010f08143
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Wed Mar 29 15:18:11 2023 +0200 verify options after loading them, set defaults if options are missing or invalid commit3d2483ca37
Merge:535dd235
f77c6541
Author: Patrick Schult <75116288+FreddleSpl0it@users.noreply.github.com> Date: Wed Mar 29 08:13:11 2023 +0200 Merge pull request #5093 from brunoleon/fix_snat Fix SNAT never being added because of exception commit535dd23509
Merge:4336a99c
9fd4aa93
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Tue Mar 28 11:44:59 2023 +0200 Merge pull request #5139 from mailcow/renovate/mailcow-rspamd-1.x Update mailcow/rspamd Docker tag to v1.93 commit4336a99c6a
Author: DerLinkman <derlinkman@gmail.com> Date: Tue Mar 28 11:40:00 2023 +0200 [Nextcloud] Changed default X-Robots Tag behavior commit4cd5f93cdf
Author: DerLinkman <derlinkman@gmail.com> Date: Tue Mar 28 11:22:49 2023 +0200 Fixed broken pipe errors in nextcloud.sh commit67955779b0
Author: DerLinkman <derlinkman@gmail.com> Date: Tue Mar 28 11:17:59 2023 +0200 Fix broken pipe error in reset-admin.sh commit26c34b484a
Author: FreddleSpl0it <patschul@posteo.de> Date: Tue Mar 28 11:01:14 2023 +0200 increase dockerapi image commit4021613059
Author: FreddleSpl0it <patschul@posteo.de> Date: Tue Mar 28 10:59:08 2023 +0200 delete vmail_index when mbox is deleted commite891bf8411
Merge:f7798d1a
5bc3d935
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Mar 27 10:40:40 2023 +0200 Merge pull request #5138 from th-joerger/feature/pubsub-exception [netfilter] add pubsub exception commitf7798d1aac
Merge:d11f0026
db2fb128
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Mar 27 10:13:42 2023 +0200 Merge pull request #5099 from mailcow/feat/phpfpm-8.2 Update to PHP 8.2 commitd11f00261b
Merge:ce6742c6
22cd12f3
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Mar 27 10:12:55 2023 +0200 Merge pull request #5142 from mailcow/renovate/nextcloud-server-26.x Update dependency nextcloud/server to v26 commit22cd12f37b
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Date: Sat Mar 25 18:48:22 2023 +0000 Update dependency nextcloud/server to v26 Signed-off-by: milkmaker <milkmaker@mailcow.de> commitdb2fb12837
Author: Peter <magic@kthx.at> Date: Fri Mar 24 16:08:19 2023 +0100 Install sysvsem for Nextcloud 26 commite808e595eb
Author: Peter <magic@kthx.at> Date: Fri Mar 24 16:05:35 2023 +0100 Update dependency composer/composer to v2.5.5 commitce6742c676
Merge:62f36035
cf3dc584
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Thu Mar 23 19:38:23 2023 +0100 Merge pull request #5147 from mailcow/renovate/nextcloud-server-25.x Update dependency nextcloud/server to v25.0.5 commitcf3dc584d0
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Date: Thu Mar 23 14:18:29 2023 +0000 Update dependency nextcloud/server to v25.0.5 Signed-off-by: milkmaker <milkmaker@mailcow.de> commit62f3603588
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Date: Wed Mar 22 15:00:55 2023 +0100 Update actions/stale action to v8 (#5143) Signed-off-by: milkmaker <milkmaker@mailcow.de> Co-authored-by: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> commit9fd4aa93e9
Author: renovate[bot] <29139614+renovate[bot]@users.noreply.github.com> Date: Tue Mar 21 10:32:21 2023 +0000 Update mailcow/rspamd Docker tag to v1.93 Signed-off-by: milkmaker <milkmaker@mailcow.de> commit5bc3d93545
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Tue Mar 21 11:12:07 2023 +0100 log exception of redis pubsub subscription commitc28a6b89f0
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Fri Mar 17 18:22:16 2023 +0100 Added ban_time_increment and max_ban_time to UI commit1233613bea
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Fri Mar 17 14:41:37 2023 +0100 implemented handling of max_bantime and ban_time_increment flag commit0206e0886c
Author: Thorbjörn Jörger <thor@joerger.dev> Date: Fri Mar 17 01:33:40 2023 +0100 implemented exponentially incrementing bantime, removed active_window code that did nothing, cleanly initialized dictionary commitf6d135fbad
Author: DerLinkman <derlinkman@gmail.com> Date: Mon Mar 20 12:05:11 2023 +0100 [Update.sh] Fix docker compose detection + added failover commitf7da314dcf
Merge:0f59d495
e6ce5e88
Author: Niklas Meyer <62480600+DerLinkman@users.noreply.github.com> Date: Mon Mar 20 11:08:11 2023 +0100 Merge pull request #5134 from mailcow/fix/generate-config-dev [Generate.sh] Fixed broken pipe error message commite6ce5e88f7
Author: DerLinkman <derlinkman@gmail.com> Date: Mon Mar 20 10:57:40 2023 +0100 [Generate.sh] Fixed broken pipe error message commite5e6418be8
Author: Kristian Feldsam <feldsam@gmail.com> Date: Mon Mar 20 01:30:06 2023 +0100 [web] fixed tooltips in ajax loaded alias table Signed-off-by: Kristian Feldsam <feldsam@gmail.com> commit6507b53bbb
Author: Kristian Feldsam <feldsam@gmail.com> Date: Mon Mar 20 01:29:01 2023 +0100 [web] fix mailbox badge height Signed-off-by: Kristian Feldsam <feldsam@gmail.com> commit0f59d4952b
Author: milkmaker <milkmaker@mailcow.de> Date: Fri Mar 17 19:13:49 2023 +0100 Translations update from Weblate (#5131) * [Web] Updated lang.da-dk.json Co-authored-by: Victor Pahuus Petersen <dibbohh@gmail.com> Co-authored-by: milkmaker <milkmaker@mailcow.de> * [Web] Updated lang.fr-fr.json Co-authored-by: UpSilot <alexandre+weblate@kilobit.fr> Co-authored-by: milkmaker <milkmaker@mailcow.de> --------- Co-authored-by: Victor Pahuus Petersen <dibbohh@gmail.com> Co-authored-by: UpSilot <alexandre+weblate@kilobit.fr> commita5b8f1b7f7
Author: Peter <magic@kthx.at> Date: Tue Feb 28 20:08:33 2023 +0100 Update to PHP 8.2 commitf77c65411d
Author: Bruno Léon <bruno.leon@unyonsys.com> Date: Mon Feb 27 12:04:32 2023 +0100 Fix SNAT never being added because of exception Some firewall rule object (iptc) do not have a parameter attribute, which results in an exception being triggered, and the mailcow SNAT rule to never be created. Firewall rules that trigger such exception are: - -A POSTROUTING -s 192.168.122.0/24 -d 224.0.0.0/24 -j RETURN This commit just verify attribute presence, and skip the rule properly instead of triggering an exception.
This commit is contained in:
parent
8034f1bc0b
commit
fb20fd48fb
|
@ -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@v7.0.0
|
uses: actions/stale@v8.0.0
|
||||||
with:
|
with:
|
||||||
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
||||||
days-before-stale: 60
|
days-before-stale: 60
|
||||||
|
|
|
@ -380,7 +380,15 @@ class DockerUtils:
|
||||||
if 'maildir' in request_json:
|
if 'maildir' in request_json:
|
||||||
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
for container in self.docker_client.containers.list(filters={"id": container_id}):
|
||||||
sane_name = re.sub(r'\W+', '', request_json['maildir'])
|
sane_name = re.sub(r'\W+', '', request_json['maildir'])
|
||||||
cmd = ["/bin/bash", "-c", "if [[ -d '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' ]]; then /bin/mv '/var/vmail/" + request_json['maildir'].replace("'", "'\\''") + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"]
|
vmail_name = request_json['maildir'].replace("'", "'\\''")
|
||||||
|
cmd_vmail = "if [[ -d '/var/vmail/" + vmail_name + "' ]]; then /bin/mv '/var/vmail/" + vmail_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "'; fi"
|
||||||
|
index_name = request_json['maildir'].split("/")
|
||||||
|
if len(index_name) > 1:
|
||||||
|
index_name = index_name[1].replace("'", "'\\''") + "@" + index_name[0].replace("'", "'\\''")
|
||||||
|
cmd_vmail_index = "if [[ -d '/var/vmail_index/" + index_name + "' ]]; then /bin/mv '/var/vmail_index/" + index_name + "' '/var/vmail/_garbage/" + str(int(time.time())) + "_" + sane_name + "_index'; fi"
|
||||||
|
cmd = ["/bin/bash", "-c", cmd_vmail + " && " + cmd_vmail_index]
|
||||||
|
else:
|
||||||
|
cmd = ["/bin/bash", "-c", cmd_vmail]
|
||||||
maildir_cleanup = container.exec_run(cmd, user='vmail')
|
maildir_cleanup = container.exec_run(cmd, user='vmail')
|
||||||
return exec_run_handler('generic', maildir_cleanup)
|
return exec_run_handler('generic', maildir_cleanup)
|
||||||
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
|
# api call: container_post - post_action: exec - cmd: rspamd - task: worker_password
|
||||||
|
|
|
@ -80,28 +80,40 @@ def refreshF2boptions():
|
||||||
global f2boptions
|
global f2boptions
|
||||||
global quit_now
|
global quit_now
|
||||||
global exit_code
|
global exit_code
|
||||||
|
|
||||||
|
f2boptions = {}
|
||||||
|
|
||||||
if not r.get('F2B_OPTIONS'):
|
if not r.get('F2B_OPTIONS'):
|
||||||
f2boptions = {}
|
f2boptions['ban_time'] = r.get('F2B_BAN_TIME')
|
||||||
f2boptions['ban_time'] = int
|
f2boptions['max_ban_time'] = r.get('F2B_MAX_BAN_TIME')
|
||||||
f2boptions['max_attempts'] = int
|
f2boptions['ban_time_increment'] = r.get('F2B_BAN_TIME_INCREMENT')
|
||||||
f2boptions['retry_window'] = int
|
f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS')
|
||||||
f2boptions['netban_ipv4'] = int
|
f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW')
|
||||||
f2boptions['netban_ipv6'] = int
|
f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4')
|
||||||
f2boptions['ban_time'] = r.get('F2B_BAN_TIME') or 1800
|
f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6')
|
||||||
f2boptions['max_attempts'] = r.get('F2B_MAX_ATTEMPTS') or 10
|
|
||||||
f2boptions['retry_window'] = r.get('F2B_RETRY_WINDOW') or 600
|
|
||||||
f2boptions['netban_ipv4'] = r.get('F2B_NETBAN_IPV4') or 32
|
|
||||||
f2boptions['netban_ipv6'] = r.get('F2B_NETBAN_IPV6') or 128
|
|
||||||
r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False))
|
|
||||||
else:
|
else:
|
||||||
try:
|
try:
|
||||||
f2boptions = {}
|
|
||||||
f2boptions = json.loads(r.get('F2B_OPTIONS'))
|
f2boptions = json.loads(r.get('F2B_OPTIONS'))
|
||||||
except ValueError:
|
except ValueError:
|
||||||
print('Error loading F2B options: F2B_OPTIONS is not json')
|
print('Error loading F2B options: F2B_OPTIONS is not json')
|
||||||
quit_now = True
|
quit_now = True
|
||||||
exit_code = 2
|
exit_code = 2
|
||||||
|
|
||||||
|
verifyF2boptions(f2boptions)
|
||||||
|
r.set('F2B_OPTIONS', json.dumps(f2boptions, ensure_ascii=False))
|
||||||
|
|
||||||
|
def verifyF2boptions(f2boptions):
|
||||||
|
verifyF2boption(f2boptions,'ban_time', 1800)
|
||||||
|
verifyF2boption(f2boptions,'max_ban_time', 10000)
|
||||||
|
verifyF2boption(f2boptions,'ban_time_increment', True)
|
||||||
|
verifyF2boption(f2boptions,'max_attempts', 10)
|
||||||
|
verifyF2boption(f2boptions,'retry_window', 600)
|
||||||
|
verifyF2boption(f2boptions,'netban_ipv4', 32)
|
||||||
|
verifyF2boption(f2boptions,'netban_ipv6', 128)
|
||||||
|
|
||||||
|
def verifyF2boption(f2boptions, f2boption, f2bdefault):
|
||||||
|
f2boptions[f2boption] = f2boptions[f2boption] if f2boption in f2boptions and f2boptions[f2boption] is not None else f2bdefault
|
||||||
|
|
||||||
def refreshF2bregex():
|
def refreshF2bregex():
|
||||||
global f2bregex
|
global f2bregex
|
||||||
global quit_now
|
global quit_now
|
||||||
|
@ -560,6 +572,7 @@ def ban(address):
|
||||||
global lock
|
global lock
|
||||||
refreshF2boptions()
|
refreshF2boptions()
|
||||||
BAN_TIME = int(f2boptions['ban_time'])
|
BAN_TIME = int(f2boptions['ban_time'])
|
||||||
|
BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment'])
|
||||||
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
||||||
RETRY_WINDOW = int(f2boptions['retry_window'])
|
RETRY_WINDOW = int(f2boptions['retry_window'])
|
||||||
NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4'])
|
NETBAN_IPV4 = '/' + str(f2boptions['netban_ipv4'])
|
||||||
|
@ -596,11 +609,10 @@ def ban(address):
|
||||||
bans[net]['attempts'] += 1
|
bans[net]['attempts'] += 1
|
||||||
bans[net]['last_attempt'] = time.time()
|
bans[net]['last_attempt'] = time.time()
|
||||||
|
|
||||||
active_window = time.time() - bans[net]['last_attempt']
|
|
||||||
|
|
||||||
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
||||||
cur_time = int(round(time.time()))
|
cur_time = int(round(time.time()))
|
||||||
logCrit('Banning %s for %d minutes' % (net, BAN_TIME / 60))
|
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||||
|
logCrit('Banning %s for %d minutes' % (net, NET_BAN_TIME / 60 ))
|
||||||
if type(ip) is ipaddress.IPv4Address:
|
if type(ip) is ipaddress.IPv4Address:
|
||||||
with lock:
|
with lock:
|
||||||
if backend == 'iptables':
|
if backend == 'iptables':
|
||||||
|
@ -628,7 +640,7 @@ def ban(address):
|
||||||
ban_dict = get_ban_ip_dict(net, "ip6")
|
ban_dict = get_ban_ip_dict(net, "ip6")
|
||||||
nft_exec_dict(ban_dict)
|
nft_exec_dict(ban_dict)
|
||||||
|
|
||||||
r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + BAN_TIME)
|
r.hset('F2B_ACTIVE_BANS', '%s' % net, cur_time + NET_BAN_TIME)
|
||||||
else:
|
else:
|
||||||
logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net))
|
logWarn('%d more attempts in the next %d seconds until %s is banned' % (MAX_ATTEMPTS - bans[net]['attempts'], RETRY_WINDOW, net))
|
||||||
|
|
||||||
|
@ -673,7 +685,8 @@ def unban(net):
|
||||||
r.hdel('F2B_ACTIVE_BANS', '%s' % net)
|
r.hdel('F2B_ACTIVE_BANS', '%s' % net)
|
||||||
r.hdel('F2B_QUEUE_UNBAN', '%s' % net)
|
r.hdel('F2B_QUEUE_UNBAN', '%s' % net)
|
||||||
if net in bans:
|
if net in bans:
|
||||||
del bans[net]
|
bans[net]['attempts'] = 0
|
||||||
|
bans[net]['ban_counter'] += 1
|
||||||
|
|
||||||
def permBan(net, unban=False):
|
def permBan(net, unban=False):
|
||||||
global lock
|
global lock
|
||||||
|
@ -840,7 +853,7 @@ def watch():
|
||||||
logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data']))
|
logWarn('%s matched rule id %s (%s)' % (addr, rule_id, item['data']))
|
||||||
ban(addr)
|
ban(addr)
|
||||||
except Exception as ex:
|
except Exception as ex:
|
||||||
logWarn('Error reading log line from pubsub')
|
logWarn('Error reading log line from pubsub: %s' % ex)
|
||||||
quit_now = True
|
quit_now = True
|
||||||
exit_code = 2
|
exit_code = 2
|
||||||
|
|
||||||
|
@ -946,6 +959,8 @@ def autopurge():
|
||||||
time.sleep(10)
|
time.sleep(10)
|
||||||
refreshF2boptions()
|
refreshF2boptions()
|
||||||
BAN_TIME = int(f2boptions['ban_time'])
|
BAN_TIME = int(f2boptions['ban_time'])
|
||||||
|
MAX_BAN_TIME = int(f2boptions['max_ban_time'])
|
||||||
|
BAN_TIME_INCREMENT = bool(f2boptions['ban_time_increment'])
|
||||||
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
MAX_ATTEMPTS = int(f2boptions['max_attempts'])
|
||||||
QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN')
|
QUEUE_UNBAN = r.hgetall('F2B_QUEUE_UNBAN')
|
||||||
if QUEUE_UNBAN:
|
if QUEUE_UNBAN:
|
||||||
|
@ -953,7 +968,9 @@ def autopurge():
|
||||||
unban(str(net))
|
unban(str(net))
|
||||||
for net in bans.copy():
|
for net in bans.copy():
|
||||||
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
if bans[net]['attempts'] >= MAX_ATTEMPTS:
|
||||||
if time.time() - bans[net]['last_attempt'] > BAN_TIME:
|
NET_BAN_TIME = BAN_TIME if not BAN_TIME_INCREMENT else BAN_TIME * 2 ** bans[net]['ban_counter']
|
||||||
|
TIME_SINCE_LAST_ATTEMPT = time.time() - bans[net]['last_attempt']
|
||||||
|
if TIME_SINCE_LAST_ATTEMPT > NET_BAN_TIME or TIME_SINCE_LAST_ATTEMPT > MAX_BAN_TIME:
|
||||||
unban(net)
|
unban(net)
|
||||||
|
|
||||||
def isIpNetwork(address):
|
def isIpNetwork(address):
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
FROM php:8.1-fpm-alpine3.17
|
FROM php:8.2-fpm-alpine3.17
|
||||||
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
LABEL maintainer "Andre Peters <andre.peters@servercow.de>"
|
||||||
|
|
||||||
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced
|
# renovate: datasource=github-tags depName=krakjoe/apcu versioning=semver-coerced
|
||||||
|
@ -12,7 +12,7 @@ ARG MEMCACHED_PECL_VERSION=3.2.0
|
||||||
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced
|
# renovate: datasource=github-tags depName=phpredis/phpredis versioning=semver-coerced
|
||||||
ARG REDIS_PECL_VERSION=5.3.7
|
ARG REDIS_PECL_VERSION=5.3.7
|
||||||
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced
|
# renovate: datasource=github-tags depName=composer/composer versioning=semver-coerced
|
||||||
ARG COMPOSER_VERSION=2.5.4
|
ARG COMPOSER_VERSION=2.5.5
|
||||||
|
|
||||||
RUN apk add -U --no-cache autoconf \
|
RUN apk add -U --no-cache autoconf \
|
||||||
aspell-dev \
|
aspell-dev \
|
||||||
|
@ -52,6 +52,7 @@ RUN apk add -U --no-cache autoconf \
|
||||||
libxpm-dev \
|
libxpm-dev \
|
||||||
libzip \
|
libzip \
|
||||||
libzip-dev \
|
libzip-dev \
|
||||||
|
linux-headers \
|
||||||
make \
|
make \
|
||||||
mysql-client \
|
mysql-client \
|
||||||
openldap-dev \
|
openldap-dev \
|
||||||
|
@ -75,7 +76,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 zip bcmath gmp \
|
&& 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-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} \
|
||||||
|
@ -99,6 +100,7 @@ RUN apk add -U --no-cache autoconf \
|
||||||
libxml2-dev \
|
libxml2-dev \
|
||||||
libxpm-dev \
|
libxpm-dev \
|
||||||
libzip-dev \
|
libzip-dev \
|
||||||
|
linux-headers \
|
||||||
make \
|
make \
|
||||||
openldap-dev \
|
openldap-dev \
|
||||||
pcre-dev \
|
pcre-dev \
|
||||||
|
|
|
@ -24,7 +24,7 @@ server {
|
||||||
add_header X-Download-Options "noopen" always;
|
add_header X-Download-Options "noopen" always;
|
||||||
add_header X-Frame-Options "SAMEORIGIN" always;
|
add_header X-Frame-Options "SAMEORIGIN" always;
|
||||||
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
add_header X-Permitted-Cross-Domain-Policies "none" always;
|
||||||
add_header X-Robots-Tag "none" always;
|
add_header X-Robots-Tag "noindex, nofollow" always;
|
||||||
add_header X-XSS-Protection "1; mode=block" always;
|
add_header X-XSS-Protection "1; mode=block" always;
|
||||||
|
|
||||||
fastcgi_hide_header X-Powered-By;
|
fastcgi_hide_header X-Powered-By;
|
||||||
|
|
|
@ -3176,8 +3176,10 @@ paths:
|
||||||
example:
|
example:
|
||||||
attr:
|
attr:
|
||||||
ban_time: "86400"
|
ban_time: "86400"
|
||||||
|
ban_time_increment: "1"
|
||||||
blacklist: "10.100.6.5/32,10.100.8.4/32"
|
blacklist: "10.100.6.5/32,10.100.8.4/32"
|
||||||
max_attempts: "5"
|
max_attempts: "5"
|
||||||
|
max_ban_time: "86400"
|
||||||
netban_ipv4: "24"
|
netban_ipv4: "24"
|
||||||
netban_ipv6: "64"
|
netban_ipv6: "64"
|
||||||
retry_window: "600"
|
retry_window: "600"
|
||||||
|
@ -3191,11 +3193,17 @@ paths:
|
||||||
description: the backlisted ips or hostnames separated by comma
|
description: the backlisted ips or hostnames separated by comma
|
||||||
type: string
|
type: string
|
||||||
ban_time:
|
ban_time:
|
||||||
description: the time a ip should be banned
|
description: the time an ip should be banned
|
||||||
type: number
|
type: number
|
||||||
|
ban_time_increment:
|
||||||
|
description: if the time of the ban should increase each time
|
||||||
|
type: boolean
|
||||||
max_attempts:
|
max_attempts:
|
||||||
description: the maximum numbe of wrong logins before a ip is banned
|
description: the maximum numbe of wrong logins before a ip is banned
|
||||||
type: number
|
type: number
|
||||||
|
max_ban_time:
|
||||||
|
description: the maximum time an ip should be banned
|
||||||
|
type: number
|
||||||
netban_ipv4:
|
netban_ipv4:
|
||||||
description: the networks mask to ban for ipv4
|
description: the networks mask to ban for ipv4
|
||||||
type: number
|
type: number
|
||||||
|
@ -4113,10 +4121,12 @@ paths:
|
||||||
response:
|
response:
|
||||||
value:
|
value:
|
||||||
ban_time: 604800
|
ban_time: 604800
|
||||||
|
ban_time_increment: 1
|
||||||
blacklist: |-
|
blacklist: |-
|
||||||
45.82.153.37/32
|
45.82.153.37/32
|
||||||
92.118.38.52/32
|
92.118.38.52/32
|
||||||
max_attempts: 1
|
max_attempts: 1
|
||||||
|
max_ban_time: 604800
|
||||||
netban_ipv4: 32
|
netban_ipv4: 32
|
||||||
netban_ipv6: 128
|
netban_ipv6: 128
|
||||||
perm_bans:
|
perm_bans:
|
||||||
|
|
|
@ -342,6 +342,10 @@ div.dataTables_wrapper div.dt-row {
|
||||||
position: relative;
|
position: relative;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
div.dataTables_wrapper span.sorting-value {
|
||||||
|
display: none;
|
||||||
|
}
|
||||||
|
|
||||||
div.dataTables_scrollHead table.dataTable {
|
div.dataTables_scrollHead table.dataTable {
|
||||||
margin-bottom: 0 !important;
|
margin-bottom: 0 !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -66,4 +66,6 @@ table tbody tr td input[type="checkbox"] {
|
||||||
padding: .2em .4em .3em !important;
|
padding: .2em .4em .3em !important;
|
||||||
background-color: #ececec!important;
|
background-color: #ececec!important;
|
||||||
}
|
}
|
||||||
|
.badge.bg-info .bi {
|
||||||
|
font-size: inherit;
|
||||||
|
}
|
||||||
|
|
|
@ -20,6 +20,11 @@ legend {
|
||||||
background-color: #7a7a7a !important;
|
background-color: #7a7a7a !important;
|
||||||
border-color: #5c5c5c !important;
|
border-color: #5c5c5c !important;
|
||||||
}
|
}
|
||||||
|
.btn-dark {
|
||||||
|
color: #000 !important;;
|
||||||
|
background-color: #f6f6f6 !important;;
|
||||||
|
border-color: #ddd !important;;
|
||||||
|
}
|
||||||
.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle {
|
.btn-check:checked+.btn-secondary, .btn-check:active+.btn-secondary, .btn-secondary:active, .btn-secondary.active, .show>.btn-secondary.dropdown-toggle {
|
||||||
border-color: #7a7a7a !important;
|
border-color: #7a7a7a !important;
|
||||||
}
|
}
|
||||||
|
|
|
@ -239,7 +239,9 @@ function fail2ban($_action, $_data = null) {
|
||||||
$is_now = fail2ban('get');
|
$is_now = fail2ban('get');
|
||||||
if (!empty($is_now)) {
|
if (!empty($is_now)) {
|
||||||
$ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']);
|
$ban_time = intval((isset($_data['ban_time'])) ? $_data['ban_time'] : $is_now['ban_time']);
|
||||||
|
$ban_time_increment = (isset($_data['ban_time_increment']) && $_data['ban_time_increment'] == "1") ? 1 : 0;
|
||||||
$max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['max_attempts']);
|
$max_attempts = intval((isset($_data['max_attempts'])) ? $_data['max_attempts'] : $is_now['max_attempts']);
|
||||||
|
$max_ban_time = intval((isset($_data['max_ban_time'])) ? $_data['max_ban_time'] : $is_now['max_ban_time']);
|
||||||
$retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']);
|
$retry_window = intval((isset($_data['retry_window'])) ? $_data['retry_window'] : $is_now['retry_window']);
|
||||||
$netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']);
|
$netban_ipv4 = intval((isset($_data['netban_ipv4'])) ? $_data['netban_ipv4'] : $is_now['netban_ipv4']);
|
||||||
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
$netban_ipv6 = intval((isset($_data['netban_ipv6'])) ? $_data['netban_ipv6'] : $is_now['netban_ipv6']);
|
||||||
|
@ -256,6 +258,8 @@ function fail2ban($_action, $_data = null) {
|
||||||
}
|
}
|
||||||
$f2b_options = array();
|
$f2b_options = array();
|
||||||
$f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $ban_time;
|
$f2b_options['ban_time'] = ($ban_time < 60) ? 60 : $ban_time;
|
||||||
|
$f2b_options['ban_time_increment'] = ($ban_time_increment == 1) ? true : false;
|
||||||
|
$f2b_options['max_ban_time'] = ($max_ban_time < 60) ? 60 : $max_ban_time;
|
||||||
$f2b_options['netban_ipv4'] = ($netban_ipv4 < 8) ? 8 : $netban_ipv4;
|
$f2b_options['netban_ipv4'] = ($netban_ipv4 < 8) ? 8 : $netban_ipv4;
|
||||||
$f2b_options['netban_ipv6'] = ($netban_ipv6 < 8) ? 8 : $netban_ipv6;
|
$f2b_options['netban_ipv6'] = ($netban_ipv6 < 8) ? 8 : $netban_ipv6;
|
||||||
$f2b_options['netban_ipv4'] = ($netban_ipv4 > 32) ? 32 : $netban_ipv4;
|
$f2b_options['netban_ipv4'] = ($netban_ipv4 > 32) ? 32 : $netban_ipv4;
|
||||||
|
|
|
@ -1015,20 +1015,58 @@ function formatBytes($size, $precision = 2) {
|
||||||
}
|
}
|
||||||
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
return round(pow(1024, $base - floor($base)), $precision) . $suffixes[floor($base)];
|
||||||
}
|
}
|
||||||
function update_sogo_static_view() {
|
function update_sogo_static_view($mailbox = null) {
|
||||||
if (getenv('SKIP_SOGO') == "y") {
|
if (getenv('SKIP_SOGO') == "y") {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
global $pdo;
|
global $pdo;
|
||||||
global $lang;
|
global $lang;
|
||||||
$stmt = $pdo->query("SELECT 'OK' FROM INFORMATION_SCHEMA.TABLES
|
|
||||||
WHERE TABLE_NAME = 'sogo_view'");
|
$mailbox_exists = false;
|
||||||
$num_results = count($stmt->fetchAll(PDO::FETCH_ASSOC));
|
if ($mailbox !== null) {
|
||||||
if ($num_results != 0) {
|
// Check if the mailbox exists
|
||||||
$stmt = $pdo->query("REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
|
$stmt = $pdo->prepare("SELECT username FROM mailbox WHERE username = :mailbox AND active = '1'");
|
||||||
SELECT `c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings` from sogo_view");
|
$stmt->execute(array(':mailbox' => $mailbox));
|
||||||
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
$row = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||||
|
if ($row){
|
||||||
|
$mailbox_exists = true;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$query = "REPLACE INTO _sogo_static_view (`c_uid`, `domain`, `c_name`, `c_password`, `c_cn`, `mail`, `aliases`, `ad_aliases`, `ext_acl`, `kind`, `multiple_bookings`)
|
||||||
|
SELECT
|
||||||
|
mailbox.username,
|
||||||
|
mailbox.domain,
|
||||||
|
mailbox.username,
|
||||||
|
IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.force_pw_update')) = '0',
|
||||||
|
IF(JSON_UNQUOTE(JSON_VALUE(attributes, '$.sogo_access')) = 1, password, '{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'),
|
||||||
|
'{SSHA256}A123A123A321A321A321B321B321B123B123B321B432F123E321123123321321'),
|
||||||
|
mailbox.name,
|
||||||
|
mailbox.username,
|
||||||
|
IFNULL(GROUP_CONCAT(ga.aliases ORDER BY ga.aliases SEPARATOR ' '), ''),
|
||||||
|
IFNULL(gda.ad_alias, ''),
|
||||||
|
IFNULL(external_acl.send_as_acl, ''),
|
||||||
|
mailbox.kind,
|
||||||
|
mailbox.multiple_bookings
|
||||||
|
FROM
|
||||||
|
mailbox
|
||||||
|
LEFT OUTER JOIN grouped_mail_aliases ga ON ga.username REGEXP CONCAT('(^|,)', mailbox.username, '($|,)')
|
||||||
|
LEFT OUTER JOIN grouped_domain_alias_address gda ON gda.username = mailbox.username
|
||||||
|
LEFT OUTER JOIN grouped_sender_acl_external external_acl ON external_acl.username = mailbox.username
|
||||||
|
WHERE
|
||||||
|
mailbox.active = '1'";
|
||||||
|
|
||||||
|
if ($mailbox_exists) {
|
||||||
|
$query .= " AND mailbox.username = :mailbox";
|
||||||
|
$stmt = $pdo->prepare($query);
|
||||||
|
$stmt->execute(array(':mailbox' => $mailbox));
|
||||||
|
} else {
|
||||||
|
$query .= " GROUP BY mailbox.username";
|
||||||
|
$stmt = $pdo->query($query);
|
||||||
|
}
|
||||||
|
|
||||||
|
$stmt = $pdo->query("DELETE FROM _sogo_static_view WHERE `c_uid` NOT IN (SELECT `username` FROM `mailbox` WHERE `active` = '1');");
|
||||||
|
|
||||||
flush_memcached();
|
flush_memcached();
|
||||||
}
|
}
|
||||||
function edit_user_account($_data) {
|
function edit_user_account($_data) {
|
||||||
|
|
|
@ -1264,11 +1264,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||||
));
|
));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_sogo_static_view($username);
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
'msg' => array('mailbox_added', htmlspecialchars($username))
|
'msg' => array('mailbox_added', htmlspecialchars($username))
|
||||||
);
|
);
|
||||||
|
return true;
|
||||||
break;
|
break;
|
||||||
case 'resource':
|
case 'resource':
|
||||||
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
$domain = idn_to_ascii(strtolower(trim($_data['domain'])), 0, INTL_IDNA_VARIANT_UTS46);
|
||||||
|
@ -3130,7 +3132,10 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
'msg' => array('mailbox_modified', $username)
|
'msg' => array('mailbox_modified', $username)
|
||||||
);
|
);
|
||||||
|
|
||||||
|
update_sogo_static_view($username);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
break;
|
break;
|
||||||
case 'mailbox_templates':
|
case 'mailbox_templates':
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
@ -5053,12 +5058,15 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||||
);
|
);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
update_sogo_static_view($username);
|
||||||
$_SESSION['return'][] = array(
|
$_SESSION['return'][] = array(
|
||||||
'type' => 'success',
|
'type' => 'success',
|
||||||
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
|
||||||
'msg' => array('mailbox_removed', htmlspecialchars($username))
|
'msg' => array('mailbox_removed', htmlspecialchars($username))
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
return true;
|
||||||
break;
|
break;
|
||||||
case 'mailbox_templates':
|
case 'mailbox_templates':
|
||||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||||
|
@ -5264,7 +5272,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'mailbox', 'resource')) && getenv('SKIP_SOGO') != "y") {
|
if ($_action != 'get' && in_array($_type, array('domain', 'alias', 'alias_domain', 'resource')) && getenv('SKIP_SOGO') != "y") {
|
||||||
update_sogo_static_view();
|
update_sogo_static_view();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -117,8 +117,8 @@ jQuery(function($){
|
||||||
data: 'tfa_active',
|
data: 'tfa_active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -126,8 +126,8 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -260,8 +260,8 @@ jQuery(function($){
|
||||||
data: 'tfa_active',
|
data: 'tfa_active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -269,8 +269,8 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -337,7 +337,7 @@ jQuery(function($){
|
||||||
data: 'keep_spam',
|
data: 'keep_spam',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function(data, type){
|
render: function(data, type){
|
||||||
return 'yes'==data?'<i class="bi bi-x-lg"></i>':'no'==data&&'<i class="bi bi-check-lg"></i>';
|
return 'yes'==data?'<i class="bi bi-x-lg"><span class="sorting-value">yes</span></i>':'no'==data&&'<i class="bi bi-check-lg"><span class="sorting-value">no</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -414,8 +414,8 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -492,8 +492,8 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
if(data == 1) return '<i class="bi bi-check-lg"></i>';
|
if(data == 1) return '<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>';
|
||||||
else return '<i class="bi bi-x-lg"></i>';
|
else return '<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -607,7 +607,7 @@ jQuery(function($){
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 6,
|
responsivePriority: 6,
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -754,7 +754,7 @@ jQuery(function($){
|
||||||
data: 'attributes.gal',
|
data: 'attributes.gal',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -762,7 +762,7 @@ jQuery(function($){
|
||||||
data: 'attributes.backupmx',
|
data: 'attributes.backupmx',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -770,7 +770,7 @@ jQuery(function($){
|
||||||
data: 'attributes.relay_all_recipients',
|
data: 'attributes.relay_all_recipients',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -778,7 +778,7 @@ jQuery(function($){
|
||||||
data: 'attributes.relay_unknown_only',
|
data: 'attributes.relay_unknown_only',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -787,7 +787,7 @@ jQuery(function($){
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 4,
|
responsivePriority: 4,
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1093,7 +1093,7 @@ jQuery(function($){
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 4,
|
responsivePriority: 4,
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1164,13 +1164,13 @@ jQuery(function($){
|
||||||
|
|
||||||
item.attributes.quota = humanFileSize(item.attributes.quota);
|
item.attributes.quota = humanFileSize(item.attributes.quota);
|
||||||
|
|
||||||
item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
|
item.attributes.tls_enforce_in = '<i class="text-' + (item.attributes.tls_enforce_in == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_in == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"></i>';
|
item.attributes.tls_enforce_out = '<i class="text-' + (item.attributes.tls_enforce_out == 1 ? 'success bi bi-lock-fill' : 'danger bi bi-unlock-fill') + '"><span class="sorting-value">' + (item.attributes.tls_enforce_out == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
item.attributes.pop3_access = '<i class="text-' + (item.attributes.pop3_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.pop3_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.pop3_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
item.attributes.imap_access = '<i class="text-' + (item.attributes.imap_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.imap_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.imap_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
item.attributes.smtp_access = '<i class="text-' + (item.attributes.smtp_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.smtp_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.smtp_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
item.attributes.sieve_access = '<i class="text-' + (item.attributes.sieve_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sieve_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sieve_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"></i>';
|
item.attributes.sogo_access = '<i class="text-' + (item.attributes.sogo_access == 1 ? 'success' : 'danger') + ' bi bi-' + (item.attributes.sogo_access == 1 ? 'check-lg' : 'x-lg') + '"><span class="sorting-value">' + (item.attributes.sogo_access == 1 ? '1' : '0') + '</span></i>';
|
||||||
if (item.attributes.quarantine_notification === 'never') {
|
if (item.attributes.quarantine_notification === 'never') {
|
||||||
item.attributes.quarantine_notification = lang.never;
|
item.attributes.quarantine_notification = lang.never;
|
||||||
} else if (item.attributes.quarantine_notification === 'hourly') {
|
} else if (item.attributes.quarantine_notification === 'hourly') {
|
||||||
|
@ -1188,7 +1188,6 @@ jQuery(function($){
|
||||||
item.attributes.quarantine_category = lang.q_all;
|
item.attributes.quarantine_category = lang.q_all;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if (item.template.toLowerCase() == "default"){
|
if (item.template.toLowerCase() == "default"){
|
||||||
item.action = '<div class="btn-group">' +
|
item.action = '<div class="btn-group">' +
|
||||||
'<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
'<a href="/edit/template/' + encodeURIComponent(item.id) + '" class="btn btn-xs btn-xs-half btn-secondary"><i class="bi bi-pencil-fill"></i> ' + lang.edit + '</a>' +
|
||||||
|
@ -1329,7 +1328,7 @@ jQuery(function($){
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 4,
|
responsivePriority: 4,
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1440,7 +1439,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1578,7 +1577,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':(0==data?'<i class="bi bi-x-lg"></i>':2==data&&'—');
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':(0==data?'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>':2==data&&'—');
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1675,7 +1674,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1782,7 +1781,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1917,7 +1916,7 @@ jQuery(function($){
|
||||||
data: 'sogo_visible',
|
data: 'sogo_visible',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function(data, type){
|
render: function(data, type){
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1936,7 +1935,7 @@ jQuery(function($){
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
responsivePriority: 6,
|
responsivePriority: 6,
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -1952,6 +1951,10 @@ jQuery(function($){
|
||||||
table.on('responsive-resize', function (e, datatable, columns){
|
table.on('responsive-resize', function (e, datatable, columns){
|
||||||
hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
|
hideTableExpandCollapseBtn('#tab-mbox-aliases', '#alias_table');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
table.on( 'draw', function (){
|
||||||
|
$('#alias_table [data-bs-toggle="tooltip"]').tooltip();
|
||||||
|
});
|
||||||
}
|
}
|
||||||
function draw_aliasdomain_table() {
|
function draw_aliasdomain_table() {
|
||||||
// just recalc width if instance already exists
|
// just recalc width if instance already exists
|
||||||
|
@ -2031,7 +2034,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
@ -2167,7 +2170,7 @@ jQuery(function($){
|
||||||
data: 'active',
|
data: 'active',
|
||||||
defaultContent: '',
|
defaultContent: '',
|
||||||
render: function (data, type) {
|
render: function (data, type) {
|
||||||
return 1==data?'<i class="bi bi-check-lg"></i>':0==data&&'<i class="bi bi-x-lg"></i>';
|
return 1==data?'<i class="bi bi-check-lg"><span class="sorting-value">1</span></i>':0==data&&'<i class="bi bi-x-lg"><span class="sorting-value">0</span></i>';
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
|
|
|
@ -105,7 +105,8 @@
|
||||||
"timeout2": "Časový limit pro připojení k lokálnímu serveru",
|
"timeout2": "Časový limit pro připojení k lokálnímu serveru",
|
||||||
"username": "Uživatelské jméno",
|
"username": "Uživatelské jméno",
|
||||||
"validate": "Ověřit",
|
"validate": "Ověřit",
|
||||||
"validation_success": "Úspěšně ověřeno"
|
"validation_success": "Úspěšně ověřeno",
|
||||||
|
"tags": "Štítky"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "Přístupy",
|
"access": "Přístupy",
|
||||||
|
@ -333,7 +334,11 @@
|
||||||
"username": "Uživatelské jméno",
|
"username": "Uživatelské jméno",
|
||||||
"validate_license_now": "Ověřit GUID na licenčním serveru",
|
"validate_license_now": "Ověřit GUID na licenčním serveru",
|
||||||
"verify": "Ověřit",
|
"verify": "Ověřit",
|
||||||
"yes": "✓"
|
"yes": "✓",
|
||||||
|
"f2b_ban_time_increment": "Délka banu je prodlužována s každým dalším banem",
|
||||||
|
"f2b_max_ban_time": "Maximální délka banu (s)",
|
||||||
|
"ip_check": "Kontrola IP",
|
||||||
|
"ip_check_disabled": "Kontrola IP je vypnuta. Můžete ji zapnout v <br> <strong>System > Nastavení > Options > Přizpůsobení</strong>"
|
||||||
},
|
},
|
||||||
"danger": {
|
"danger": {
|
||||||
"access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
|
"access_denied": "Přístup odepřen nebo jsou neplatná data ve formuláři",
|
||||||
|
|
|
@ -1048,7 +1048,7 @@
|
||||||
"spamfilter_table_empty": "Intet data at vise",
|
"spamfilter_table_empty": "Intet data at vise",
|
||||||
"spamfilter_table_remove": "slet",
|
"spamfilter_table_remove": "slet",
|
||||||
"spamfilter_table_rule": "Regl",
|
"spamfilter_table_rule": "Regl",
|
||||||
"spamfilter_wl": "Hvisliste",
|
"spamfilter_wl": "Hvidliste",
|
||||||
"spamfilter_wl_desc": "Hvidlistede e-mail-adresser til <b>aldrig</b> at klassificeres som spam. Wildcards kan bruges. Et filter anvendes kun på direkte aliaser (aliaser med en enkelt målpostkasse) eksklusive catch-aliaser og selve en postkasse.",
|
"spamfilter_wl_desc": "Hvidlistede e-mail-adresser til <b>aldrig</b> at klassificeres som spam. Wildcards kan bruges. Et filter anvendes kun på direkte aliaser (aliaser med en enkelt målpostkasse) eksklusive catch-aliaser og selve en postkasse.",
|
||||||
"spamfilter_yellow": "Gul: denne besked kan være spam, vil blive tagget som spam og flyttes til din junk-mappe",
|
"spamfilter_yellow": "Gul: denne besked kan være spam, vil blive tagget som spam og flyttes til din junk-mappe",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
|
|
|
@ -175,10 +175,12 @@
|
||||||
"empty": "Keine Einträge vorhanden",
|
"empty": "Keine Einträge vorhanden",
|
||||||
"excludes": "Diese Empfänger ausschließen",
|
"excludes": "Diese Empfänger ausschließen",
|
||||||
"f2b_ban_time": "Bannzeit in Sekunden",
|
"f2b_ban_time": "Bannzeit in Sekunden",
|
||||||
|
"f2b_ban_time_increment": "Bannzeit erhöht sich mit jedem Bann",
|
||||||
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
"f2b_blacklist": "Blacklist für Netzwerke und Hosts",
|
||||||
"f2b_filter": "Regex-Filter",
|
"f2b_filter": "Regex-Filter",
|
||||||
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
"f2b_list_info": "Ein Host oder Netzwerk auf der Blacklist wird immer eine Whitelist-Einheit überwiegen. <b>Die Aktualisierung der Liste dauert einige Sekunden.</b>",
|
||||||
"f2b_max_attempts": "Max. Versuche",
|
"f2b_max_attempts": "Max. Versuche",
|
||||||
|
"f2b_max_ban_time": "Maximale Bannzeit in Sekunden",
|
||||||
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
"f2b_netban_ipv4": "Netzbereich für IPv4-Banns (8-32)",
|
||||||
"f2b_netban_ipv6": "Netzbereich für IPv6-Banns (8-128)",
|
"f2b_netban_ipv6": "Netzbereich für IPv6-Banns (8-128)",
|
||||||
"f2b_parameters": "Fail2ban-Parameter",
|
"f2b_parameters": "Fail2ban-Parameter",
|
||||||
|
|
|
@ -177,10 +177,12 @@
|
||||||
"empty": "No results",
|
"empty": "No results",
|
||||||
"excludes": "Excludes these recipients",
|
"excludes": "Excludes these recipients",
|
||||||
"f2b_ban_time": "Ban time (s)",
|
"f2b_ban_time": "Ban time (s)",
|
||||||
|
"f2b_ban_time_increment": "Ban time is incremented with each ban",
|
||||||
"f2b_blacklist": "Blacklisted networks/hosts",
|
"f2b_blacklist": "Blacklisted networks/hosts",
|
||||||
"f2b_filter": "Regex filters",
|
"f2b_filter": "Regex filters",
|
||||||
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
"f2b_list_info": "A blacklisted host or network will always outweigh a whitelist entity. <b>List updates will take a few seconds to be applied.</b>",
|
||||||
"f2b_max_attempts": "Max. attempts",
|
"f2b_max_attempts": "Max. attempts",
|
||||||
|
"f2b_max_ban_time": "Max. ban time (s)",
|
||||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||||
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
||||||
"f2b_parameters": "Fail2ban parameters",
|
"f2b_parameters": "Fail2ban parameters",
|
||||||
|
|
|
@ -141,9 +141,11 @@
|
||||||
"empty": "Sin resultados",
|
"empty": "Sin resultados",
|
||||||
"excludes": "Excluye a estos destinatarios",
|
"excludes": "Excluye a estos destinatarios",
|
||||||
"f2b_ban_time": "Tiempo de restricción (s)",
|
"f2b_ban_time": "Tiempo de restricción (s)",
|
||||||
|
"f2b_ban_time_increment": "Tiempo de restricción se incrementa con cada restricción",
|
||||||
"f2b_blacklist": "Redes y hosts en lista negra",
|
"f2b_blacklist": "Redes y hosts en lista negra",
|
||||||
"f2b_list_info": "Un host o red en lista negra siempre superará a una entidad de la lista blanca. <b>Las actualizaciones de la lista tardarán unos segundos en aplicarse.</b>",
|
"f2b_list_info": "Un host o red en lista negra siempre superará a una entidad de la lista blanca. <b>Las actualizaciones de la lista tardarán unos segundos en aplicarse.</b>",
|
||||||
"f2b_max_attempts": "Max num. de intentos",
|
"f2b_max_attempts": "Max num. de intentos",
|
||||||
|
"f2b_max_ban_time": "Max tiempo de restricción (s)",
|
||||||
"f2b_netban_ipv4": "Tamaño de subred IPv4 para aplicar la restricción (8-32)",
|
"f2b_netban_ipv4": "Tamaño de subred IPv4 para aplicar la restricción (8-32)",
|
||||||
"f2b_netban_ipv6": "Tamaño de subred IPv6 para aplicar la restricción (8-128)",
|
"f2b_netban_ipv6": "Tamaño de subred IPv6 para aplicar la restricción (8-128)",
|
||||||
"f2b_parameters": "Parametros Fail2ban",
|
"f2b_parameters": "Parametros Fail2ban",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"spam_policy": "Liste Noire/Liste Blanche",
|
"spam_policy": "Liste Noire/Liste Blanche",
|
||||||
"spam_score": "Score SPAM",
|
"spam_score": "Score SPAM",
|
||||||
"syncjobs": "Tâches de synchronisation",
|
"syncjobs": "Tâches de synchronisation",
|
||||||
"tls_policy": "Police TLS",
|
"tls_policy": "Politique TLS",
|
||||||
"unlimited_quota": "Quota illimité pour les boites de courriel",
|
"unlimited_quota": "Quota illimité pour les boites de courriel",
|
||||||
"domain_desc": "Modifier la description du domaine",
|
"domain_desc": "Modifier la description du domaine",
|
||||||
"domain_relayhost": "Changer le relais pour un domaine",
|
"domain_relayhost": "Changer le relais pour un domaine",
|
||||||
|
@ -106,7 +106,8 @@
|
||||||
"validate": "Valider",
|
"validate": "Valider",
|
||||||
"validation_success": "Validation réussie",
|
"validation_success": "Validation réussie",
|
||||||
"bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.<br>Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.",
|
"bcc_dest_format": "La destination Cci doit être une seule adresse e-mail valide.<br>Si vous avez besoin d'envoyer une copie à plusieurs adresses, créez un alias et utilisez-le ici.",
|
||||||
"tags": "Etiquettes"
|
"tags": "Etiquettes",
|
||||||
|
"app_passwd_protocols": "Protocoles autorisés pour le mot de passe de l'application"
|
||||||
},
|
},
|
||||||
"admin": {
|
"admin": {
|
||||||
"access": "Accès",
|
"access": "Accès",
|
||||||
|
@ -171,11 +172,13 @@
|
||||||
"edit": "Editer",
|
"edit": "Editer",
|
||||||
"empty": "Aucun résultat",
|
"empty": "Aucun résultat",
|
||||||
"excludes": "Exclure ces destinataires",
|
"excludes": "Exclure ces destinataires",
|
||||||
"f2b_ban_time": "Durée du bannissement(s)",
|
"f2b_ban_time": "Durée du bannissement (s)",
|
||||||
|
"f2b_ban_time_increment": "Durée du bannissement est augmentée à chaque bannissement",
|
||||||
"f2b_blacklist": "Réseaux/Domaines sur Liste Noire",
|
"f2b_blacklist": "Réseaux/Domaines sur Liste Noire",
|
||||||
"f2b_filter": "Filtre(s) Regex",
|
"f2b_filter": "Filtre(s) Regex",
|
||||||
"f2b_list_info": "Un hôte ou un réseau sur liste noire l'emportera toujours sur une entité de liste blanche. <b>L'application des mises à jour de liste prendra quelques secondes.</b>",
|
"f2b_list_info": "Un hôte ou un réseau sur liste noire l'emportera toujours sur une entité de liste blanche. <b>L'application des mises à jour de liste prendra quelques secondes.</b>",
|
||||||
"f2b_max_attempts": "Nb max. de tentatives",
|
"f2b_max_attempts": "Nb max. de tentatives",
|
||||||
|
"f2b_max_ban_time": "Max. durée du bannissement (s)",
|
||||||
"f2b_netban_ipv4": "Taille du sous-réseau IPv4 pour l'application du bannissement (8-32)",
|
"f2b_netban_ipv4": "Taille du sous-réseau IPv4 pour l'application du bannissement (8-32)",
|
||||||
"f2b_netban_ipv6": "Taille du sous-réseau IPv6 pour l'application du bannissement (8-128)",
|
"f2b_netban_ipv6": "Taille du sous-réseau IPv6 pour l'application du bannissement (8-128)",
|
||||||
"f2b_parameters": "Paramètres Fail2ban",
|
"f2b_parameters": "Paramètres Fail2ban",
|
||||||
|
@ -585,7 +588,7 @@
|
||||||
"unchanged_if_empty": "Si non modifié, laisser en blanc",
|
"unchanged_if_empty": "Si non modifié, laisser en blanc",
|
||||||
"username": "Nom d'utilisateur",
|
"username": "Nom d'utilisateur",
|
||||||
"validate_save": "Valider et sauver",
|
"validate_save": "Valider et sauver",
|
||||||
"lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (<code>.*google\\.com</code> pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut).",
|
"lookup_mx": "La destination est une expression régulière qui doit correspondre avec le nom du MX (<code>.*google\\.com</code> pour acheminer tout le courrier destiné à un MX se terminant par google.com via ce saut)",
|
||||||
"mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine."
|
"mailbox_relayhost_info": "S'applique uniquement à la boîte aux lettres et aux alias directs, remplace le relayhost du domaine."
|
||||||
},
|
},
|
||||||
"footer": {
|
"footer": {
|
||||||
|
@ -1088,9 +1091,12 @@
|
||||||
"username": "Nom d'utilisateur",
|
"username": "Nom d'utilisateur",
|
||||||
"verify": "Vérification",
|
"verify": "Vérification",
|
||||||
"waiting": "En attente",
|
"waiting": "En attente",
|
||||||
"week": "Semaine",
|
"week": "semaine",
|
||||||
"weekly": "Hebdomadaire",
|
"weekly": "Hebdomadaire",
|
||||||
"weeks": "semaines"
|
"weeks": "semaines",
|
||||||
|
"months": "mois",
|
||||||
|
"year": "année",
|
||||||
|
"years": "années"
|
||||||
},
|
},
|
||||||
"warning": {
|
"warning": {
|
||||||
"cannot_delete_self": "Impossible de supprimer l’utilisateur connecté",
|
"cannot_delete_self": "Impossible de supprimer l’utilisateur connecté",
|
||||||
|
|
|
@ -175,10 +175,12 @@
|
||||||
"empty": "Nessun risultato",
|
"empty": "Nessun risultato",
|
||||||
"excludes": "Esclude questi destinatari",
|
"excludes": "Esclude questi destinatari",
|
||||||
"f2b_ban_time": "Tempo di blocco (s)",
|
"f2b_ban_time": "Tempo di blocco (s)",
|
||||||
|
"f2b_ban_time_increment": "Tempo di blocco aumenta ad ogni blocco",
|
||||||
"f2b_blacklist": "Host/reti in blacklist",
|
"f2b_blacklist": "Host/reti in blacklist",
|
||||||
"f2b_filter": "Filtri Regex",
|
"f2b_filter": "Filtri Regex",
|
||||||
"f2b_list_info": "Un host oppure una rete in blacklist, avrà sempre un peso maggiore rispetto ad una in whitelist. <b>L'aggiornamento della lista richiede alcuni secondi per la sua entrata in azione.</b>",
|
"f2b_list_info": "Un host oppure una rete in blacklist, avrà sempre un peso maggiore rispetto ad una in whitelist. <b>L'aggiornamento della lista richiede alcuni secondi per la sua entrata in azione.</b>",
|
||||||
"f2b_max_attempts": "Tentativi massimi",
|
"f2b_max_attempts": "Tentativi massimi",
|
||||||
|
"f2b_max_ban_time": "Tempo massimo di blocco (s)",
|
||||||
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
"f2b_netban_ipv4": "IPv4 subnet size to apply ban on (8-32)",
|
||||||
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
"f2b_netban_ipv6": "IPv6 subnet size to apply ban on (8-128)",
|
||||||
"f2b_parameters": "Parametri Fail2ban",
|
"f2b_parameters": "Parametri Fail2ban",
|
||||||
|
|
|
@ -168,10 +168,12 @@
|
||||||
"empty": "Geen resultaten",
|
"empty": "Geen resultaten",
|
||||||
"excludes": "Exclusief",
|
"excludes": "Exclusief",
|
||||||
"f2b_ban_time": "Verbanningstijd (s)",
|
"f2b_ban_time": "Verbanningstijd (s)",
|
||||||
|
"f2b_ban_time_increment": "Verbanningstijd wordt verhoogd met elk verbanning",
|
||||||
"f2b_blacklist": "Netwerken/hosts op de blacklist",
|
"f2b_blacklist": "Netwerken/hosts op de blacklist",
|
||||||
"f2b_filter": "Regex-filters",
|
"f2b_filter": "Regex-filters",
|
||||||
"f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. <b>Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.</b>",
|
"f2b_list_info": "Een host of netwerk op de blacklist staat altijd boven eenzelfde op de whitelist. <b>Het doorvoeren van wijzigingen kan enkele seconden in beslag nemen.</b>",
|
||||||
"f2b_max_attempts": "Maximaal aantal pogingen",
|
"f2b_max_attempts": "Maximaal aantal pogingen",
|
||||||
|
"f2b_max_ban_time": "Maximaal verbanningstijd (s)",
|
||||||
"f2b_netban_ipv4": "Voer de IPv4-subnetgrootte in waar de verbanning van kracht moet zijn (8-32)",
|
"f2b_netban_ipv4": "Voer de IPv4-subnetgrootte in waar de verbanning van kracht moet zijn (8-32)",
|
||||||
"f2b_netban_ipv6": "Voer de IPv6-subnetgrootte in waar de verbanning van kracht moet zijn (8-128)",
|
"f2b_netban_ipv6": "Voer de IPv6-subnetgrootte in waar de verbanning van kracht moet zijn (8-128)",
|
||||||
"f2b_parameters": "Fail2ban",
|
"f2b_parameters": "Fail2ban",
|
||||||
|
|
|
@ -60,7 +60,7 @@ elseif (isset($_GET['login'])) {
|
||||||
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
|
':remote_addr' => ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR'])
|
||||||
));
|
));
|
||||||
// redirect to sogo (sogo will get the correct credentials via nginx auth_request
|
// redirect to sogo (sogo will get the correct credentials via nginx auth_request
|
||||||
header("Location: /SOGo/so/${login}");
|
header("Location: /SOGo/so/{$login}");
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,14 @@
|
||||||
<label for="f2b_ban_time">{{ lang.admin.f2b_ban_time }}:</label>
|
<label for="f2b_ban_time">{{ lang.admin.f2b_ban_time }}:</label>
|
||||||
<input type="number" class="form-control" id="f2b_ban_time" name="ban_time" value="{{ f2b_data.ban_time }}" required>
|
<input type="number" class="form-control" id="f2b_ban_time" name="ban_time" value="{{ f2b_data.ban_time }}" required>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<label for="f2b_max_ban_time">{{ lang.admin.f2b_max_ban_time }}:</label>
|
||||||
|
<input type="number" class="form-control" id="f2b_max_ban_time" name="max_ban_time" value="{{ f2b_data.max_ban_time }}" required>
|
||||||
|
</div>
|
||||||
|
<div class="mb-4">
|
||||||
|
<input class="form-check-input" type="checkbox" value="1" name="ban_time_increment" id="f2b_ban_time_increment" {% if f2b_data.ban_time_increment == 1 %}checked{% endif %}>
|
||||||
|
<label class="form-check-label" for="f2b_ban_time_increment">{{ lang.admin.f2b_ban_time_increment }}</label>
|
||||||
|
</div>
|
||||||
<div class="mb-4">
|
<div class="mb-4">
|
||||||
<label for="f2b_max_attempts">{{ lang.admin.f2b_max_attempts }}:</label>
|
<label for="f2b_max_attempts">{{ lang.admin.f2b_max_attempts }}:</label>
|
||||||
<input type="number" class="form-control" id="f2b_max_attempts" name="max_attempts" value="{{ f2b_data.max_attempts }}" required>
|
<input type="number" class="form-control" id="f2b_max_attempts" name="max_attempts" value="{{ f2b_data.max_attempts }}" required>
|
||||||
|
|
|
@ -109,25 +109,25 @@
|
||||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label>
|
<label class="control-label col-sm-2">{{ lang.user.quarantine_notification }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
|
@ -141,19 +141,19 @@
|
||||||
<label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label>
|
<label class="control-label col-sm-2">{{ lang.user.quarantine_category }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
data-api-url='edit/quarantine_category'
|
data-api-url='edit/quarantine_category'
|
||||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
data-api-url='edit/quarantine_category'
|
data-api-url='edit/quarantine_category'
|
||||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
|
@ -167,13 +167,13 @@
|
||||||
<label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
|
<label class="control-label col-sm-2" for="sender_acl">{{ lang.user.tls_policy }}</label>
|
||||||
<div class="col-sm-10">
|
<div class="col-sm-10">
|
||||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="tls_policy"
|
data-id="tls_policy"
|
||||||
data-api-url='edit/tls_policy'
|
data-api-url='edit/tls_policy'
|
||||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailbox }}"
|
data-item="{{ mailbox }}"
|
||||||
data-id="tls_policy"
|
data-id="tls_policy"
|
||||||
|
|
|
@ -54,6 +54,7 @@
|
||||||
<li class="dropdown-header">SMTP</li>
|
<li class="dropdown-header">SMTP</li>
|
||||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"smtp_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||||
|
<li><hr class="dropdown-divider"></li>
|
||||||
<li class="dropdown-header">Sieve</li>
|
<li class="dropdown-header">Sieve</li>
|
||||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":1}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
<li><a class="dropdown-item" data-action="edit_selected" data-id="mailbox" data-api-url='edit/mailbox' data-api-attr='{"sieve_access":0}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||||
|
|
|
@ -12,19 +12,19 @@
|
||||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tag_handling }}:</div>
|
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tag_handling }}:</div>
|
||||||
<div class="col-sm-9 col-12">
|
<div class="col-sm-9 col-12">
|
||||||
<div class="btn-group" data-acl="{{ acl.delimiter_action }}">
|
<div class="btn-group" data-acl="{{ acl.delimiter_action }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subfolder' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subfolder' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="delimiter_action"
|
data-id="delimiter_action"
|
||||||
data-api-url='edit/delimiter_action'
|
data-api-url='edit/delimiter_action'
|
||||||
data-api-attr='{"tagged_mail_handler":"subfolder"}'>{{ lang.user.tag_in_subfolder }}</button>
|
data-api-attr='{"tagged_mail_handler":"subfolder"}'>{{ lang.user.tag_in_subfolder }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'subject' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'subject' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="delimiter_action"
|
data-id="delimiter_action"
|
||||||
data-api-url='edit/delimiter_action'
|
data-api-url='edit/delimiter_action'
|
||||||
data-api-attr='{"tagged_mail_handler":"subject"}'>{{ lang.user.tag_in_subject }}</button>
|
data-api-attr='{"tagged_mail_handler":"subject"}'>{{ lang.user.tag_in_subject }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if get_tagging_options == 'none' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if get_tagging_options == 'none' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="delimiter_action"
|
data-id="delimiter_action"
|
||||||
|
@ -40,13 +40,13 @@
|
||||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tls_policy }}:</div>
|
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.tls_policy }}:</div>
|
||||||
<div class="col-sm-9 col-12">
|
<div class="col-sm-9 col-12">
|
||||||
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
<div class="btn-group" data-acl="{{ acl.tls_policy }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_in == '1' %} active"{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_in == '1' %} btn-dark"{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="tls_policy"
|
data-id="tls_policy"
|
||||||
data-api-url='edit/tls_policy'
|
data-api-url='edit/tls_policy'
|
||||||
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
data-api-attr='{"tls_enforce_in": {% if get_tls_policy.tls_enforce_in == '1' %}0{% else %}1{% endif %} }'>{{ lang.user.tls_enforce_in }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary{% if get_tls_policy.tls_enforce_out == '1' %} active"{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-half d-block d-sm-inline btn-light{% if get_tls_policy.tls_enforce_out == '1' %} btn-dark"{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="tls_policy"
|
data-id="tls_policy"
|
||||||
|
@ -61,25 +61,25 @@
|
||||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_notification }}:</div>
|
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_notification }}:</div>
|
||||||
<div class="col-sm-9 col-12">
|
<div class="col-sm-9 col-12">
|
||||||
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
<div class="btn-group" data-acl="{{ acl.quarantine_notification }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'never' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'never' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
data-api-attr='{"quarantine_notification":"never"}'>{{ lang.user.never }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'hourly' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'hourly' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
data-api-attr='{"quarantine_notification":"hourly"}'>{{ lang.user.hourly }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'daily' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'daily' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
data-api-url='edit/quarantine_notification'
|
data-api-url='edit/quarantine_notification'
|
||||||
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
data-api-attr='{"quarantine_notification":"daily"}'>{{ lang.user.daily }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-secondary{% if quarantine_notification == 'weekly' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light{% if quarantine_notification == 'weekly' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_notification"
|
data-id="quarantine_notification"
|
||||||
|
@ -93,19 +93,19 @@
|
||||||
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_category }}:</div>
|
<div class="col-sm-3 col-12 text-sm-end text-start text-xs-bold mb-4">{{ lang.user.quarantine_category }}:</div>
|
||||||
<div class="col-sm-9 col-12">
|
<div class="col-sm-9 col-12">
|
||||||
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
<div class="btn-group" data-acl="{{ acl.quarantine_category }}">
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'reject' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'reject' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
data-api-url='edit/quarantine_category'
|
data-api-url='edit/quarantine_category'
|
||||||
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
data-api-attr='{"quarantine_category":"reject"}'>{{ lang.user.q_reject }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'add_header' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'add_header' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
data-api-url='edit/quarantine_category'
|
data-api-url='edit/quarantine_category'
|
||||||
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
data-api-attr='{"quarantine_category":"add_header"}'>{{ lang.user.q_add_header }}</button>
|
||||||
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-secondary{% if quarantine_category == 'all' %} active{% endif %}"
|
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline btn-light{% if quarantine_category == 'all' %} btn-dark{% endif %}"
|
||||||
data-action="edit_selected"
|
data-action="edit_selected"
|
||||||
data-item="{{ mailcow_cc_username }}"
|
data-item="{{ mailcow_cc_username }}"
|
||||||
data-id="quarantine_category"
|
data-id="quarantine_category"
|
||||||
|
|
|
@ -106,7 +106,7 @@ services:
|
||||||
- rspamd
|
- rspamd
|
||||||
|
|
||||||
php-fpm-mailcow:
|
php-fpm-mailcow:
|
||||||
image: mailcow/phpfpm:1.82
|
image: mailcow/phpfpm:1.83
|
||||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||||
depends_on:
|
depends_on:
|
||||||
- redis-mailcow
|
- redis-mailcow
|
||||||
|
@ -169,7 +169,7 @@ services:
|
||||||
- phpfpm
|
- phpfpm
|
||||||
|
|
||||||
sogo-mailcow:
|
sogo-mailcow:
|
||||||
image: mailcow/sogo:1.115
|
image: mailcow/sogo:1.117
|
||||||
environment:
|
environment:
|
||||||
- DBNAME=${DBNAME}
|
- DBNAME=${DBNAME}
|
||||||
- DBUSER=${DBUSER}
|
- DBUSER=${DBUSER}
|
||||||
|
@ -425,7 +425,7 @@ services:
|
||||||
- acme
|
- acme
|
||||||
|
|
||||||
netfilter-mailcow:
|
netfilter-mailcow:
|
||||||
image: mailcow/netfilter:1.51
|
image: mailcow/netfilter:1.52
|
||||||
stop_grace_period: 30s
|
stop_grace_period: 30s
|
||||||
depends_on:
|
depends_on:
|
||||||
- dovecot-mailcow
|
- dovecot-mailcow
|
||||||
|
@ -510,7 +510,7 @@ services:
|
||||||
- watchdog
|
- watchdog
|
||||||
|
|
||||||
dockerapi-mailcow:
|
dockerapi-mailcow:
|
||||||
image: mailcow/dockerapi:2.01
|
image: mailcow/dockerapi:2.03
|
||||||
security_opt:
|
security_opt:
|
||||||
- label=disable
|
- label=disable
|
||||||
restart: always
|
restart: always
|
||||||
|
|
|
@ -205,8 +205,8 @@ DBUSER=mailcow
|
||||||
|
|
||||||
# Please use long, random alphanumeric strings (A-Za-z0-9)
|
# Please use long, random alphanumeric strings (A-Za-z0-9)
|
||||||
|
|
||||||
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
DBPASS=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||||
DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
DBROOT=$(LC_ALL=C </dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||||
|
|
||||||
# ------------------------------
|
# ------------------------------
|
||||||
# HTTP/S Bindings
|
# HTTP/S Bindings
|
||||||
|
@ -261,7 +261,7 @@ COMPOSE_PROJECT_NAME=mailcowdockerized
|
||||||
# Switch here between native (compose plugin) and standalone
|
# Switch here between native (compose plugin) and standalone
|
||||||
# For more informations take a look at the mailcow docs regarding the configuration options.
|
# For more informations take a look at the mailcow docs regarding the configuration options.
|
||||||
# Normally this should be untouched but if you decided to use either of those you can switch it manually here.
|
# Normally this should be untouched but if you decided to use either of those you can switch it manually here.
|
||||||
# Please be aware that at least one of those variants should be installed on your maschine or mailcow will fail.
|
# Please be aware that at least one of those variants should be installed on your machine or mailcow will fail.
|
||||||
|
|
||||||
DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
|
DOCKER_COMPOSE_VERSION=${COMPOSE_VERSION}
|
||||||
|
|
||||||
|
|
|
@ -19,7 +19,7 @@ read -r -p "Are you sure you want to reset the mailcow administrator account? [y
|
||||||
response=${response,,} # tolower
|
response=${response,,} # tolower
|
||||||
if [[ "$response" =~ ^(yes|y)$ ]]; then
|
if [[ "$response" =~ ^(yes|y)$ ]]; then
|
||||||
echo -e "\nWorking, please wait..."
|
echo -e "\nWorking, please wait..."
|
||||||
random=$(</dev/urandom tr -dc _A-Z-a-z-0-9 | head -c${1:-16})
|
random=$(</dev/urandom tr -dc _A-Z-a-z-0-9 2> /dev/null | head -c${1:-16})
|
||||||
password=$(docker exec -it $(docker ps -qf name=dovecot-mailcow) doveadm pw -s SSHA256 -p ${random} | tr -d '\r')
|
password=$(docker exec -it $(docker ps -qf name=dovecot-mailcow) doveadm pw -s SSHA256 -p ${random} | tr -d '\r')
|
||||||
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';"
|
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM admin WHERE username='admin';"
|
||||||
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';"
|
docker exec -it $(docker ps -qf name=mysql-mailcow) mysql -u${DBUSER} -p${DBPASS} ${DBNAME} -e "DELETE FROM domain_admins WHERE username='admin';"
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
# renovate: datasource=github-releases depName=nextcloud/server versioning=semver extractVersion=^v(?<version>.*)$
|
||||||
NEXTCLOUD_VERSION=25.0.4
|
NEXTCLOUD_VERSION=26.0.1
|
||||||
|
|
||||||
echo -ne "Checking prerequisites..."
|
echo -ne "Checking prerequisites..."
|
||||||
sleep 1
|
sleep 1
|
||||||
|
@ -97,8 +97,12 @@ elif [[ ${NC_UPDATE} == "y" ]]; then
|
||||||
echo -e "\033[31mError: Nextcloud occ not found. Is Nextcloud installed?\033[0m"
|
echo -e "\033[31mError: Nextcloud occ not found. Is Nextcloud installed?\033[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
if ! grep -q 'installed: true' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
if grep -Pq 'This version of Nextcloud is not compatible with (?:PHP)?(?>=?)(?:PHP)?(?>.+)' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
||||||
echo "Nextcloud seems not to be installed."
|
echo -e "\033[31mError: This version of Nextcloud is not compatible with the current PHP version of php-fpm-mailcow, we'll fix it\033[0m"
|
||||||
|
wget -q https://raw.githubusercontent.com/nextcloud/server/v26.0.0/lib/versioncheck.php -O ./data/web/nextcloud/lib/versioncheck.php
|
||||||
|
echo -e "\e[33mPlease restart the update again.\e[0m"
|
||||||
|
elif ! grep -q 'installed: true' <<<$(docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "/web/nextcloud/occ --no-warnings status"); then
|
||||||
|
echo -e "\033[31mError: Nextcloud seems not to be installed.\033[0m"
|
||||||
exit 1
|
exit 1
|
||||||
else
|
else
|
||||||
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar"
|
docker exec -it -u www-data $(docker ps -f name=php-fpm-mailcow -q) bash -c "php /web/nextcloud/updater/updater.phar"
|
||||||
|
@ -122,7 +126,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
||||||
&& chmod +x ./data/web/nextcloud/occ
|
&& chmod +x ./data/web/nextcloud/occ
|
||||||
|
|
||||||
echo -e "\033[33mCreating 'nextcloud' database...\033[0m"
|
echo -e "\033[33mCreating 'nextcloud' database...\033[0m"
|
||||||
NC_DBPASS=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
NC_DBPASS=$(</dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||||
NC_DBUSER=nextcloud
|
NC_DBUSER=nextcloud
|
||||||
NC_DBNAME=nextcloud
|
NC_DBNAME=nextcloud
|
||||||
|
|
||||||
|
@ -138,7 +142,7 @@ elif [[ ${NC_INSTALL} == "y" ]]; then
|
||||||
|
|
||||||
echo ""
|
echo ""
|
||||||
echo -e "\033[33mInstalling Nextcloud...\033[0m"
|
echo -e "\033[33mInstalling Nextcloud...\033[0m"
|
||||||
ADMIN_NC_PASS=$(</dev/urandom tr -dc A-Za-z0-9 | head -c 28)
|
ADMIN_NC_PASS=$(</dev/urandom tr -dc A-Za-z0-9 2> /dev/null | head -c 28)
|
||||||
|
|
||||||
echo -ne "[1/4] Setting correct permissions for www-data"
|
echo -ne "[1/4] Setting correct permissions for www-data"
|
||||||
docker exec -it $(docker ps -f name=php-fpm-mailcow -q) /bin/bash -c "chown -R www-data:www-data /web/nextcloud"
|
docker exec -it $(docker ps -f name=php-fpm-mailcow -q) /bin/bash -c "chown -R www-data:www-data /web/nextcloud"
|
||||||
|
|
77
update.sh
77
update.sh
|
@ -176,18 +176,19 @@ remove_obsolete_nginx_ports() {
|
||||||
}
|
}
|
||||||
|
|
||||||
detect_docker_compose_command(){
|
detect_docker_compose_command(){
|
||||||
if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
if ! [[ "${DOCKER_COMPOSE_VERSION}" =~ ^(native|standalone)$ ]]; then
|
||||||
if docker compose > /dev/null 2>&1; then
|
if docker compose > /dev/null 2>&1; then
|
||||||
if docker compose version --short | grep "2." > /dev/null 2>&1; then
|
if docker compose version --short | grep "2." > /dev/null 2>&1; then
|
||||||
DOCKER_COMPOSE_VERSION=native
|
DOCKER_COMPOSE_VERSION=native
|
||||||
COMPOSE_COMMAND="docker compose"
|
COMPOSE_COMMAND="docker compose"
|
||||||
echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m"
|
echo -e "\e[31mFound Docker Compose Plugin (native).\e[0m"
|
||||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m"
|
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to native\e[0m"
|
||||||
|
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf
|
||||||
sleep 2
|
sleep 2
|
||||||
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
echo -e "\e[33mNotice: You'll have to update this Compose Version via your Package Manager manually!\e[0m"
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||||
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
echo -e "\e[31mPlease update/install it manually regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
elif docker-compose > /dev/null 2>&1; then
|
elif docker-compose > /dev/null 2>&1; then
|
||||||
|
@ -197,26 +198,60 @@ if ! [ "${DOCKER_COMPOSE_VERSION}" == "native" ] && ! [ "${DOCKER_COMPOSE_VERSIO
|
||||||
COMPOSE_COMMAND="docker-compose"
|
COMPOSE_COMMAND="docker-compose"
|
||||||
echo -e "\e[31mFound Docker Compose Standalone.\e[0m"
|
echo -e "\e[31mFound Docker Compose Standalone.\e[0m"
|
||||||
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m"
|
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable to standalone\e[0m"
|
||||||
|
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf
|
||||||
sleep 2
|
sleep 2
|
||||||
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
|
echo -e "\e[33mNotice: For an automatic update of docker-compose please use the update_compose.sh scripts located at the helper-scripts folder.\e[0m"
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
echo -e "\e[31mCannot find Docker Compose with a Version Higher than 2.X.X.\e[0m"
|
||||||
echo -e "\e[31mPlease update/install regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
echo -e "\e[31mPlease update/install regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
else
|
else
|
||||||
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||||
echo -e "\e[31mPlease install it regarding to this doc site: https://mailcow.github.io/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||||
exit 1
|
exit 1
|
||||||
fi
|
fi
|
||||||
|
|
||||||
elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
|
elif [ "${DOCKER_COMPOSE_VERSION}" == "native" ]; then
|
||||||
COMPOSE_COMMAND="docker compose"
|
COMPOSE_COMMAND="docker compose"
|
||||||
|
# Check if Native Compose works and has not been deleted
|
||||||
|
if ! $COMPOSE_COMMAND > /dev/null 2>&1; then
|
||||||
|
# IF it not exists/work anymore try the other command
|
||||||
|
COMPOSE_COMMAND="docker-compose"
|
||||||
|
if ! $COMPOSE_COMMAND > /dev/null 2>&1 || ! $COMPOSE_COMMAND --version | grep "^2." > /dev/null 2>&1; then
|
||||||
|
# IF it cannot find Standalone in > 2.X, then script stops
|
||||||
|
echo -e "\e[31mCannot find Docker Compose or the Version is lower then 2.X.X.\e[0m"
|
||||||
|
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# If it finds the standalone Plugin it will use this instead and change the mailcow.conf Variable accordingly
|
||||||
|
echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m"
|
||||||
|
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from native to standalone\e[0m"
|
||||||
|
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=standalone/' $SCRIPT_DIR/mailcow.conf
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
|
|
||||||
|
|
||||||
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
elif [ "${DOCKER_COMPOSE_VERSION}" == "standalone" ]; then
|
||||||
COMPOSE_COMMAND="docker-compose"
|
COMPOSE_COMMAND="docker-compose"
|
||||||
|
# Check if Standalone Compose works and has not been deleted
|
||||||
|
if ! $COMPOSE_COMMAND > /dev/null 2>&1 && ! $COMPOSE_COMMAND --version > /dev/null 2>&1 | grep "^2." > /dev/null 2>&1; then
|
||||||
|
# IF it not exists/work anymore try the other command
|
||||||
|
COMPOSE_COMMAND="docker compose"
|
||||||
|
if ! $COMPOSE_COMMAND > /dev/null 2>&1; then
|
||||||
|
# IF it cannot find Native in > 2.X, then script stops
|
||||||
|
echo -e "\e[31mCannot find Docker Compose.\e[0m"
|
||||||
|
echo -e "\e[31mPlease install it regarding to this doc site: https://docs.mailcow.email/mailcow-dockerized-docs/i_u_m/i_u_m_install/\e[0m"
|
||||||
|
exit 1
|
||||||
|
fi
|
||||||
|
# If it finds the native Plugin it will use this instead and change the mailcow.conf Variable accordingly
|
||||||
|
echo -e "\e[31mFound different Docker Compose Version then declared in mailcow.conf!\e[0m"
|
||||||
|
echo -e "\e[31mSetting the DOCKER_COMPOSE_VERSION Variable from standalone to native\e[0m"
|
||||||
|
sed -i 's/^DOCKER_COMPOSE_VERSION=.*/DOCKER_COMPOSE_VERSION=native/' $SCRIPT_DIR/mailcow.conf
|
||||||
|
sleep 2
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -326,8 +361,12 @@ while (($#)); do
|
||||||
echo -e "\e[32mRunning in forced mode...\e[0m"
|
echo -e "\e[32mRunning in forced mode...\e[0m"
|
||||||
FORCE=y
|
FORCE=y
|
||||||
;;
|
;;
|
||||||
|
-d|--dev)
|
||||||
|
echo -e "\e[32mRunning in Developer mode...\e[0m"
|
||||||
|
DEV=y
|
||||||
|
;;
|
||||||
--help|-h)
|
--help|-h)
|
||||||
echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -h|--help]
|
echo './update.sh [-c|--check, --ours, --gc, --nightly, --prefetch, --skip-start, --skip-ping-check, --stable, -f|--force, -d|--dev, -h|--help]
|
||||||
|
|
||||||
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
|
-c|--check - Check for updates and exit (exit codes => 0: update available, 3: no updates)
|
||||||
--ours - Use merge strategy option "ours" to solve conflicts in favor of non-mailcow code (local changes over remote changes), not recommended!
|
--ours - Use merge strategy option "ours" to solve conflicts in favor of non-mailcow code (local changes over remote changes), not recommended!
|
||||||
|
@ -338,6 +377,7 @@ while (($#)); do
|
||||||
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you´ve blocked any ICMP Connections to your mailcow machine)
|
--skip-ping-check - Skip ICMP Check to public DNS resolvers (Use it only if you´ve blocked any ICMP Connections to your mailcow machine)
|
||||||
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly.
|
--stable - Switch your mailcow updates to the stable (master) branch. Default unless you changed it with --nightly.
|
||||||
-f|--force - Force update, do not ask questions
|
-f|--force - Force update, do not ask questions
|
||||||
|
-d|--dev - Enables Developer Mode (No Checkout of update.sh for tests)
|
||||||
'
|
'
|
||||||
exit 1
|
exit 1
|
||||||
esac
|
esac
|
||||||
|
@ -597,7 +637,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
||||||
echo "Adding new option \"${option}\" to mailcow.conf"
|
echo "Adding new option \"${option}\" to mailcow.conf"
|
||||||
echo '# Password hash algorithm' >> mailcow.conf
|
echo '# Password hash algorithm' >> mailcow.conf
|
||||||
echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf
|
echo '# Only certain password hash algorithm are supported. For a fully list of supported schemes,' >> mailcow.conf
|
||||||
echo '# see https://mailcow.github.io/mailcow-dockerized-docs/models/model-passwd/' >> mailcow.conf
|
echo '# see https://docs.mailcow.email/models/model-passwd/' >> mailcow.conf
|
||||||
echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf
|
echo "MAILCOW_PASS_SCHEME=BLF-CRYPT" >> mailcow.conf
|
||||||
fi
|
fi
|
||||||
elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then
|
elif [[ ${option} == "ADDITIONAL_SERVER_NAMES" ]]; then
|
||||||
|
@ -617,7 +657,7 @@ for option in ${CONFIG_ARRAY[@]}; do
|
||||||
echo '# Optional: Leave empty for none' >> mailcow.conf
|
echo '# Optional: Leave empty for none' >> mailcow.conf
|
||||||
echo '# This value is only used on first order!' >> mailcow.conf
|
echo '# This value is only used on first order!' >> mailcow.conf
|
||||||
echo '# Setting it at a later point will require the following steps:' >> mailcow.conf
|
echo '# Setting it at a later point will require the following steps:' >> mailcow.conf
|
||||||
echo '# https://mailcow.github.io/mailcow-dockerized-docs/troubleshooting/debug-reset_tls/' >> mailcow.conf
|
echo '# https://docs.mailcow.email/troubleshooting/debug-reset_tls/' >> mailcow.conf
|
||||||
echo 'ACME_CONTACT=' >> mailcow.conf
|
echo 'ACME_CONTACT=' >> mailcow.conf
|
||||||
fi
|
fi
|
||||||
elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then
|
elif [[ ${option} == "WEBAUTHN_ONLY_TRUSTED_VENDORS" ]]; then
|
||||||
|
@ -727,15 +767,17 @@ elif [ $NEW_BRANCH == "nightly" ] && [ $CURRENT_BRANCH != "nightly" ]; then
|
||||||
git checkout -f ${BRANCH}
|
git checkout -f ${BRANCH}
|
||||||
fi
|
fi
|
||||||
|
|
||||||
echo -e "\e[32mChecking for newer update script...\e[0m"
|
if [ ! $DEV ]; then
|
||||||
SHA1_1=$(sha1sum update.sh)
|
echo -e "\e[32mChecking for newer update script...\e[0m"
|
||||||
git fetch origin #${BRANCH}
|
SHA1_1=$(sha1sum update.sh)
|
||||||
git checkout origin/${BRANCH} update.sh
|
git fetch origin #${BRANCH}
|
||||||
SHA1_2=$(sha1sum update.sh)
|
git checkout origin/${BRANCH} update.sh
|
||||||
if [[ ${SHA1_1} != ${SHA1_2} ]]; then
|
SHA1_2=$(sha1sum update.sh)
|
||||||
echo "update.sh changed, please run this script again, exiting."
|
if [[ ${SHA1_1} != ${SHA1_2} ]]; then
|
||||||
chmod +x update.sh
|
echo "update.sh changed, please run this script again, exiting."
|
||||||
exit 2
|
chmod +x update.sh
|
||||||
|
exit 2
|
||||||
|
fi
|
||||||
fi
|
fi
|
||||||
|
|
||||||
if [ ! $FORCE ]; then
|
if [ ! $FORCE ]; then
|
||||||
|
@ -902,9 +944,6 @@ else
|
||||||
echo -e "\e[33mCannot determine current git repository version...\e[0m"
|
echo -e "\e[33mCannot determine current git repository version...\e[0m"
|
||||||
fi
|
fi
|
||||||
|
|
||||||
# Set DOCKER_COMPOSE_VERSION
|
|
||||||
sed -i 's/^DOCKER_COMPOSE_VERSION=$/DOCKER_COMPOSE_VERSION='$DOCKER_COMPOSE_VERSION'/g' mailcow.conf
|
|
||||||
|
|
||||||
if [[ ${SKIP_START} == "y" ]]; then
|
if [[ ${SKIP_START} == "y" ]]; then
|
||||||
echo -e "\e[33mNot starting mailcow, please run \"$COMPOSE_COMMAND up -d --remove-orphans\" to start mailcow.\e[0m"
|
echo -e "\e[33mNot starting mailcow, please run \"$COMPOSE_COMMAND up -d --remove-orphans\" to start mailcow.\e[0m"
|
||||||
else
|
else
|
||||||
|
|
Loading…
Reference in New Issue