mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-07-21 09:10:15 +00:00
Merge 8dc5d15945 into 4b62af9d02
This commit is contained in:
commit
4b00a3524e
5 changed files with 293 additions and 71 deletions
|
|
@ -1,69 +1,175 @@
|
|||
<html>
|
||||
<head>
|
||||
<meta name="x-apple-disable-message-reformatting" />
|
||||
<!DOCTYPE html>
|
||||
<html lang="en" xmlns="http://www.w3.org/1999/xhtml" xmlns:v="urn:schemas-microsoft-com:vml" xmlns:o="urn:schemas-microsoft-com:office:office">
|
||||
<head>
|
||||
<meta charset="utf-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="x-apple-disable-message-reformatting">
|
||||
<meta name="color-scheme" content="light dark">
|
||||
<meta name="supported-color-schemes" content="light dark">
|
||||
<title>Quarantine notification</title>
|
||||
<!--[if mso]>
|
||||
<noscript>
|
||||
<xml>
|
||||
<o:OfficeDocumentSettings>
|
||||
<o:PixelsPerInch>96</o:PixelsPerInch>
|
||||
</o:OfficeDocumentSettings>
|
||||
</xml>
|
||||
</noscript>
|
||||
<![endif]-->
|
||||
<style>
|
||||
body {
|
||||
font-family: Helvetica, Arial, Sans-Serif;
|
||||
}
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
margin-bottom: 20px;
|
||||
}
|
||||
th, td {
|
||||
padding: 8px;
|
||||
text-align: left;
|
||||
border-bottom: 1px solid #ddd;
|
||||
vertical-align: top;
|
||||
}
|
||||
td.fixed {
|
||||
white-space: nowrap;
|
||||
}
|
||||
th {
|
||||
background-color: #56B04C;
|
||||
color: white;
|
||||
}
|
||||
tr:nth-child(even) {
|
||||
background-color: #f2f2f2;
|
||||
}
|
||||
/* mobile devices */
|
||||
@media all and (max-width: 480px) {
|
||||
.mob {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
:root { color-scheme: light dark; supported-color-schemes: light dark; }
|
||||
body { margin: 0 !important; padding: 0 !important; width: 100% !important; -webkit-text-size-adjust: 100%; -ms-text-size-adjust: 100%; }
|
||||
table { border-collapse: collapse !important; }
|
||||
img { border: 0; line-height: 100%; outline: none; text-decoration: none; -ms-interpolation-mode: bicubic; }
|
||||
a { text-decoration: none; }
|
||||
.msg-card td { word-break: break-word; }
|
||||
|
||||
/* Mobile */
|
||||
@media only screen and (max-width: 600px) {
|
||||
.container { width: 100% !important; }
|
||||
.px { padding-left: 20px !important; padding-right: 20px !important; }
|
||||
.btn-a { display: block !important; text-align: center !important; }
|
||||
.btn-cell { display: block !important; width: 100% !important; padding: 4px 0 !important; }
|
||||
}
|
||||
|
||||
/* Dark mode */
|
||||
@media (prefers-color-scheme: dark) {
|
||||
body, .bg-page { background-color: #16181d !important; }
|
||||
.bg-card { background-color: #21242b !important; }
|
||||
.text-main { color: #e7e9ee !important; }
|
||||
.text-muted { color: #a4a9b4 !important; }
|
||||
.border-card { border-color: #343842 !important; }
|
||||
.divider { border-color: #343842 !important; }
|
||||
.btn-primary-cell { background-color: #3a4350 !important; }
|
||||
.btn-secondary-cell { background-color: #2c313a !important; }
|
||||
.btn-secondary-cell a { color: #e7e9ee !important; }
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body>
|
||||
<p>Hi {{username}}!<br>
|
||||
{% if counter == 1 %}
|
||||
There is 1 new message waiting in quarantine:<br>
|
||||
{% else %}
|
||||
There are {{counter}} new messages waiting in quarantine:<br>
|
||||
{% endif %}
|
||||
<table>
|
||||
<tr><th>Subject</th><th>Sender</th><th class="mob">Score</th><th class="mob">Action</th><th class="mob">Arrived on</th>{% if quarantine_acl == 1 %}<th>Actions</th>{% endif %}</tr>
|
||||
{% for line in meta|reverse %}
|
||||
</head>
|
||||
<body class="bg-page" style="margin:0; padding:0; background-color:#f4f5f7;">
|
||||
<div style="display:none; max-height:0; overflow:hidden; mso-hide:all; font-size:1px; line-height:1px; color:#f4f5f7;">
|
||||
{% if counter == 1 %}1 new message is waiting in your quarantine.{% else %}{{ counter }} new messages are waiting in your quarantine.{% endif %}
|
||||
‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌ ‌
|
||||
</div>
|
||||
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" class="bg-page" style="background-color:#f4f5f7;">
|
||||
<tr>
|
||||
<td>{{ line.subject|e }}</td>
|
||||
<td>{{ line.sender|e }}</td>
|
||||
<td class="mob">{{ line.score }}</td>
|
||||
{% if line.action == "reject" %}
|
||||
<td class="mob">Rejected</td>
|
||||
{% else %}
|
||||
<td class="mob">Sent to Junk folder</td>
|
||||
{% endif %}
|
||||
<td class="mob">{{ line.created }}</td>
|
||||
{% if quarantine_acl == 1 %}
|
||||
{% if line.action == "reject" %}
|
||||
<td class="fixed"><a href="https://{{ hostname }}/qhandler/release/{{ line.qhash }}">Release to inbox</a> | <a href="https://{{ hostname }}/qhandler/delete/{{ line.qhash }}">delete</a></td>
|
||||
{% else %}
|
||||
<td class="fixed"><a href="https://{{ hostname }}/qhandler/release/{{ line.qhash }}">Send copy to inbox</a> | <a href="https://{{ hostname }}/qhandler/delete/{{ line.qhash }}">delete</a></td>
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
<td align="center" style="padding:24px 12px;">
|
||||
<table role="presentation" width="600" cellpadding="0" cellspacing="0" border="0" class="container" style="width:600px; max-width:600px;">
|
||||
|
||||
<!-- Header -->
|
||||
<tr>
|
||||
<td style="padding:0;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
<tr>
|
||||
<td class="px bg-card border-card" style="border-radius:12px 12px 0 0; background-color:#ffffff; border-bottom:1px solid #e4e7ec; padding:24px 32px;">
|
||||
<span class="text-main" style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; font-size:18px; font-weight:700; color:#1f2430; letter-spacing:0.2px;">
|
||||
✉ Quarantine notification
|
||||
</span>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Body -->
|
||||
<tr>
|
||||
<td class="bg-card" style="background-color:#ffffff; border-radius:0 0 12px 12px; padding:32px;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0">
|
||||
|
||||
<!-- Greeting -->
|
||||
<tr>
|
||||
<td class="px" style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; padding-bottom:8px;">
|
||||
<p class="text-main" style="margin:0 0 6px 0; font-size:16px; color:#1f2430;">Hi {{ username }},</p>
|
||||
<p class="text-muted" style="margin:0; font-size:15px; line-height:22px; color:#5b6472;">
|
||||
{% if counter == 1 %}
|
||||
There is <b>1 new message</b> waiting in your quarantine.
|
||||
{% else %}
|
||||
There are <b>{{ counter }} new messages</b> waiting in your quarantine.
|
||||
{% endif %}
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
<!-- Messages -->
|
||||
{% for line in meta|reverse %}
|
||||
<tr>
|
||||
<td style="padding-top:18px;">
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" class="msg-card bg-card border-card" style="background-color:#ffffff; border:1px solid #e4e7ec; border-radius:10px;">
|
||||
<tr>
|
||||
<td style="padding:16px 18px; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif;">
|
||||
|
||||
<!-- Subject + status -->
|
||||
<p class="text-main" style="margin:0 0 10px 0; font-size:15px; font-weight:600; line-height:21px; color:#1f2430;">{{ line.subject|e }}</p>
|
||||
|
||||
{% if line.action == "reject" %}
|
||||
<span style="display:inline-block; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.4px; color:#ffffff; background-color:#d64545; border-radius:6px; padding:3px 9px;">Rejected</span>
|
||||
{% else %}
|
||||
<span style="display:inline-block; font-size:11px; font-weight:700; text-transform:uppercase; letter-spacing:0.4px; color:#ffffff; background-color:#c2891b; border-radius:6px; padding:3px 9px;">Sent to Junk</span>
|
||||
{% endif %}
|
||||
<span class="text-muted" style="display:inline-block; font-size:12px; color:#8a93a2; padding-left:8px;">Score {{ line.score }}</span>
|
||||
|
||||
<!-- Meta -->
|
||||
<table role="presentation" width="100%" cellpadding="0" cellspacing="0" border="0" style="margin-top:12px;">
|
||||
<tr>
|
||||
<td class="text-muted" style="font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; font-size:13px; line-height:20px; color:#5b6472;">
|
||||
<span class="text-muted" style="color:#8a93a2;">From</span> {{ line.sender|e }}<br>
|
||||
<span class="text-muted" style="color:#8a93a2;">Arrived</span> {{ line.created }}
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
|
||||
{% if quarantine_acl == 1 %}
|
||||
<!-- Actions -->
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="margin-top:14px;">
|
||||
<tr>
|
||||
<td class="btn-cell" style="padding-right:8px;">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="width:100%;">
|
||||
<tr>
|
||||
<td align="center" class="btn-primary-cell" style="border-radius:8px; background-color:#2b333f;">
|
||||
<a class="btn-a" href="https://{{ hostname }}/qhandler/release/{{ line.qhash }}" target="_blank" style="display:inline-block; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; font-size:14px; font-weight:600; color:#ffffff; padding:10px 18px; border-radius:8px;">{% if line.action == "reject" %}Release to inbox{% else %}Send copy to inbox{% endif %}</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
<td class="btn-cell">
|
||||
<table role="presentation" cellpadding="0" cellspacing="0" border="0" style="width:100%;">
|
||||
<tr>
|
||||
<td align="center" class="btn-secondary-cell" style="border-radius:8px; background-color:#eceef1;">
|
||||
<a class="btn-a" href="https://{{ hostname }}/qhandler/delete/{{ line.qhash }}" target="_blank" style="display:inline-block; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; font-size:14px; font-weight:600; color:#2b333f; padding:10px 18px; border-radius:8px;">Delete</a>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
{% endif %}
|
||||
|
||||
</td>
|
||||
</tr>
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
|
||||
<!-- Footer note -->
|
||||
<tr>
|
||||
<td class="px" style="padding-top:24px;">
|
||||
<hr class="divider" style="border:0; border-top:1px solid #e4e7ec; margin:0 0 16px 0;">
|
||||
<p class="text-muted" style="margin:0; font-family:-apple-system,BlinkMacSystemFont,'Segoe UI',Roboto,Helvetica,Arial,sans-serif; font-size:12px; line-height:18px; color:#8a93a2;">
|
||||
This is an automated message from your mail server ({{ hostname }}). You receive it because quarantine notifications are enabled for your mailbox.
|
||||
</p>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
|
||||
</table>
|
||||
</td>
|
||||
</tr>
|
||||
{% endfor %}
|
||||
</table>
|
||||
</p>
|
||||
</body>
|
||||
</table>
|
||||
</body>
|
||||
</html>
|
||||
|
|
|
|||
|
|
@ -1,4 +1,29 @@
|
|||
<?php
|
||||
// Resolve the default quarantine setting for new mailboxes.
|
||||
// Order of precedence: server-wide default (Redis, set in the admin quarantine
|
||||
// settings) -> compile-time default ($MAILBOX_DEFAULT_ATTRIBUTES in vars.inc.php).
|
||||
// $key is either 'notification' or 'category'.
|
||||
function get_quarantine_default($key) {
|
||||
global $redis, $MAILBOX_DEFAULT_ATTRIBUTES;
|
||||
$redis_keys = array(
|
||||
'notification' => 'Q_DEF_NOTIFICATION',
|
||||
'category' => 'Q_DEF_CATEGORY'
|
||||
);
|
||||
$attr_keys = array(
|
||||
'notification' => 'quarantine_notification',
|
||||
'category' => 'quarantine_category'
|
||||
);
|
||||
if (!isset($redis_keys[$key])) {
|
||||
return null;
|
||||
}
|
||||
try {
|
||||
$value = $redis->Get($redis_keys[$key]);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$value = false;
|
||||
}
|
||||
return ($value !== false && $value !== '') ? $value : $MAILBOX_DEFAULT_ATTRIBUTES[$attr_keys[$key]];
|
||||
}
|
||||
function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
||||
global $pdo;
|
||||
global $redis;
|
||||
|
|
@ -1109,8 +1134,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$eas_access = (isset($_data['eas_access'])) ? intval($_data['eas_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['eas_access']);
|
||||
$dav_access = (isset($_data['dav_access'])) ? intval($_data['dav_access']) : intval($MAILBOX_DEFAULT_ATTRIBUTES['dav_access']);
|
||||
$relayhost = (isset($_data['relayhost'])) ? intval($_data['relayhost']) : 0;
|
||||
$quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification']);
|
||||
$quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
|
||||
$quarantine_notification = (isset($_data['quarantine_notification'])) ? strval($_data['quarantine_notification']) : strval(get_quarantine_default('notification'));
|
||||
$quarantine_category = (isset($_data['quarantine_category'])) ? strval($_data['quarantine_category']) : strval(get_quarantine_default('category'));
|
||||
// Validate quarantine_category
|
||||
if (!in_array($quarantine_category, array('add_header', 'reject', 'all'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
@ -1740,8 +1765,8 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
|
|||
$attr["quota"] = isset($_data['quota']) ? intval($_data['quota']) * 1048576 : 0;
|
||||
$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_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval($MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category']);
|
||||
$attr["quarantine_notification"] = (!empty($_data['quarantine_notification'])) ? $_data['quarantine_notification'] : strval(get_quarantine_default('notification'));
|
||||
$attr["quarantine_category"] = (!empty($_data['quarantine_category'])) ? $_data['quarantine_category'] : strval(get_quarantine_default('category'));
|
||||
// Validate quarantine_category
|
||||
if (!in_array($attr["quarantine_category"], array('add_header', 'reject', 'all'))) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ function quarantine($_action, $_data = null) {
|
|||
global $pdo;
|
||||
global $redis;
|
||||
global $lang;
|
||||
global $MAILBOX_DEFAULT_ATTRIBUTES;
|
||||
$_data_log = $_data;
|
||||
switch ($_action) {
|
||||
case 'quick_delete':
|
||||
|
|
@ -22,7 +23,7 @@ function quarantine($_action, $_data = null) {
|
|||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`
|
||||
WHERE `qhash` = :hash
|
||||
WHERE `qhash` = :hash
|
||||
AND user_acl.quarantine = 1
|
||||
AND rcpt IN (SELECT username FROM mailbox)');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
|
|
@ -65,7 +66,7 @@ function quarantine($_action, $_data = null) {
|
|||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT `id` FROM `quarantine` LEFT OUTER JOIN `user_acl` ON `user_acl`.`username` = `rcpt`
|
||||
WHERE `qhash` = :hash
|
||||
WHERE `qhash` = :hash
|
||||
AND `user_acl`.`quarantine` = 1
|
||||
AND `username` IN (SELECT `username` FROM `mailbox`)');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
|
|
@ -331,6 +332,9 @@ function quarantine($_action, $_data = null) {
|
|||
$max_age = 365;
|
||||
}
|
||||
$exclude_domains = (array)$_data['exclude_domains'];
|
||||
// Server-wide default quarantine notification settings for new mailboxes
|
||||
$def_notification = (in_array($_data['def_notification'], array('never', 'hourly', 'daily', 'weekly'))) ? $_data['def_notification'] : 'never';
|
||||
$def_category = (in_array($_data['def_category'], array('add_header', 'reject', 'all'))) ? $_data['def_category'] : 'reject';
|
||||
try {
|
||||
$redis->Set('Q_RETENTION_SIZE', intval($retention_size));
|
||||
$redis->Set('Q_MAX_SIZE', intval($max_size));
|
||||
|
|
@ -343,6 +347,8 @@ function quarantine($_action, $_data = null) {
|
|||
$redis->Set('Q_REDIRECT', $redirect);
|
||||
$redis->Set('Q_SUBJ', $subject);
|
||||
$redis->Set('Q_HTML', $html);
|
||||
$redis->Set('Q_DEF_NOTIFICATION', $def_notification);
|
||||
$redis->Set('Q_DEF_CATEGORY', $def_category);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
@ -358,6 +364,55 @@ function quarantine($_action, $_data = null) {
|
|||
'msg' => 'saved_settings'
|
||||
);
|
||||
}
|
||||
// Force the server-wide default onto all existing mailboxes (overwrites user overrides)
|
||||
elseif ($_data['action'] == 'apply_existing') {
|
||||
if ($_SESSION['mailcow_cc_role'] != "admin") {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => 'access_denied'
|
||||
);
|
||||
return false;
|
||||
}
|
||||
// Resolve the default to apply: prefer the values submitted with the form
|
||||
// (the settings form is merged into this request), fall back to the stored default.
|
||||
$def_notification = (in_array($_data['def_notification'], array('never', 'hourly', 'daily', 'weekly'))) ? $_data['def_notification'] : get_quarantine_default('notification');
|
||||
$def_category = (in_array($_data['def_category'], array('add_header', 'reject', 'all'))) ? $_data['def_category'] : get_quarantine_default('category');
|
||||
try {
|
||||
// Keep the stored default in sync with what we are forcing onto mailboxes
|
||||
$redis->Set('Q_DEF_NOTIFICATION', $def_notification);
|
||||
$redis->Set('Q_DEF_CATEGORY', $def_category);
|
||||
$stmt = $pdo->prepare("UPDATE `mailbox` SET `attributes` = JSON_SET(`attributes`,
|
||||
'$.quarantine_notification', :quarantine_notification,
|
||||
'$.quarantine_category', :quarantine_category)");
|
||||
$stmt->execute(array(
|
||||
':quarantine_notification' => $def_notification,
|
||||
':quarantine_category' => $def_category
|
||||
));
|
||||
$affected = $stmt->rowCount();
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('redis_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'success',
|
||||
'log' => array(__FUNCTION__, $_action, $_data_log),
|
||||
'msg' => array('quarantine_defaults_applied', $affected)
|
||||
);
|
||||
}
|
||||
// Release item
|
||||
elseif ($_data['action'] == 'release' || $_data['action'] == 'learnham') {
|
||||
if (!is_array($_data['id'])) {
|
||||
|
|
@ -791,6 +846,8 @@ function quarantine($_action, $_data = null) {
|
|||
if (empty($settings['html_tmpl'])) {
|
||||
$settings['html_tmpl'] = htmlspecialchars(file_get_contents("/tpls/quarantine.tpl"));
|
||||
}
|
||||
$settings['def_notification'] = $redis->Get('Q_DEF_NOTIFICATION') ?: $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_notification'];
|
||||
$settings['def_category'] = $redis->Get('Q_DEF_CATEGORY') ?: $MAILBOX_DEFAULT_ATTRIBUTES['quarantine_category'];
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
|
|
@ -833,7 +890,7 @@ function quarantine($_action, $_data = null) {
|
|||
)));
|
||||
return false;
|
||||
}
|
||||
$stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE `qhash` = :hash');
|
||||
$stmt = $pdo->prepare('SELECT * FROM `quarantine` WHERE `qhash` = :hash');
|
||||
$stmt->execute(array(':hash' => $hash));
|
||||
return $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -315,6 +315,11 @@
|
|||
"private_key": "Private key",
|
||||
"quarantine": "Quarantine",
|
||||
"quarantine_bcc": "Send a copy of all notifications (BCC) to this recipient:<br><small>Leave empty to disable. <b>Unsigned, unchecked mail. Should be delivered internally only.</b></small>",
|
||||
"quarantine_defaults_apply": "Apply default to all existing mailboxes",
|
||||
"quarantine_defaults_apply_confirm": "This will overwrite the quarantine notification interval and category of ALL existing mailboxes with the default selected above. User overrides will be lost. Continue?",
|
||||
"quarantine_defaults_apply_info": "Applies the default to <b>all existing mailboxes</b> and overwrites individual user settings. New mailboxes always inherit the default above.",
|
||||
"quarantine_defaults_category": "Default notification category for new mailboxes",
|
||||
"quarantine_defaults_notification": "Default notification interval for new mailboxes",
|
||||
"quarantine_exclude_domains": "Exclude domains and alias-domains",
|
||||
"quarantine_max_age": "Maximum age in days<br><small>Value must be equal to or greater than 1 day.</small>",
|
||||
"quarantine_max_score": "Discard notification if spam score of a mail is higher than this value:<br><small>Defaults to 9999.0</small>",
|
||||
|
|
@ -1190,6 +1195,7 @@
|
|||
"pushover_settings_edited": "Pushover settings successfully set, please verify credentials.",
|
||||
"qlearn_spam": "Message ID %s was learned as spam and deleted",
|
||||
"queue_command_success": "Queue command completed successfully",
|
||||
"quarantine_defaults_applied": "Default quarantine notification settings applied to %s existing mailbox(es)",
|
||||
"recipient_map_entry_deleted": "Recipient map ID %s has been deleted",
|
||||
"recipient_map_entry_saved": "Recipient map entry \"%s\" has been saved",
|
||||
"recovery_email_sent": "Recovery email sent to %s",
|
||||
|
|
|
|||
|
|
@ -62,6 +62,34 @@
|
|||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_def_notification">{{ lang.admin.quarantine_defaults_notification|raw }}</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" id="quarantine_def_notification" name="def_notification" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option {% if q_data.def_notification == 'never' %}selected{% endif %} value="never">{{ lang.user.never }}</option>
|
||||
<option {% if q_data.def_notification == 'hourly' %}selected{% endif %} value="hourly">{{ lang.user.hourly }}</option>
|
||||
<option {% if q_data.def_notification == 'daily' %}selected{% endif %} value="daily">{{ lang.user.daily }}</option>
|
||||
<option {% if q_data.def_notification == 'weekly' %}selected{% endif %} value="weekly">{{ lang.user.weekly }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_def_category">{{ lang.admin.quarantine_defaults_category|raw }}</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
<select data-width="100%" id="quarantine_def_category" name="def_category" class="selectpicker" title="{{ lang.tfa.select }}">
|
||||
<option {% if q_data.def_category == 'reject' %}selected{% endif %} value="reject">{{ lang.user.q_reject }}</option>
|
||||
<option {% if q_data.def_category == 'add_header' %}selected{% endif %} value="add_header">{{ lang.user.q_add_header }}</option>
|
||||
<option {% if q_data.def_category == 'all' %}selected{% endif %} value="all">{{ lang.user.q_all }}</option>
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-4">
|
||||
<div class="col-sm-8 offset-sm-4">
|
||||
<button type="button" class="btn btn-sm d-block d-sm-inline btn-warning" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"apply_existing"}' onclick="if(!confirm('{{ lang.admin.quarantine_defaults_apply_confirm }}')){event.stopImmediatePropagation();event.preventDefault();return false;}"><i class="bi bi-arrow-repeat"></i> {{ lang.admin.quarantine_defaults_apply }}</button>
|
||||
<p class="text-muted mt-2 mb-0">{{ lang.admin.quarantine_defaults_apply_info|raw }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<hr>
|
||||
<div class="row mb-2">
|
||||
<label class="col-sm-4 control-label text-sm-end" for="quarantine_release_format">{{ lang.admin.quarantine_release_format }}:</label>
|
||||
<div class="col-sm-8 col-md-6 col-lg-4 col-xl-3">
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue