mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-11-08 18:13:37 +00:00
[Web][Dovecot] Add retention rules: nightly deletion of mail by folder and age for domains, groups and mailboxes
This commit is contained in:
36 files changed
+3013
-16
No files matched your search
@@ -17,6 +17,7 @@
|
||||
<li role="presentation"><button class="dropdown-item" data-bs-target="#tab-api-logs" aria-selected="false" aria-controls="tab-api-logs" role="tab" data-bs-toggle="tab">API</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" data-bs-target="#tab-api-rl" aria-selected="false" aria-controls="tab-api-rl" role="tab" data-bs-toggle="tab">Ratelimits</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" data-bs-target="#tab-cron-logs" aria-selected="false" aria-controls="tab-api-rl" role="tab" data-bs-toggle="tab">Crontasks</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" data-bs-target="#tab-retention-logs" aria-selected="false" aria-controls="tab-retention-logs" role="tab" data-bs-toggle="tab">{{ lang.mailbox.policies_retention }}</button></li>
|
||||
<li role="presentation"><span class="dropdown-header fs-6">{{ lang.debug.external_logs }}</span></li>
|
||||
<li role="presentation"><button class="dropdown-item" data-bs-target="#tab-rspamd-history" aria-selected="false" aria-controls="tab-rspamd-history" role="tab" data-bs-toggle="tab">Rspamd</button></li>
|
||||
<li role="presentation"><span class="dropdown-header fs-6">{{ lang.debug.static_logs }}</span></li>
|
||||
@@ -547,6 +548,21 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div role="tabpanel" class="tab-pane" id="tab-retention-logs">
|
||||
<div class="debug-log-info">{{ lang.retention.log_info }}</div>
|
||||
<div class="card">
|
||||
<div class="card-header d-flex align-items-center fs-5">
|
||||
<span class="mt-2 ms-2">{{ lang.retention.rules }}</span>
|
||||
<div class="btn-group ms-auto">
|
||||
<button class="btn btn-sm btn-secondary refresh_table" data-table="retention_log">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="card-body">
|
||||
<table id="retention_log" class="table table-striped dt-responsive w-100"></table>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div> <!-- /tab-content -->
|
||||
</div> <!-- /col-md-12 -->
|
||||
</div> <!-- /row -->
|
||||
@@ -554,6 +570,7 @@
|
||||
<script type='text/javascript'>
|
||||
var lang = {{ lang_admin|raw }};
|
||||
var lang_debug = {{ lang_debug|raw }};
|
||||
lang.retention = {{ lang_retention|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
var csrf_token = '{{ csrf_token }}';
|
||||
var log_pagination_size = Math.trunc('{{ log_pagination_size }}');
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
{# Fields of a retention rule (add modal, edit page): rule, id (prefix of the element ids), groups (choices: id, name,
|
||||
domain, address), mailboxes (choices), ro, label_class. Own folders are sent apart as own_folders, one per line;
|
||||
without group choices (none in the domain, no access to groups) the group field is left out and stays unchanged. #}
|
||||
{% set special = [] %}
|
||||
{% set own = [] %}
|
||||
{% for folder in rule.folders|default([]) %}
|
||||
{% if folder starts with 'folder:' %}
|
||||
{% set own = own|merge([folder|slice(7)]) %}
|
||||
{% else %}
|
||||
{% set special = special|merge([folder]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_folders">{{ lang.retention.folders }}</label>
|
||||
<div class="col-sm-10">
|
||||
{% if not ro %}<input type="hidden" name="folders" value="">{% endif %}
|
||||
<select data-width="100%" name="folders" id="{{ id }}_folders" class="form-control" multiple title="{{ lang.retention.folders }}"{% if ro %} disabled{% endif %}>
|
||||
{% for folder in ['trash', 'junk', 'sent', 'drafts', 'archive', 'inbox', 'all'] %}
|
||||
<option value="{{ folder }}"{% if folder in special %} selected{% endif %}>{{ attribute(lang.retention, 'folder_' ~ folder) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<small class="text-muted d-block">{{ lang.retention.folders_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_own_folders">{{ lang.retention.own_folders }}</label>
|
||||
<div class="col-sm-10">
|
||||
<textarea class="form-control" rows="2" name="own_folders" id="{{ id }}_own_folders" placeholder="Newsletter Projekte/*"{% if ro %} disabled{% endif %}>{{ own|join("\n") }}</textarea>
|
||||
<small class="text-muted d-block">{{ lang.retention.own_folders_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_days">{{ lang.retention.days }}</label>
|
||||
<div class="col-sm-10">
|
||||
<div class="input-group" style="max-width: 16rem">
|
||||
<input type="number" class="form-control" name="days" id="{{ id }}_days" min="1" max="36500" value="{{ rule.days|default(30) }}" required{% if ro %} disabled{% endif %}>
|
||||
<span class="input-group-text">{{ lang.retention.days_short|replace({'%s ': ''}) }}</span>
|
||||
</div>
|
||||
<small class="text-muted d-block">{{ lang.retention.days_info }}</small>
|
||||
<div class="form-check mt-1">
|
||||
{% if not ro %}<input type="hidden" value="0" name="keep_flagged">{% endif %}
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="keep_flagged"{% if rule.keep_flagged|default(0) == 1 %} checked{% endif %}{% if ro %} disabled{% endif %}> {{ lang.retention.keep_flagged }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_mode">{{ lang.retention.mode }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select class="form-control" name="mode" id="{{ id }}_mode"{% if ro %} disabled{% endif %}>
|
||||
{% for mode in ['simulate', 'delete'] %}
|
||||
<option value="{{ mode }}"{% if rule.mode|default('simulate') == mode %} selected{% endif %}>{{ attribute(lang.retention, 'mode_' ~ mode) }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
<small class="text-muted d-block">{{ lang.retention.mode_info }}</small>
|
||||
</div>
|
||||
</div>
|
||||
<legend class="fs-5 mt-4"><i class="bi bi-people"></i> {{ lang.retention.assign }}</legend><hr>
|
||||
<p class="text-muted small">{{ lang.retention.assign_info }}</p>
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
{% if not ro %}<input type="hidden" value="0" name="all_mailboxes">{% endif %}
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="all_mailboxes"{% if rule.all_mailboxes|default(0) == 1 %} checked{% endif %}{% if ro %} disabled{% endif %}> {{ lang.retention.all_mailboxes }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_mailboxes">{{ lang.retention.mailboxes }}</label>
|
||||
<div class="col-sm-10">
|
||||
{% if not ro %}<input type="hidden" name="mailboxes" value="">{% endif %}
|
||||
<select data-live-search="true" data-width="100%" name="mailboxes" id="{{ id }}_mailboxes" class="form-control retention-mailboxes" multiple title="{{ lang.retention.mailboxes }}"{% if ro %} disabled{% endif %}>
|
||||
{% for mailbox in mailboxes %}
|
||||
<option value="{{ mailbox }}" data-domain="{{ mailbox|split('@')|last }}"{% if mailbox in rule.mailboxes|default([]) %} selected{% endif %}>{{ mailbox }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% if groups %}
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2{{ label_class }}" for="{{ id }}_groups">{{ lang.retention.groups }}</label>
|
||||
<div class="col-sm-10">
|
||||
{% if not ro %}<input type="hidden" name="groups" value="">{% endif %}
|
||||
<select data-live-search="true" data-width="100%" name="groups" id="{{ id }}_groups" class="form-control retention-groups" multiple title="{{ lang.retention.groups }}"{% if ro %} disabled{% endif %}>
|
||||
{% for group in groups %}
|
||||
<option value="{{ group.id }}" data-domain="{{ group.domain }}"{% if group.id in rule.groups|default([]) %} selected{% endif %}>{{ group.name }}{% if group.address %} ({{ group.address }}){% endif %}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
@@ -0,0 +1,46 @@
|
||||
{% extends 'edit.twig' %}
|
||||
|
||||
{% block inner_content %}
|
||||
{% if result %}
|
||||
{% set ro = not result.can_edit %}
|
||||
<h4>{{ lang.retention.rule }}: {{ result.name }}</h4>
|
||||
<form data-id="edit_retention_rule" class="form-horizontal" role="form" method="post" autocapitalize="none" autocorrect="off">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="retention_rule_domain">{{ lang.retention.domain }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" id="retention_rule_domain" value="{{ result.domain }}" disabled>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="retention_rule_name">{{ lang.retention.name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" id="retention_rule_name" value="{{ result.name }}" maxlength="100" required{% if ro %} disabled{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2" for="retention_rule_description">{{ lang.retention.description }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="retention_rule_description" value="{{ result.description }}" maxlength="255"{% if ro %} disabled{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
{% include 'edit/retention-rule-fields.twig' with {'rule': result, 'id': 'retention_rule', 'groups': retention_groups, 'mailboxes': mailboxes, 'ro': ro, 'label_class': ''} %}
|
||||
<div class="row mb-4">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active"{% if result.active == 1 %} checked{% endif %}{% if ro %} disabled{% endif %}> {{ lang.mailbox.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
{% if not ro %}
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="edit_selected" data-id="edit_retention_rule" data-item="{{ result.id }}" data-api-url='edit/retention-rule' data-api-attr='{}' href="#"><i class="bi bi-check-lg"></i> {{ lang.admin.save }}</button>
|
||||
</div>
|
||||
</div>
|
||||
{% endif %}
|
||||
</form>
|
||||
{% else %}
|
||||
{{ parent() }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
@@ -36,16 +36,22 @@
|
||||
{% if acl.mailbox_groups == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-groups" role="tab" data-bs-toggle="tab" data-bs-target="#tab-groups">{{ lang.groups.groups }}</button></li>
|
||||
{% endif %}
|
||||
{% if mailcow_cc_role == 'admin' %}
|
||||
{# policies: TLS (admins), mail policies and retention rules (ACLs); a single one is a plain tab #}
|
||||
{% set policy_tabs = [] %}
|
||||
{% if mailcow_cc_role == 'admin' %}{% set policy_tabs = policy_tabs|merge([{'id': 'tab-tls-policy', 'short': lang.mailbox.policies_tls, 'long': lang.mailbox.tls_policy_maps}]) %}{% endif %}
|
||||
{% if acl.mail_policies == 1 %}{% set policy_tabs = policy_tabs|merge([{'id': 'tab-mail-policies', 'short': lang.mailbox.policies_mail, 'long': lang.mail_policy.mail_policies}]) %}{% endif %}
|
||||
{% if acl.retention == 1 %}{% set policy_tabs = policy_tabs|merge([{'id': 'tab-retention', 'short': lang.mailbox.policies_retention, 'long': lang.retention.rules}]) %}{% endif %}
|
||||
{% if policy_tabs|length > 1 %}
|
||||
<li class="nav-item dropdown">
|
||||
<a class="nav-link dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.policies }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-tls-policy" role="tab" data-bs-toggle="tab" data-bs-target="#tab-tls-policy">{{ lang.mailbox.policies_tls }}</button></li>
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="tab-mail-policies" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mail-policies">{{ lang.mailbox.policies_mail }}</button></li>
|
||||
{% for tab in policy_tabs %}
|
||||
<li role="presentation"><button class="dropdown-item" aria-selected="false" aria-controls="{{ tab.id }}" role="tab" data-bs-toggle="tab" data-bs-target="#{{ tab.id }}">{{ tab.short }}</button></li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
</li>
|
||||
{% elseif acl.mail_policies == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-mail-policies" role="tab" data-bs-toggle="tab" data-bs-target="#tab-mail-policies">{{ lang.mail_policy.mail_policies }}</button></li>
|
||||
{% elseif policy_tabs|length == 1 %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="{{ policy_tabs[0].id }}" role="tab" data-bs-toggle="tab" data-bs-target="#{{ policy_tabs[0].id }}">{{ policy_tabs[0].long }}</button></li>
|
||||
{% endif %}
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-syncjobs" role="tab" data-bs-toggle="tab" data-bs-target="#tab-syncjobs">{{ lang.syncjobs.sync_jobs }}</button></li>
|
||||
<li class="nav-item" role="presentation"><button class="nav-link" aria-selected="false" aria-controls="tab-filters" role="tab" data-bs-toggle="tab" data-bs-target="#tab-filters">{{ lang.mailbox.filters }}</button></li>
|
||||
@@ -72,6 +78,9 @@
|
||||
{% if acl.mail_policies == 1 %}
|
||||
{% include 'mailbox/tab-mail-policies.twig' %}
|
||||
{% endif %}
|
||||
{% if acl.retention == 1 %}
|
||||
{% include 'mailbox/tab-retention.twig' %}
|
||||
{% endif %}
|
||||
{% include 'mailbox/tab-syncjobs.twig' %}
|
||||
{% include 'mailbox/tab-filters.twig' %}
|
||||
{% include 'mailbox/tab-bcc.twig' %}
|
||||
@@ -89,6 +98,7 @@
|
||||
lang.syncjobs = {{ lang_syncjobs|raw }};
|
||||
lang.groups = {{ lang_groups|raw }};
|
||||
lang.mail_policy = {{ lang_mail_policy|raw }};
|
||||
lang.retention = {{ lang_retention|raw }};
|
||||
var lang_rl = {{ lang_rl|raw }};
|
||||
var lang_edit = {{ lang_edit|raw }};
|
||||
var lang_datatables = {{ lang_datatables|raw }};
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<div class="tab-pane fade" id="tab-retention" role="tabpanel" aria-labelledby="tab-retention">
|
||||
<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-retention" data-bs-toggle="collapse" aria-controls="collapse-tab-retention">
|
||||
{{ lang.retention.rules }} <span class="badge bg-info table-lines"></span>
|
||||
</button>
|
||||
<span class="d-none d-md-block">{{ lang.retention.rules }} <span class="badge bg-info table-lines"></span></span>
|
||||
<div class="btn-group ms-auto d-flex">
|
||||
<button class="btn btn-xs btn-secondary refresh_table" data-table="retention_table">{{ lang.admin.refresh }}</button>
|
||||
</div>
|
||||
</div>
|
||||
<div id="collapse-tab-retention" class="card-body collapse" data-bs-parent="#mail-content">
|
||||
<p class="text-muted">{{ lang.retention.info }}</p>
|
||||
<table id="retention_table" class="table table-striped dt-responsive w-100"></table>
|
||||
<div class="mass-actions-mailbox mt-4">
|
||||
<div class="btn-group">
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary" id="toggle_multi_select_all" data-id="retention_rule" href="#"><i class="bi bi-check-all"></i> {{ lang.mailbox.toggle_all }}</a>
|
||||
<a class="btn btn-sm btn-xs-half d-block d-sm-inline btn-secondary dropdown-toggle" data-bs-toggle="dropdown" href="#">{{ lang.mailbox.quick_actions }}</a>
|
||||
<ul class="dropdown-menu">
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="retention_rule" data-api-url='edit/retention-rule' data-api-attr='{"active":"1"}' href="#">{{ lang.mailbox.activate }}</a></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="retention_rule" data-api-url='edit/retention-rule' data-api-attr='{"active":"0"}' href="#">{{ lang.mailbox.deactivate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="edit_selected" data-id="retention_rule" data-api-url='edit/retention-rule' data-api-attr='{"mode":"simulate"}' href="#">{{ lang.retention.mode }}: {{ lang.retention.mode_simulate }}</a></li>
|
||||
<li><hr class="dropdown-divider"></li>
|
||||
<li><a class="dropdown-item" data-action="delete_selected" data-id="retention_rule" data-api-url='delete/retention-rule' href="#">{{ lang.mailbox.remove }}</a></li>
|
||||
</ul>
|
||||
<a class="btn btn-sm d-block d-sm-inline btn-success" href="#" data-bs-toggle="modal" data-bs-target="#addRetentionModal"><i class="bi bi-plus-lg"></i> {{ lang.retention.add }}</a>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1365,3 +1365,6 @@
|
||||
{% if acl.mail_policies == 1 %}
|
||||
{% include "modals/mail_policy.twig" %}
|
||||
{% endif %}
|
||||
{% if acl.retention == 1 %}
|
||||
{% include "modals/retention.twig" %}
|
||||
{% endif %}
|
||||
@@ -0,0 +1,50 @@
|
||||
<div class="modal fade" id="addRetentionModal" tabindex="-1" role="dialog" aria-hidden="true">
|
||||
<div class="modal-dialog modal-xl">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h3 class="modal-title">{{ lang.retention.add }}</h3>
|
||||
<button type="button" class="btn-close" data-bs-dismiss="modal"></button>
|
||||
</div>
|
||||
<div class="modal-body">
|
||||
<form class="form-horizontal" role="form" data-id="add_retention_rule" autocapitalize="none" autocorrect="off">
|
||||
<input type="hidden" value="0" name="active">
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="add_retention_rule_domain">{{ lang.retention.domain }}</label>
|
||||
<div class="col-sm-10">
|
||||
<select data-live-search="true" name="domain" id="add_retention_rule_domain" class="form-control retention-domain-select" required>
|
||||
{% for domain in domains %}
|
||||
<option>{{ domain }}</option>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="add_retention_rule_name">{{ lang.retention.name }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="name" id="add_retention_rule_name" maxlength="100" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="control-label col-sm-2 text-sm-end" for="add_retention_rule_description">{{ lang.retention.description }}</label>
|
||||
<div class="col-sm-10">
|
||||
<input type="text" class="form-control" name="description" id="add_retention_rule_description" maxlength="255">
|
||||
</div>
|
||||
</div>
|
||||
{% include 'edit/retention-rule-fields.twig' with {'rule': {}, 'id': 'add_retention_rule', 'groups': retention_groups, 'mailboxes': mailboxes, 'ro': false, 'label_class': ' text-sm-end'} %}
|
||||
<div class="row mb-2">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<div class="form-check">
|
||||
<label><input type="checkbox" class="form-check-input" value="1" name="active" checked> {{ lang.mailbox.active }}</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="offset-sm-2 col-sm-10">
|
||||
<button class="btn btn-xs-lg d-block d-sm-inline btn-success" data-action="add_item" data-id="add_retention_rule" data-api-url='add/retention-rule' data-api-attr='{}' href="#">{{ lang.admin.add }}</button>
|
||||
</div>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@@ -73,6 +73,21 @@
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4"><i class="bi bi-hourglass-split"></i> {{ lang.mailbox.policies_retention }}:
|
||||
<p class="small">{{ lang.retention.user_info }}</p>
|
||||
</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
<p>
|
||||
{% for action in retention_rules %}
|
||||
{% if action.folder starts with 'folder:' %}{{ action.folder|slice(7) }}{% elseif action.folder == 'all' and not loop.first %}{{ lang.retention.user_all_other }}{% elseif action.match == 'subfolders' %}{{ lang.retention.user_subfolders_of|format(attribute(lang.retention, 'folder_' ~ action.folder)) }}{% else %}{{ attribute(lang.retention, 'folder_' ~ action.folder) }}{% if action.subfolders %} {{ lang.retention.user_with_subfolders }}{% endif %}{% endif %}:
|
||||
{{ lang.retention.days_short|format(action.days) }}{% if action.keep_flagged %}, {{ lang.retention.user_keep_flagged }}{% endif %}{% if action.mode != 'delete' %} <span class="text-muted">({{ lang.retention.user_simulated }})</span>{% endif %}{% if not loop.last %}<br>{% endif %}
|
||||
{% else %}
|
||||
{{ lang.retention.user_none }}
|
||||
{% endfor %}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row">
|
||||
<div class="col-sm-4 col-md-3 col-12 text-sm-end text-start mb-4">{{ lang.user.is_catch_all }}:</div>
|
||||
<div class="col-sm-8 col-md-9 col-12">
|
||||
|
||||
Reference in new issue
Block a user