1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2026-04-19 07:28:58 +00:00

[Web][Dovecot] Allow parallel imapsync execution

This commit is contained in:
FreddleSpl0it
2026-04-15 10:20:15 +02:00
parent 886dbcc419
commit 9610a79c3e
11 changed files with 312 additions and 100 deletions

View File

@@ -106,6 +106,7 @@ $template_data = [
'f2b_data' => $f2b_data,
'f2b_banlist_url' => getBaseUrl() . "/f2b-banlist?id=" . $f2b_data['banlist_id'],
'q_data' => quarantine('settings'),
'sj_data' => mailbox('get', 'syncjob_settings'),
'qn_data' => quota_notification('get'),
'pw_reset_data' => reset_password('get_notification'),
'rsettings_map' => file_get_contents('http://nginx:8081/settings.php'),

View File

@@ -3931,6 +3931,64 @@ paths:
type: object
type: object
summary: Update sync job
/api/v1/edit/syncjob_settings:
post:
responses:
"401":
$ref: "#/components/responses/Unauthorized"
"200":
content:
application/json:
examples:
response:
value:
log:
- entity
- action
- object
msg:
- message
- entity name
type: success
schema:
properties:
log:
description: contains request object
items: {}
type: array
msg:
items: {}
type: array
type:
enum:
- success
- danger
- error
type: string
type: object
description: OK
headers: {}
tags:
- Sync jobs
description: >-
Update the global sync job settings. Currently exposes the maximum
number of imapsync processes that are allowed to run in parallel.
Admin access required.
operationId: Update sync job settings
requestBody:
content:
application/json:
schema:
example:
max_parallel: 4
properties:
max_parallel:
description: >-
Maximum number of imapsync processes allowed to run in
parallel (1 = sequential behavior, max 50)
type: integer
type: object
summary: Update sync job settings
/api/v1/edit/user-acl:
post:
responses:
@@ -5629,6 +5687,36 @@ paths:
description: You can list all syn jobs existing in system.
operationId: Get sync jobs
summary: Get sync jobs
/api/v1/get/syncjob_settings:
get:
responses:
"401":
$ref: "#/components/responses/Unauthorized"
"200":
content:
application/json:
examples:
response:
value:
max_parallel: 4
schema:
properties:
max_parallel:
description: >-
Maximum number of imapsync processes allowed to run in
parallel (1 = sequential behavior)
type: integer
type: object
description: OK
headers: {}
tags:
- Sync jobs
description: >-
Return the global sync job settings. Currently exposes the maximum
number of imapsync processes allowed to run in parallel. Admin access
required.
operationId: Get sync job settings
summary: Get sync job settings
"/api/v1/get/tls-policy-map/{id}":
get:
parameters:

View File

@@ -2265,6 +2265,35 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
);
}
break;
case 'syncjob_settings':
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'admin') {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'access_denied'
);
return false;
}
$max_parallel = intval($_data['max_parallel']);
if ($max_parallel < 1) { $max_parallel = 1; }
if ($max_parallel > 50) { $max_parallel = 50; }
try {
$redis->Set('SYNCJOBS_MAX_PARALLEL', $max_parallel);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => array('redis_error', $e->getMessage())
);
return false;
}
$_SESSION['return'][] = array(
'type' => 'success',
'log' => array(__FUNCTION__, $_action, $_type, $_data_log, $_attr),
'msg' => 'syncjob_settings_saved'
);
break;
case 'syncjob':
if (!is_array($_data['id'])) {
$ids = array();
@@ -4619,6 +4648,20 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
}
return $syncjobdetails;
break;
case 'syncjob_settings':
if (!isset($_SESSION['mailcow_cc_role']) || $_SESSION['mailcow_cc_role'] != 'admin') {
return false;
}
$settings = array();
try {
$max_parallel = $redis->Get('SYNCJOBS_MAX_PARALLEL');
}
catch (RedisException $e) {
$max_parallel = null;
}
$settings['max_parallel'] = intval($max_parallel) ?: 1;
return $settings;
break;
case 'syncjobs':
$syncjobdata = array();
if (isset($_data) && filter_var($_data, FILTER_VALIDATE_EMAIL)) {

View File

@@ -1104,6 +1104,10 @@ if (isset($_GET['query'])) {
break;
}
break;
case "syncjob_settings":
$data = mailbox('get', 'syncjob_settings');
process_get_return($data);
break;
case "active-user-sieve":
if (isset($object)) {
$sieve_filter = mailbox('get', 'active_user_sieve', $object);
@@ -1970,6 +1974,9 @@ if (isset($_GET['query'])) {
case "syncjob":
process_edit_return(mailbox('edit', 'syncjob', array_merge(array('id' => $items), $attr)));
break;
case "syncjob_settings":
process_edit_return(mailbox('edit', 'syncjob_settings', $attr));
break;
case "filter":
process_edit_return(mailbox('edit', 'filter', array_merge(array('id' => $items), $attr)));
break;

View File

@@ -372,6 +372,8 @@
"spamfilter": "Spamfilter",
"subject": "Betreff",
"success": "Erfolg",
"syncjobs": "Sync-Jobs",
"syncjobs_max_parallel": "Maximale Anzahl paralleler Sync-Jobs<br><small>Wie viele imapsync-Prozesse dürfen gleichzeitig laufen. 1 = sequentiell (aktuelles Verhalten).</small>",
"sys_mails": "System-E-Mails",
"task": "Aufgabe",
"text": "Text",
@@ -1200,6 +1202,7 @@
"template_modified": "Änderungen am Template %s wurden gespeichert",
"template_removed": "Template ID %s wurde gelöscht",
"sogo_profile_reset": "ActiveSync-Gerät des Benutzers %s wurde zurückgesetzt",
"syncjob_settings_saved": "Sync-Job-Einstellungen wurden gespeichert",
"tls_policy_map_entry_deleted": "TLS-Richtlinie mit der ID %s wurde gelöscht",
"tls_policy_map_entry_saved": "TLS-Richtlinieneintrag \"%s\" wurde gespeichert",
"ui_texts": "Änderungen an UI-Texten",

View File

@@ -382,6 +382,8 @@
"spamfilter": "Spam filter",
"subject": "Subject",
"success": "Success",
"syncjobs": "Sync jobs",
"syncjobs_max_parallel": "Maximum parallel sync jobs<br><small>How many imapsync processes are allowed to run in parallel. 1 = sequential (legacy behavior).</small>",
"sys_mails": "System mails",
"task": "Task",
"text": "Text",
@@ -1204,6 +1206,7 @@
"settings_map_added": "Added settings map entry",
"settings_map_removed": "Removed settings map ID %s",
"sogo_profile_reset": "SOGo profile for user %s was reset",
"syncjob_settings_saved": "Sync job settings have been saved",
"template_added": "Added template %s",
"template_modified": "Changes to template %s have been saved",
"template_removed": "Template ID %s has been deleted",

View File

@@ -21,6 +21,7 @@
<li><button class="dropdown-item" data-bs-target="#tab-config-fwdhosts" aria-selected="false" aria-controls="tab-config-fwdhosts" role="tab" data-bs-toggle="tab">{{ lang.admin.forwarding_hosts }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-f2b" aria-selected="false" aria-controls="tab-config-f2b" role="tab" data-bs-toggle="tab">{{ lang.admin.f2b_parameters }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-quarantine" aria-selected="false" aria-controls="tab-config-quarantine" role="tab" data-bs-toggle="tab">{{ lang.admin.quarantine }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-syncjobs" aria-selected="false" aria-controls="tab-config-syncjobs" role="tab" data-bs-toggle="tab">{{ lang.admin.syncjobs }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-quota" aria-selected="false" aria-controls="tab-config-quota" role="tab" data-bs-toggle="tab">{{ lang.admin.quota_notifications }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-rsettings" aria-selected="false" aria-controls="tab-config-rsettings" role="tab" data-bs-toggle="tab">{{ lang.admin.rspamd_settings_map }}</button></li>
<li><button class="dropdown-item" data-bs-target="#tab-config-password-settings" aria-selected="false" aria-controls="tab-config-password-settings" role="tab" data-bs-toggle="tab">{{ lang.admin.password_settings }}</button></li>
@@ -50,6 +51,7 @@
{% include 'admin/tab-config-fwdhosts.twig' %}
{% include 'admin/tab-config-f2b.twig' %}
{% include 'admin/tab-config-quarantine.twig' %}
{% include 'admin/tab-config-syncjobs.twig' %}
{% include 'admin/tab-config-quota.twig' %}
{% include 'admin/tab-config-rsettings.twig' %}
{% include 'admin/tab-config-customize.twig' %}

View File

@@ -0,0 +1,21 @@
<div class="tab-pane fade" id="tab-config-syncjobs" role="tabpanel" aria-labelledby="tab-config-syncjobs">
<div class="card mb-4">
<div class="card-header d-flex fs-5">
<button class="btn d-md-none flex-grow-1 text-start" data-bs-target="#collapse-tab-config-syncjobs" data-bs-toggle="collapse" aria-controls="collapse-tab-config-syncjobs">
{{ lang.admin.syncjobs }}
</button>
<span class="d-none d-md-block">{{ lang.admin.syncjobs }}</span>
</div>
<div id="collapse-tab-config-syncjobs" class="card-body collapse" data-bs-parent="#admin-content">
<form class="form-horizontal" data-id="syncjob_settings" role="form" method="post">
<div class="row mb-4">
<label class="col-sm-4 control-label text-sm-end" for="syncjobs_max_parallel">{{ lang.admin.syncjobs_max_parallel|raw }}</label>
<div class="col-sm-8">
<input type="number" class="form-control" id="syncjobs_max_parallel" name="max_parallel" value="{{ sj_data.max_parallel }}" min="1" max="50" required>
</div>
</div>
<button class="btn btn-sm d-block d-sm-inline btn-success" data-action="edit_selected" data-item="self" data-id="syncjob_settings" data-api-url='edit/syncjob_settings' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
</form>
</div>
</div>
</div>