1
0
mirror of https://github.com/mailcow/mailcow-dockerized.git synced 2025-12-22 06:11:32 +00:00

[Web] Add delimiter_action to mailbox and mailbox_template add/edit admin forms (#6620)

This commit is contained in:
FreddleSpl0it
2025-08-06 09:40:47 +02:00
committed by GitHub
parent 842cb235b6
commit 1e42b8dd21
7 changed files with 193 additions and 73 deletions

View File

@@ -125,6 +125,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
'mailbox' => $mailbox, 'mailbox' => $mailbox,
'rl' => $rl, 'rl' => $rl,
'pushover_data' => $pushover_data, 'pushover_data' => $pushover_data,
'get_tagging_options' => mailbox('get', 'delimiter_action', $mailbox),
'quarantine_notification' => $quarantine_notification, 'quarantine_notification' => $quarantine_notification,
'quarantine_category' => $quarantine_category, 'quarantine_category' => $quarantine_category,
'get_tls_policy' => $get_tls_policy, 'get_tls_policy' => $get_tls_policy,

View File

@@ -1223,6 +1223,14 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$stmt->execute(array( $stmt->execute(array(
':username' => $username ':username' => $username
)); ));
// save delimiter_action
if (isset($_data['tagged_mail_handler'])) {
mailbox('edit', 'delimiter_action', array(
'username' => $username,
'tagged_mail_handler' => $_data['tagged_mail_handler']
));
}
// save tags // save tags
foreach($tags as $index => $tag){ foreach($tags as $index => $tag){
if (empty($tag)) continue; if (empty($tag)) continue;
@@ -1613,6 +1621,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$attr = array(); $attr = array();
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array(); $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : array();
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler']);
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']); $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']); $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s"; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : "s";
@@ -3259,6 +3268,13 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
); );
return false; return false;
} }
// save delimiter_action
if (isset($_data['tagged_mail_handler'])) {
mailbox('edit', 'delimiter_action', array(
'username' => $username,
'tagged_mail_handler' => $_data['tagged_mail_handler']
));
}
// save tags // save tags
foreach($tags as $index => $tag){ foreach($tags as $index => $tag){
if (empty($tag)) continue; if (empty($tag)) continue;
@@ -3604,6 +3620,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
$attr = array(); $attr = array();
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0; $attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
$attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags']; $attr['tags'] = (isset($_data['tags'])) ? $_data['tags'] : $is_now['tags'];
$attr["tagged_mail_handler"] = (!empty($_data['tagged_mail_handler'])) ? $_data['tagged_mail_handler'] : $is_now['tagged_mail_handler'];
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification']; $attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : $is_now['quarantine_notification'];
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category']; $attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : $is_now['quarantine_category'];
$attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame']; $attr["rl_frame"] = (!empty($_data['rl_frame'])) ? $_data['rl_frame'] : $is_now['rl_frame'];

View File

@@ -186,6 +186,12 @@ $MAILBOX_DEFAULT_ATTRIBUTES['force_pw_update'] = false;
// Enable SOGo access - Users will be redirected to SOGo after login (set to false to disable redirect by default) // Enable SOGo access - Users will be redirected to SOGo after login (set to false to disable redirect by default)
$MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true; $MAILBOX_DEFAULT_ATTRIBUTES['sogo_access'] = true;
// How to handle tagged emails
// none - No special handling
// subfolder - Create subfolder under INBOX (e.g. "INBOX/Facebook")
// subject - Add tag to subject (e.g. "[Facebook] Subject")
$MAILBOX_DEFAULT_ATTRIBUTES['tagged_mail_handler'] = "none";
// Send notification when quarantine is not empty (never, hourly, daily, weekly) // Send notification when quarantine is not empty (never, hourly, daily, weekly)
$MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'hourly'; $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'] = 'hourly';
@@ -257,57 +263,57 @@ $RSPAMD_MAPS = array(
$IMAPSYNC_OPTIONS = array( $IMAPSYNC_OPTIONS = array(
'whitelist' => array( 'whitelist' => array(
'abort', 'abort',
'authmd51', 'authmd51',
'authmd52', 'authmd52',
'authmech1', 'authmech1',
'authmech2', 'authmech2',
'authuser1', 'authuser1',
'authuser2', 'authuser2',
'debug', 'debug',
'debugcontent', 'debugcontent',
'debugcrossduplicates', 'debugcrossduplicates',
'debugflags', 'debugflags',
'debugfolders', 'debugfolders',
'debugimap', 'debugimap',
'debugimap1', 'debugimap1',
'debugimap2', 'debugimap2',
'debugmemory', 'debugmemory',
'debugssl', 'debugssl',
'delete1emptyfolders', 'delete1emptyfolders',
'delete2folders', 'delete2folders',
'disarmreadreceipts', 'disarmreadreceipts',
'domain1', 'domain1',
'domain2', 'domain2',
'domino1', 'domino1',
'domino2', 'domino2',
'dry', 'dry',
'errorsmax', 'errorsmax',
'exchange1', 'exchange1',
'exchange2', 'exchange2',
'exitwhenover', 'exitwhenover',
'expunge1', 'expunge1',
'f1f2', 'f1f2',
'filterbuggyflags', 'filterbuggyflags',
'folder', 'folder',
'folderfirst', 'folderfirst',
'folderlast', 'folderlast',
'folderrec', 'folderrec',
'gmail1', 'gmail1',
'gmail2', 'gmail2',
'idatefromheader', 'idatefromheader',
'include', 'include',
'inet4', 'inet4',
'inet6', 'inet6',
'justconnect', 'justconnect',
'justfolders', 'justfolders',
'justfoldersizes', 'justfoldersizes',
'justlogin', 'justlogin',
'keepalive1', 'keepalive1',
'keepalive2', 'keepalive2',
'log', 'log',
'logdir', 'logdir',
'logfile', 'logfile',
'maxbytesafter', 'maxbytesafter',
'maxlinelength', 'maxlinelength',
'maxmessagespersecond', 'maxmessagespersecond',
@@ -315,62 +321,62 @@ $IMAPSYNC_OPTIONS = array(
'maxsleep', 'maxsleep',
'minage', 'minage',
'minsize', 'minsize',
'noabletosearch', 'noabletosearch',
'noabletosearch1', 'noabletosearch1',
'noabletosearch2', 'noabletosearch2',
'noexpunge1', 'noexpunge1',
'noexpunge2', 'noexpunge2',
'nofoldersizesatend', 'nofoldersizesatend',
'noid', 'noid',
'nolog', 'nolog',
'nomixfolders', 'nomixfolders',
'noresyncflags', 'noresyncflags',
'nossl1', 'nossl1',
'nossl2', 'nossl2',
'nosyncacls', 'nosyncacls',
'notls1', 'notls1',
'notls2', 'notls2',
'nouidexpunge2', 'nouidexpunge2',
'nousecache', 'nousecache',
'oauthaccesstoken1', 'oauthaccesstoken1',
'oauthaccesstoken2', 'oauthaccesstoken2',
'oauthdirect1', 'oauthdirect1',
'oauthdirect2', 'oauthdirect2',
'office1', 'office1',
'office2', 'office2',
'pidfile', 'pidfile',
'pidfilelocking', 'pidfilelocking',
'prefix1', 'prefix1',
'prefix2', 'prefix2',
'proxyauth1', 'proxyauth1',
'proxyauth2', 'proxyauth2',
'resyncflags', 'resyncflags',
'resynclabels', 'resynclabels',
'search', 'search',
'search1', 'search1',
'search2', 'search2',
'sep1', 'sep1',
'sep2', 'sep2',
'showpasswords', 'showpasswords',
'skipemptyfolders', 'skipemptyfolders',
'ssl2', 'ssl2',
'sslargs1', 'sslargs1',
'sslargs2', 'sslargs2',
'subfolder1', 'subfolder1',
'subscribe', 'subscribe',
'subscribed', 'subscribed',
'syncacls', 'syncacls',
'syncduplicates', 'syncduplicates',
'syncinternaldates', 'syncinternaldates',
'synclabels', 'synclabels',
'tests', 'tests',
'testslive', 'testslive',
'testslive6', 'testslive6',
'tls2', 'tls2',
'truncmess', 'truncmess',
'usecache', 'usecache',
'useheader', 'useheader',
'useuid' 'useuid'
), ),
'blacklist' => array( 'blacklist' => array(
'skipmess', 'skipmess',

View File

@@ -269,6 +269,24 @@ $(document).ready(function() {
function setMailboxTemplateData(template){ function setMailboxTemplateData(template){
$("#addInputQuota").val(template.quota / 1048576); $("#addInputQuota").val(template.quota / 1048576);
if (template.tagged_mail_handler === "subfolder"){
$('#tagged_mail_handler_subfolder').prop('checked', true);
$('#tagged_mail_handler_subject').prop('checked', false);
$('#tagged_mail_handler_none').prop('checked', false);
} else if(template.tagged_mail_handler === "subject"){
$('#tagged_mail_handler_subfolder').prop('checked', false);
$('#tagged_mail_handler_subject').prop('checked', true);
$('#tagged_mail_handler_none').prop('checked', false);
} else if(template.tagged_mail_handler === "none"){
$('#tagged_mail_handler_subfolder').prop('checked', false);
$('#tagged_mail_handler_subject').prop('checked', false);
$('#tagged_mail_handler_none').prop('checked', true);
} else {
$('#tagged_mail_handler_subfolder').prop('checked', false);
$('#tagged_mail_handler_subject').prop('checked', false);
$('#tagged_mail_handler_none').prop('checked', true);
}
if (template.quarantine_notification === "never"){ if (template.quarantine_notification === "never"){
$('#quarantine_notification_never').prop('checked', true); $('#quarantine_notification_never').prop('checked', true);
$('#quarantine_notification_hourly').prop('checked', false); $('#quarantine_notification_hourly').prop('checked', false);

View File

@@ -36,6 +36,23 @@
<small class="text-muted">0 = ∞</small> <small class="text-muted">0 = ∞</small>
</div> </div>
</div> </div>
<div class="row mb-2">
<label class="control-label col-sm-2">{{ lang.user.tag_handling }}</label>
<div class="col-sm-10">
<div class="btn-group">
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_subfolder" autocomplete="off" value="subfolder" {% if template.attributes.tagged_mail_handler == 'subfolder' %}checked{% endif %}>
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_subfolder">{{ lang.user.tag_in_subfolder }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_subject" autocomplete="off" value="subject" {% if template.attributes.tagged_mail_handler == 'subject' %}checked{% endif %}>
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_subject">{{ lang.user.tag_in_subject }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_none" autocomplete="off" value="none" {% if template.attributes.tagged_mail_handler == 'none' %}checked{% endif %}>
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_none">{{ lang.user.tag_in_none }}</label>
</div>
<p class="text-muted"><small>{{ lang.user.tag_help_explain|raw }}</small></p>
<p class="text-muted"><small>{{ lang.user.tag_help_example|raw }}</small></p>
</div>
</div>
<div class="row mb-2"> <div class="row mb-2">
<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">

View File

@@ -117,7 +117,7 @@
<div class="row mb-2"> <div class="row mb-2">
<label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label> <label class="control-label col-sm-2" for="relayhost">{{ lang.edit.relayhost }}</label>
<div class="col-sm-10"> <div class="col-sm-10">
<select data-acl="{{ acl.mailbox_relayhost }}" data-live-search="true" id="relayhost" name="relayhost" class="form-control mb-4"> <select data-acl="{{ acl.mailbox_relayhost }}" data-live-search="true" id="relayhost" name="relayhost" class="form-control">
{% for rlyhost in rlyhosts %} {% for rlyhost in rlyhosts %}
<option <option
style="{% if rlyhost.active != '1' %}background: #ff4136; color: #fff{% endif %}" style="{% if rlyhost.active != '1' %}background: #ff4136; color: #fff{% endif %}"
@@ -131,7 +131,34 @@
</option> </option>
</select> </select>
<p class="d-block d-sm-none" style="margin: 0;padding: 0">&nbsp;</p> <p class="d-block d-sm-none" style="margin: 0;padding: 0">&nbsp;</p>
<small class="text-muted d-block">{{ lang.edit.mailbox_relayhost_info }}</small> <small class="text-muted d-block mb-4">{{ lang.edit.mailbox_relayhost_info }}</small>
</div>
</div>
<div class="row mb-2">
<label class="control-label col-sm-2">{{ lang.user.tag_handling }}</label>
<div class="col-sm-10">
<div class="btn-group" data-acl="{{ acl.delimiter_action }}">
<button type="button" class="btn btn-sm btn-xs-third d-block d-sm-inline{% if get_tagging_options == 'subfolder' %} btn-dark{% else %} btn-light{% endif %}"
data-action="edit_selected"
data-item="{{ mailbox }}"
data-id="delimiter_action"
data-api-url='edit/delimiter_action'
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{% if get_tagging_options == 'subject' %} btn-dark{% else %} btn-light{% endif %}"
data-action="edit_selected"
data-item="{{ mailbox }}"
data-id="delimiter_action"
data-api-url='edit/delimiter_action'
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{% if get_tagging_options == 'none' %} btn-dark{% else %} btn-light{% endif %}"
data-action="edit_selected"
data-item="{{ mailbox }}"
data-id="delimiter_action"
data-api-url='edit/delimiter_action'
data-api-attr='{"tagged_mail_handler":"none"}'>{{ lang.user.tag_in_none }}</button>
</div>
<p class="text-muted"><small>{{ lang.user.tag_help_explain|raw }}</small></p>
<p class="text-muted"><small>{{ lang.user.tag_help_example|raw }}</small></p>
</div> </div>
</div> </div>
<div class="row mb-2"> <div class="row mb-2">

View File

@@ -76,6 +76,23 @@
<div class="badge fs-5 bg-warning addInputQuotaExhausted" style="display:none;">{{ lang.warning.quota_exceeded_scope }}</div> <div class="badge fs-5 bg-warning addInputQuotaExhausted" style="display:none;">{{ lang.warning.quota_exceeded_scope }}</div>
</div> </div>
</div> </div>
<div class="row mb-2">
<label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.tag_handling }}</label>
<div class="col-sm-10">
<div class="btn-group">
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_subfolder" autocomplete="off" value="subfolder">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_subfolder">{{ lang.user.tag_in_subfolder }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_subject" autocomplete="off" value="subject">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_subject">{{ lang.user.tag_in_subject }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="tagged_mail_handler_none" autocomplete="off" value="none">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="tagged_mail_handler_none">{{ lang.user.tag_in_none }}</label>
</div>
<p class="text-muted"><small>{{ lang.user.tag_help_explain|raw }}</small></p>
<p class="text-muted"><small>{{ lang.user.tag_help_example|raw }}</small></p>
</div>
</div>
<div class="row mb-2"> <div class="row mb-2">
<label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.quarantine_notification }}</label> <label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.quarantine_notification }}</label>
<div class="col-sm-10"> <div class="col-sm-10">
@@ -246,6 +263,23 @@
<small class="text-muted">0 = ∞</small> <small class="text-muted">0 = ∞</small>
</div> </div>
</div> </div>
<div class="row mb-2">
<label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.tag_handling }}</label>
<div class="col-sm-10">
<div class="btn-group">
<input type="radio" class="btn-check" name="tagged_mail_handler" id="template_tagged_mail_handler_subfolder" autocomplete="off" value="subfolder">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="template_tagged_mail_handler_subfolder">{{ lang.user.tag_in_subfolder }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="template_tagged_mail_handler_subject" autocomplete="off" value="subject">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="template_tagged_mail_handler_subject">{{ lang.user.tag_in_subject }}</label>
<input type="radio" class="btn-check" name="tagged_mail_handler" id="template_tagged_mail_handler_none" autocomplete="off" value="none">
<label class="btn btn-sm btn-xs-quart d-block d-sm-inline btn-light" for="template_tagged_mail_handler_none">{{ lang.user.tag_in_none }}</label>
</div>
<p class="text-muted"><small>{{ lang.user.tag_help_explain|raw }}</small></p>
<p class="text-muted"><small>{{ lang.user.tag_help_example|raw }}</small></p>
</div>
</div>
<div class="row mb-2"> <div class="row mb-2">
<label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.quarantine_notification }}</label> <label class="control-label col-sm-2 text-sm-end text-sm-end">{{ lang.user.quarantine_notification }}</label>
<div class="col-sm-10"> <div class="col-sm-10">