[Web] Feature: Allow copies of quota notifications to be sent via SMTP to internal or external addresses

[Web] Various style fixes
[Web] Remove unused or unnecessary dependencies
master
andryyy 2021-05-23 13:18:52 +02:00
parent beda649ecf
commit e6d5516c7f
No known key found for this signature in database
GPG Key ID: 8EC34FF2794E25EF
18 changed files with 117 additions and 85 deletions

View File

@ -115,9 +115,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<? // FIDO2 ?> <? // FIDO2 ?>
<legend style="margin-top:20px"> <legend style="margin-top:20px">
<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" style="margin-bottom: -5px;"> <i class="bi bi-shield-fill-check"></i>
<path d="M17.81 4.47c-.08 0-.16-.02-.23-.06C15.66 3.42 14 3 12.01 3c-1.98 0-3.86.47-5.57 1.41-.24.13-.54.04-.68-.2-.13-.24-.04-.55.2-.68C7.82 2.52 9.86 2 12.01 2c2.13 0 3.99.47 6.03 1.52.25.13.34.43.21.67-.09.18-.26.28-.44.28zM3.5 9.72c-.1 0-.2-.03-.29-.09-.23-.16-.28-.47-.12-.7.99-1.4 2.25-2.5 3.75-3.27C9.98 4.04 14 4.03 17.15 5.65c1.5.77 2.76 1.86 3.75 3.25.16.22.11.54-.12.7-.23.16-.54.11-.7-.12-.9-1.26-2.04-2.25-3.39-2.94-2.87-1.47-6.54-1.47-9.4.01-1.36.7-2.5 1.7-3.4 2.96-.08.14-.23.21-.39.21zm6.25 12.07c-.13 0-.26-.05-.35-.15-.87-.87-1.34-1.43-2.01-2.64-.69-1.23-1.05-2.73-1.05-4.34 0-2.97 2.54-5.39 5.66-5.39s5.66 2.42 5.66 5.39c0 .28-.22.5-.5.5s-.5-.22-.5-.5c0-2.42-2.09-4.39-4.66-4.39-2.57 0-4.66 1.97-4.66 4.39 0 1.44.32 2.77.93 3.85.64 1.15 1.08 1.64 1.85 2.42.19.2.19.51 0 .71-.11.1-.24.15-.37.15zm7.17-1.85c-1.19 0-2.24-.3-3.1-.89-1.49-1.01-2.38-2.65-2.38-4.39 0-.28.22-.5.5-.5s.5.22.5.5c0 1.41.72 2.74 1.94 3.56.71.48 1.54.71 2.54.71.24 0 .64-.03 1.04-.1.27-.05.53.13.58.41.05.27-.13.53-.41.58-.57.11-1.07.12-1.21.12zM14.91 22c-.04 0-.09-.01-.13-.02-1.59-.44-2.63-1.03-3.72-2.1-1.4-1.39-2.17-3.24-2.17-5.22 0-1.62 1.38-2.94 3.08-2.94 1.7 0 3.08 1.32 3.08 2.94 0 1.07.93 1.94 2.08 1.94s2.08-.87 2.08-1.94c0-3.77-3.25-6.83-7.25-6.83-2.84 0-5.44 1.58-6.61 4.03-.39.81-.59 1.76-.59 2.8 0 .78.07 2.01.67 3.61.1.26-.03.55-.29.64-.26.1-.55-.04-.64-.29-.49-1.31-.73-2.61-.73-3.96 0-1.2.23-2.29.68-3.24 1.33-2.79 4.28-4.6 7.51-4.6 4.55 0 8.25 3.51 8.25 7.83 0 1.62-1.38 2.94-3.08 2.94s-3.08-1.32-3.08-2.94c0-1.07-.93-1.94-2.08-1.94s-2.08.87-2.08 1.94c0 1.71.66 3.31 1.87 4.51.95.94 1.86 1.46 3.27 1.85.27.07.42.35.35.61-.05.23-.26.38-.47.38z"/>
</svg>
<?=$lang['fido2']['fido2_auth'];?></legend> <?=$lang['fido2']['fido2_auth'];?></legend>
<div class="row"> <div class="row">
<div class="col-sm-3 col-xs-5 text-right"><?=$lang['fido2']['known_ids'];?>:</div> <div class="col-sm-3 col-xs-5 text-right"><?=$lang['fido2']['known_ids'];?>:</div>
@ -134,7 +132,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
?> ?>
<tr> <tr>
<td> <td>
<?=($_SESSION['fido2_cid'] == $key_info['cid']) ? ' ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?> <?=($_SESSION['fido2_cid'] == $key_info['cid']) ? '<i class="bi bi-unlock-fill"></i> ' : NULL; ?><?=(!empty($key_info['fn']))?$key_info['fn']:$key_info['subject'];?>
</td> </td>
<td style="min-width:240px;text-align: right"> <td style="min-width:240px;text-align: right">
<form style="display:inline;" method="post"> <form style="display:inline;" method="post">
@ -1121,12 +1119,12 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<div class="panel panel-default"> <div class="panel panel-default">
<div class="panel-heading"><?=$lang['admin']['customize'];?></div> <div class="panel-heading"><?=$lang['admin']['customize'];?></div>
<div class="panel-body"> <div class="panel-body">
<legend><?=$lang['admin']['change_logo'];?></legend> <legend><i class="bi bi-file-image"></i> <?=$lang['admin']['change_logo'];?></legend>
<p class="help-block"><?=$lang['admin']['logo_info'];?></p> <p class="help-block"><?=$lang['admin']['logo_info'];?></p>
<form class="form-inline" role="form" method="post" enctype="multipart/form-data"> <form class="form-inline" role="form" method="post" enctype="multipart/form-data">
<p> <p>
<input type="file" name="main_logo" class="filestyle" data-buttonName="btn-default" data-buttonText="Select" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"> <input type="file" name="main_logo" accept="image/gif, image/jpeg, image/pjpeg, image/x-png, image/png, image/svg+xml"><br>
<button name="submit_main_logo" type="submit" class="btn btn-default"><i class="bi bi-cloud-arrow-up-fill"></i> <?=$lang['admin']['upload'];?></button> <button name="submit_main_logo" type="submit" class="btn btn-xs btn-default"><i class="bi bi-upload"></i> <?=$lang['admin']['upload'];?></button>
</p> </p>
</form> </form>
<?php <?php

File diff suppressed because one or more lines are too long

View File

@ -160,9 +160,6 @@ legend {
.lang-link-disabled { .lang-link-disabled {
cursor: not-allowed; cursor: not-allowed;
} }
.dkim-label {
margin: 0 0 2px !important;
}
.overlay { .overlay {
background: #fff; background: #fff;
position: absolute; position: absolute;
@ -236,3 +233,12 @@ table.footable>tbody>tr.footable-empty>td {
.dropdown-menu > li > a { .dropdown-menu > li > a {
font-size: 1rem !important; font-size: 1rem !important;
} }
.label {
font-size:inherit;
}
[class^="bi-"]::before, [class*=" bi-"]::before {
vertical-align: -0.2em !important;
}
legend > [class^="bi-"]::before, legend > [class*=" bi-"]::before {
vertical-align: 0em !important;
}

View File

@ -82,3 +82,6 @@ table tbody tr td input[type="checkbox"] {
font-weight:bold; font-weight:bold;
color:white !important; color:white !important;
} }
.dkim-label {
margin: 0 0 8px !important;
}

View File

@ -53,8 +53,12 @@ table tbody tr {
table tbody tr td input[type="checkbox"] { table tbody tr td input[type="checkbox"] {
cursor: pointer; cursor: pointer;
} }
.label-last-login .bi {
font-size: 8pt !important;
}
.label-last-login { .label-last-login {
line-height: 2.5; line-height: 2.5;
color: #4a4a4a!important; color: #4a4a4a!important;
background-color: #ececec!important; background-color: #ececec!important;
} }

View File

@ -95,6 +95,4 @@ table tbody tr td input[type="checkbox"] {
font-size:110%; font-size:110%;
margin:20px; margin:20px;
} }
.label {
font-size:inherit;
}

View File

@ -254,15 +254,16 @@ if (isset($_SESSION['mailcow_cc_role'])) {
!empty($_GET["domain"])) { !empty($_GET["domain"])) {
$domain = $_GET["domain"]; $domain = $_GET["domain"];
$result = mailbox('get', 'domain_details', $domain); $result = mailbox('get', 'domain_details', $domain);
$quota_notification_bcc = quota_notification_bcc('get', $domain);
$rl = ratelimit('get', 'domain', $domain); $rl = ratelimit('get', 'domain', $domain);
$rlyhosts = relayhost('get'); $rlyhosts = relayhost('get');
if (!empty($result)) { if (!empty($result)) {
?> ?>
<ul class="nav nav-tabs"> <ul class="nav nav-tabs" role="tablist">
<li class="active"><a data-toggle="tab" href="#dedit"><?=$lang['edit']['domain'];?></a></li> <li class="active"><a data-toggle="tab" href="#dedit"><?=$lang['edit']['domain'];?></a></li>
<li><a data-toggle="tab" href="#dratelimit"><?=$lang['edit']['ratelimit'];?></a></li> <li><a data-toggle="tab" href="#dratelimit"><?=$lang['edit']['ratelimit'];?></a></li>
<li><a data-toggle="tab" href="#dspamfilter"><?=$lang['edit']['spam_filter'];?></a></li> <li><a data-toggle="tab" href="#dspamfilter"><?=$lang['edit']['spam_filter'];?></a></li>
<!-- <li><a data-toggle="tab" href="#dqwbcc"><?=$lang['edit']['quota_warning_bcc'];?></a></li> --> <li><a data-toggle="tab" href="#dqwbcc"><?=$lang['edit']['quota_warning_bcc'];?></a></li>
</ul> </ul>
<hr> <hr>
<div class="tab-content"> <div class="tab-content">
@ -469,6 +470,35 @@ if (isset($_SESSION['mailcow_cc_role'])) {
</div> </div>
</div> </div>
</div> </div>
<div id="dqwbcc" class="tab-pane">
<div class="row">
<div class="col-sm-12">
<h4><?=$lang['edit']['quota_warning_bcc'];?></h4>
<p><?=$lang['edit']['quota_warning_bcc_info'];?></p>
<form class="form-horizontal" data-id="quota_bcc">
<input type="hidden" value="0" name="active">
<div class="form-group">
<label class="control-label col-sm-2" for="script_data"><?=$lang['edit']['target_address'];?>:</label>
<div class="col-sm-10">
<textarea spellcheck="false" autocorrect="off" autocapitalize="none" class="form-control" rows="10" id="bcc_rcpt" name="bcc_rcpt"><?=implode(PHP_EOL, $quota_notification_bcc['bcc_rcpts']);?></textarea>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<div class="checkbox">
<label><input type="checkbox" value="1" name="active" <?=($quota_notification_bcc['active']=="1") ? "checked" : "";?>> <?=$lang['edit']['active'];?></label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button class="btn btn-success" data-action="edit_selected" data-id="quota_bcc" data-item="quota_bcc" data-api-url='edit/quota_notification_bcc' data-api-attr='{"domain":"<?=$domain;?>"}' href="#"><?=$lang['edit']['save'];?></button>
</div>
</div>
</form>
</div>
</div>
</div>
</div> </div>
<?php <?php
} }

View File

@ -684,6 +684,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
continue; continue;
} }
} }
$gotos = array_unique($gotos);
$gotos = array_filter($gotos); $gotos = array_filter($gotos);
if (empty($gotos)) { return false; } if (empty($gotos)) { return false; }
$goto = implode(",", $gotos); $goto = implode(",", $gotos);
@ -2082,6 +2083,7 @@ function mailbox($_action, $_type, $_data = null, $_extra = null) {
':address' => $address ':address' => $address
)); ));
} }
$gotos = array_unique($gotos);
$gotos = array_filter($gotos); $gotos = array_filter($gotos);
$goto = implode(",", $gotos); $goto = implode(",", $gotos);
} }

View File

@ -88,17 +88,27 @@ function quota_notification_bcc($_action, $_data = null) {
return false; return false;
} }
$active = intval($_data['active']); $active = intval($_data['active']);
$bcc_rcpt = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $_data['bcc_rcpt']); $bcc_rcpts = array_map('trim', preg_split( "/( |,|;|\n)/", $_data['bcc_rcpt']));
if (filter_var($bcc_rcpt, FILTER_VALIDATE_EMAIL) === false) { foreach ($bcc_rcpts as $i => &$rcpt) {
$rcpt = preg_replace('/[\x00-\x1F\x80-\xFF]/', '', $rcpt);
if (!empty($rcpt) && filter_var($rcpt, FILTER_VALIDATE_EMAIL) === false) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_data_log), 'log' => array(__FUNCTION__, $_action, $_data_log),
'msg' => 'access_denied' 'msg' => array('goto_invalid', htmlspecialchars($rcpt))
); );
return false; unset($bcc_rcpts[$i]);
continue;
}
}
$bcc_rcpts = array_unique($bcc_rcpts);
$bcc_rcpts = array_filter($bcc_rcpts);
if (empty($bcc_rcpts)) {
$active = 0;
} }
try { try {
$redis->hSet('QW_BCC', $domain, json_encode(array('bcc_rcpt' => $bcc_rcpt, 'active' => $active))); $redis->hSet('QW_BCC', $domain, json_encode(array('bcc_rcpts' => $bcc_rcpts, 'active' => $active)));
} }
catch (RedisException $e) { catch (RedisException $e) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
@ -115,7 +125,7 @@ function quota_notification_bcc($_action, $_data = null) {
); );
break; break;
case 'get': case 'get':
$domain = $_data['domain']; $domain = $_data;
if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) { if (!hasDomainAccess($_SESSION['mailcow_cc_username'], $_SESSION['mailcow_cc_role'], $domain)) {
$_SESSION['return'][] = array( $_SESSION['return'][] = array(
'type' => 'danger', 'type' => 'danger',

View File

@ -127,9 +127,9 @@
</ul> </ul>
</li> </li>
<?php } if (!isset($_SESSION['dual-login']) && isset($_SESSION['mailcow_cc_username'])) { ?> <?php } if (!isset($_SESSION['dual-login']) && isset($_SESSION['mailcow_cc_username'])) { ?>
<li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <i class="bi bi-x-circle"></i></a></li> <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?></b> <i class="bi bi-power"></i></a></li>
<?php } elseif (isset($_SESSION['dual-login'])) { ?> <?php } elseif (isset($_SESSION['dual-login'])) { ?>
<li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><i class="bi bi-x-circle"></i></a></li> <li class="logged-in-as"><a href="#" onclick="logout.submit()"><b class="username-lia"><?= htmlspecialchars($_SESSION['mailcow_cc_username']); ?> <span class="text-info">(<?= htmlspecialchars($_SESSION['dual-login']['username']); ?>)</span> </b><i class="bi bi-power"></i></a></li>
<?php } if (!preg_match('/y|yes/i', getenv('MASTER'))) { ?> <?php } if (!preg_match('/y|yes/i', getenv('MASTER'))) { ?>
<li class="text-warning slave-info">[ slave ]</li> <li class="text-warning slave-info">[ slave ]</li>
<?php } ?> <?php } ?>

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View File

@ -76,8 +76,8 @@ jQuery(function($){
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"}, {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}}, {"sorted": true,"name":"username","title":lang.username,"style":{"width":"250px"}},
{"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"}, {"name":"selected_domains","title":lang.admin_domains,"breakpoints":"xs sm"},
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -131,8 +131,8 @@ jQuery(function($){
"columns": [ "columns": [
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"}, {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"usr","title":lang.username,"style":{"width":"250px"}}, {"sorted": true,"name":"usr","title":lang.username,"style":{"width":"250px"}},
{"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"tfa_active","title":"TFA", "filterable": false,"style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -160,7 +160,7 @@ jQuery(function($){
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"}, {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}}, {"name":"host","type":"text","title":lang.host,"style":{"width":"250px"}},
{"name":"source","title":lang.source,"breakpoints":"xs sm"}, {"name":"source","title":lang.source,"breakpoints":"xs sm"},
{"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 'yes'==value?'&#10005;':'no'==value&&'&#10003;';}}, {"name":"keep_spam","title":lang.spamfilter, "type": "text","style":{"maxWidth":"80px","width":"80px"},"formatter": function(value){return 'yes'==value?'<i class="bi bi-x-lg"></i>':'no'==value&&'<i class="bi bi-check-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -188,7 +188,7 @@ jQuery(function($){
{"name":"hostname","type":"text","title":lang.host,"style":{"width":"250px"}}, {"name":"hostname","type":"text","title":lang.host,"style":{"width":"250px"}},
{"name":"username","title":lang.username,"breakpoints":"xs sm"}, {"name":"username","title":lang.username,"breakpoints":"xs sm"},
{"name":"used_by_domains","title":lang.in_use_by,"style":{"width":"110px"}, "type": "text","breakpoints":"xs sm"}, {"name":"used_by_domains","title":lang.in_use_by,"style":{"width":"110px"}, "type": "text","breakpoints":"xs sm"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -216,7 +216,7 @@ jQuery(function($){
{"name":"destination","type":"text","title":lang.destination,"style":{"width":"250px"}}, {"name":"destination","type":"text","title":lang.destination,"style":{"width":"250px"}},
{"name":"nexthop","type":"text","title":lang.nexthop,"style":{"width":"250px"}}, {"name":"nexthop","type":"text","title":lang.nexthop,"style":{"width":"250px"}},
{"name":"username","title":lang.username,"breakpoints":"xs sm"}, {"name":"username","title":lang.username,"breakpoints":"xs sm"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"220px","width":"220px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -337,7 +337,7 @@ jQuery(function($){
} else if (table == 'adminstable') { } else if (table == 'adminstable') {
$.each(data, function (i, item) { $.each(data, function (i, item) {
if (admin_username.toLowerCase() == item.username.toLowerCase()) { if (admin_username.toLowerCase() == item.username.toLowerCase()) {
item.usr = ' ' + item.username; item.usr = '<i class="bi bi-person-check"></i> ' + item.username;
} else { } else {
item.usr = item.username; item.usr = item.username;
} }

View File

@ -204,7 +204,7 @@ jQuery(function($){
function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})} function escapeHtml(n){return String(n).replace(/[&<>"'`=\/]/g,function(n){return entityMap[n]})}
// http://stackoverflow.com/questions/46155/validate-email-address-in-javascript // http://stackoverflow.com/questions/46155/validate-email-address-in-javascript
function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]} function humanFileSize(i){if(Math.abs(i)<1024)return i+" B";var B=["KiB","MiB","GiB","TiB","PiB","EiB","ZiB","YiB"],e=-1;do{i/=1024,++e}while(Math.abs(i)>=1024&&e<B.length-1);return i.toFixed(1)+" "+B[e]}
function unix_time_format(i){return""==i?'&#10005;':new Date(i?1e3*i:0).toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})} function unix_time_format(i){return""==i?'<i class="bi bi-x-lg"></i>':new Date(i?1e3*i:0).toLocaleDateString(void 0,{year:"numeric",month:"2-digit",day:"2-digit",hour:"2-digit",minute:"2-digit",second:"2-digit"})}
$(".refresh_table").on('click', function(e) { $(".refresh_table").on('click', function(e) {
e.preventDefault(); e.preventDefault();
var table_name = $(this).data('table'); var table_name = $(this).data('table');
@ -254,10 +254,10 @@ jQuery(function($){
{"name":"def_quota_for_mbox","title":lang.mailbox_defquota,"breakpoints":"xs sm md","style":{"width":"125px"}}, {"name":"def_quota_for_mbox","title":lang.mailbox_defquota,"breakpoints":"xs sm md","style":{"width":"125px"}},
{"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm","style":{"width":"125px"}}, {"name":"max_quota_for_mbox","title":lang.mailbox_quota,"breakpoints":"xs sm","style":{"width":"125px"}},
{"name":"rl","title":"RL","breakpoints":"xs sm md lg","style":{"maxWidth":"100px","width":"100px"}}, {"name":"rl","title":"RL","breakpoints":"xs sm md lg","style":{"maxWidth":"100px","width":"100px"}},
{"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm md lg","formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"backupmx","filterable": false,"style":{"maxWidth":"120px","width":"120px"},"title":lang.backup_mx,"breakpoints":"xs sm md lg","formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"domain_admins","title":lang.domain_admins,"style":{"word-break":"break-all","min-width":"200px"},"breakpoints":"xs sm md lg","filterable":(role == "admin"),"visible":(role == "admin")}, {"name":"domain_admins","title":lang.domain_admins,"style":{"word-break":"break-all","min-width":"200px"},"breakpoints":"xs sm md lg","filterable":(role == "admin"),"visible":(role == "admin")},
{"name":"xmpp","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":"XMPP","formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"xmpp","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":"XMPP","formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
], ],
"rows": $.ajax({ "rows": $.ajax({
@ -379,7 +379,7 @@ jQuery(function($){
}, },
{"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"}, {"name":"messages","filterable": false,"title":lang.msg_num,"breakpoints":"xs sm md"},
/* {"name":"rl","title":"RL","breakpoints":"all","style":{"width":"125px"}}, */ /* {"name":"rl","title":"RL","breakpoints":"all","style":{"width":"125px"}}, */
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':(0==value?'&#10005;':2==value&&'&#8212;');}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':(0==value?'<i class="bi bi-x-lg"></i>':2==value&&'&#8212;');}},
{"name":"action","filterable": false,"sortable": false,"style":{"min-width":"290px","text-align":"right"},"type":"html","title":lang.action,"breakpoints":"xs sm md"} {"name":"action","filterable": false,"sortable": false,"style":{"min-width":"290px","text-align":"right"},"type":"html","title":lang.action,"breakpoints":"xs sm md"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -497,7 +497,7 @@ jQuery(function($){
{"name":"kind","title":lang.kind}, {"name":"kind","title":lang.kind},
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"}, {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"multiple_bookings","filterable": false,"style":{"maxWidth":"150px","width":"140px"},"title":lang.multiple_bookings,"breakpoints":"xs sm"}, {"name":"multiple_bookings","filterable": false,"style":{"maxWidth":"150px","width":"140px"},"title":lang.multiple_bookings,"breakpoints":"xs sm"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -570,7 +570,7 @@ jQuery(function($){
{"name":"local_dest","title":lang.bcc_local_dest}, {"name":"local_dest","title":lang.bcc_local_dest},
{"name":"bcc_dest","title":lang.bcc_destinations}, {"name":"bcc_dest","title":lang.bcc_destinations},
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"}, {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -637,7 +637,7 @@ jQuery(function($){
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}}, {"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"recipient_map_old","title":lang.recipient_map_old}, {"name":"recipient_map_old","title":lang.recipient_map_old},
{"name":"recipient_map_new","title":lang.recipient_map_new}, {"name":"recipient_map_new","title":lang.recipient_map_new},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -702,7 +702,7 @@ jQuery(function($){
{"name":"dest","title":lang.tls_map_dest}, {"name":"dest","title":lang.tls_map_dest},
{"name":"policy","title":lang.tls_map_policy}, {"name":"policy","title":lang.tls_map_policy},
{"name":"parameters","title":lang.tls_map_parameters}, {"name":"parameters","title":lang.tls_map_parameters},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":(role == "admin" ? lang.action : ""),"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -774,8 +774,8 @@ jQuery(function($){
{"name":"domain","title":lang.domain,"breakpoints":"xs sm"}, {"name":"domain","title":lang.domain,"breakpoints":"xs sm"},
{"name":"public_comment","title":lang.public_comment,"breakpoints":"all"}, {"name":"public_comment","title":lang.public_comment,"breakpoints":"all"},
{"name":"private_comment","title":lang.private_comment,"breakpoints":"all"}, {"name":"private_comment","title":lang.private_comment,"breakpoints":"all"},
{"name":"sogo_visible","title":lang.sogo_visible,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';},"breakpoints":"all"}, {"name":"sogo_visible","title":lang.sogo_visible,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';},"breakpoints":"all"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -869,7 +869,7 @@ jQuery(function($){
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"}, {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}}, {"sorted": true,"name":"alias_domain","title":lang.alias,"style":{"width":"250px"}},
{"name":"target_domain","title":lang.target_domain,"type":"html"}, {"name":"target_domain","title":lang.target_domain,"type":"html"},
{"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"80px","width":"80px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"250px","width":"250px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,
@ -940,7 +940,7 @@ jQuery(function($){
{"name":"mins_interval","title":lang.mins_interval,"breakpoints":"all"}, {"name":"mins_interval","title":lang.mins_interval,"breakpoints":"all"},
{"name":"last_run","title":lang.last_run,"breakpoints":"xs sm md"}, {"name":"last_run","title":lang.last_run,"breakpoints":"xs sm md"},
{"name":"log","title":"Log"}, {"name":"log","title":"Log"},
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status}, {"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],

View File

@ -130,7 +130,7 @@ jQuery(function($){
{"name":"mins_interval","title":lang.interval + " (min)","breakpoints":"all"}, {"name":"mins_interval","title":lang.interval + " (min)","breakpoints":"all"},
{"name":"last_run","title":lang.last_run,"breakpoints":"all"}, {"name":"last_run","title":lang.last_run,"breakpoints":"all"},
{"name":"log","title":"Log"}, {"name":"log","title":"Log"},
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status}, {"name":"is_running","filterable": false,"style":{"maxWidth":"120px","width":"100px"},"title":lang.status},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"240px","width":"240px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
@ -192,7 +192,7 @@ jQuery(function($){
{"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"}, {"name":"chkbox","title":"","style":{"maxWidth":"60px","width":"60px","text-align":"center"},"filterable": false,"sortable": false,"type":"html"},
{"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}}, {"sorted": true,"name":"id","title":"ID","style":{"maxWidth":"60px","width":"60px","text-align":"center"}},
{"name":"name","title":lang.app_name}, {"name":"name","title":lang.app_name},
{"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'&#10003;':0==value&&'&#10005;';}}, {"name":"active","filterable": false,"style":{"maxWidth":"70px","width":"70px"},"title":lang.active,"formatter": function(value){return 1==value?'<i class="bi bi-check-lg"></i>':0==value&&'<i class="bi bi-x-lg"></i>';}},
{"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"} {"name":"action","filterable": false,"sortable": false,"style":{"text-align":"right","maxWidth":"180px","width":"180px"},"type":"html","title":lang.action,"breakpoints":"xs sm"}
], ],
"empty": lang.empty, "empty": lang.empty,

View File

@ -319,8 +319,14 @@ if (isset($_GET['query'])) {
} }
break; break;
case "get": case "get":
function process_get_return($data) { function process_get_return($data, $object = true) {
echo (!isset($data) || empty($data)) ? '{}' : json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT); if ($object === true) {
$ret_str = '{}';
}
else {
$ret_str = '[]';
}
echo (!isset($data) || empty($data)) ? $ret_str : json_encode($data, JSON_UNESCAPED_UNICODE | JSON_PRETTY_PRINT);
} }
// only allow GET requests to GET API endpoints // only allow GET requests to GET API endpoints
if ($_SERVER['REQUEST_METHOD'] != 'GET') { if ($_SERVER['REQUEST_METHOD'] != 'GET') {
@ -1169,10 +1175,10 @@ if (isset($_GET['query'])) {
// "all" will not print details // "all" will not print details
switch ($object) { switch ($object) {
case "all": case "all":
process_get_return(quarantine('get')); process_get_return(quarantine('get'), false);
break; break;
default: default:
process_get_return(quarantine('details', $object)); process_get_return(quarantine('details', $object), false);
break; break;
} }
break; break;
@ -1608,6 +1614,9 @@ if (isset($_GET['query'])) {
case "quota_notification": case "quota_notification":
process_edit_return(quota_notification('edit', $attr)); process_edit_return(quota_notification('edit', $attr));
break; break;
case "quota_notification_bcc":
process_edit_return(quota_notification_bcc('edit', $attr));
break;
case "mailq": case "mailq":
process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr))); process_edit_return(mailq('edit', array_merge(array('qid' => $items), $attr)));
break; break;

View File

@ -580,6 +580,7 @@
"pushover_verify": "Verbindung verifizieren", "pushover_verify": "Verbindung verifizieren",
"quota_mb": "Speicherplatz (MiB)", "quota_mb": "Speicherplatz (MiB)",
"quota_warning_bcc": "Quota-Warnung BCC", "quota_warning_bcc": "Quota-Warnung BCC",
"quota_warning_bcc_info": "Die Warnungen werden als separate Kopie an die nachstehenden Empfänger versendet. Dem Betreff wird der jeweilige Benutzername in Klammern (etwa <code>Quota-Warnung (user@example.com)</code>) angehangen.",
"ratelimit": "Rate Limit", "ratelimit": "Rate Limit",
"redirect_uri": "Redirect/Callback-URL", "redirect_uri": "Redirect/Callback-URL",
"relay_all": "Alle Empfänger-Adressen relayen", "relay_all": "Alle Empfänger-Adressen relayen",
@ -608,7 +609,7 @@
"spam_score": "Einen benutzerdefiniterten Spam-Score festlegen", "spam_score": "Einen benutzerdefiniterten Spam-Score festlegen",
"subfolder2": "Ziel-Ordner<br><small>(leer = kein Unterordner)</small>", "subfolder2": "Ziel-Ordner<br><small>(leer = kein Unterordner)</small>",
"syncjob": "Sync-Job bearbeiten", "syncjob": "Sync-Job bearbeiten",
"target_address": "Ziel-Adresse(n) <small>(getrennt durch Komma)</small>", "target_address": "Ziel-Adresse(n)",
"target_domain": "Ziel-Domain", "target_domain": "Ziel-Domain",
"timeout1": "Timeout für Verbindung zum Remote-Host", "timeout1": "Timeout für Verbindung zum Remote-Host",
"timeout2": "Timeout für Verbindung zum lokalen Host", "timeout2": "Timeout für Verbindung zum lokalen Host",

View File

@ -578,6 +578,7 @@
"pushover_verify": "Verify credentials", "pushover_verify": "Verify credentials",
"quota_mb": "Quota (MiB)", "quota_mb": "Quota (MiB)",
"quota_warning_bcc": "Quota warning BCC", "quota_warning_bcc": "Quota warning BCC",
"quota_warning_bcc_info": "Warnings will be sent as separate copies to the following recipients. The subject will be suffixed by the corresponding username in brackets, for example: <code>Quota warning (user@example.com)</code>.",
"ratelimit": "Rate limit", "ratelimit": "Rate limit",
"redirect_uri": "Redirect/Callback URL", "redirect_uri": "Redirect/Callback URL",
"relay_all": "Relay all recipients", "relay_all": "Relay all recipients",