public
nobgit
read
NobMail
Based on mailcow: dockerized
Languages
Repository composition by tracked source files.
PHP
49%
JavaScript
35%
HTML
9%
CSS
4%
Shell
2%
Python
1%
Lua
0%
Perl
0%
Ruby
0%
SCSS
0%
Create file
Wiki Documentation
Clone
https://nobgit.com/orgs/nobgit/nobmail.git
ssh://[email protected]:2222/orgs/nobgit/nobmail.git
Commit
[Web] Allow ratelimit time frame "day"; Allow to create announcements
767ae659
data/Dockerfiles/postfix/smtp_last_login.sh | 7 --
data/web/admin.php | 114 ++++++++++++++++------------
data/web/edit.php | 3 +
data/web/inc/footer.inc.php | 10 +--
data/web/inc/functions.customize.inc.php | 9 +++
data/web/inc/functions.ratelimit.inc.php | 4 +-
data/web/inc/header.inc.php | 8 ++
data/web/index.php | 3 +
data/web/lang/lang.de.json | 9 +++
data/web/lang/lang.en.json | 9 +++
data/web/modals/mailbox.php | 2 +
11 files changed, 112 insertions(+), 66 deletions(-)
delete mode 100755 data/Dockerfiles/postfix/smtp_last_login.sh
Diff
diff --git a/data/Dockerfiles/postfix/smtp_last_login.sh b/data/Dockerfiles/postfix/smtp_last_login.sh
deleted file mode 100755
index 5fd0ac49..00000000
--- a/data/Dockerfiles/postfix/smtp_last_login.sh
+++ /dev/null
@@ -1,7 +0,0 @@
-#!/bin/bash
-echo action=OK
-exit
-while read QUERY; do
- logger -t last_login -p mail.info "$QUERY"
-done
-echo action=OK
diff --git a/data/web/admin.php b/data/web/admin.php
index 96e4f189..783a9b87 100644
--- a/data/web/admin.php
+++ b/data/web/admin.php
@@ -117,10 +117,14 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<span style="font-size:12px" class="arrow rotate glyphicon glyphicon-menu-down"></span> API
</legend>
<div id="admin_api" class="collapse">
+ <div class="row">
<?php
$api_ro = admin_api('ro', 'get');
$api_rw = admin_api('rw', 'get');
?>
+ <div class="col-lg-12">
+ <p class="help-block"><?=$lang['admin']['api_info'];?></p>
+ </div>
<div class="col-lg-6">
<div class="panel panel-default">
<div class="panel-heading">
@@ -156,7 +160,6 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
- <p class="help-block"><?=$lang['admin']['api_info'];?></p>
<div class="btn-group">
<button class="btn btn-sm btn-success" name="admin_api[ro]" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-default admin-ays-dialog" name="admin_api_regen_key[ro]" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
@@ -168,52 +171,52 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
</div>
<div class="col-lg-6">
- <div class="panel panel-default">
- <div class="panel-heading">
- <h4 class="panel-title">⇄ Read-Write Access</h4>
- </div>
- <div class="panel-body">
- <form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
- <div class="form-group">
- <label class="control-label col-sm-3" for="allow_from_rw"><?=$lang['admin']['api_allow_from'];?>:</label>
- <div class="col-sm-9">
- <textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_rw" <?=($api_rw['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=htmlspecialchars($api_rw['allow_from']);?></textarea>
+ <div class="panel panel-default">
+ <div class="panel-heading">
+ <h4 class="panel-title">⇄ Read-Write Access</h4>
+ </div>
+ <div class="panel-body">
+ <form class="form-horizontal" autocapitalize="none" autocorrect="off" role="form" method="post">
+ <div class="form-group">
+ <label class="control-label col-sm-3" for="allow_from_rw"><?=$lang['admin']['api_allow_from'];?>:</label>
+ <div class="col-sm-9">
+ <textarea class="form-control textarea-code" rows="7" name="allow_from" id="allow_from_rw" <?=($api_rw['skip_ip_check'] == 1) ? 'disabled' : null;?> required><?=htmlspecialchars($api_rw['allow_from']);?></textarea>
+ </div>
</div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-3 col-sm-9">
- <label>
- <input type="checkbox" name="skip_ip_check" id="skip_ip_check_rw" <?=($api_rw['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
- </label>
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <label>
+ <input type="checkbox" name="skip_ip_check" id="skip_ip_check_rw" <?=($api_rw['skip_ip_check'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['api_skip_ip_check'];?>
+ </label>
+ </div>
</div>
- </div>
- <div class="form-group">
- <label class="control-label col-sm-3" for="admin_api_key"><?=$lang['admin']['api_key'];?>:</label>
- <div class="col-sm-9">
- <pre><?=(empty(htmlspecialchars($api_rw['api_key']))) ? '-' : htmlspecialchars($api_rw['api_key']);?></pre>
+ <div class="form-group">
+ <label class="control-label col-sm-3" for="admin_api_key"><?=$lang['admin']['api_key'];?>:</label>
+ <div class="col-sm-9">
+ <pre><?=(empty(htmlspecialchars($api_rw['api_key']))) ? '-' : htmlspecialchars($api_rw['api_key']);?></pre>
+ </div>
</div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-3 col-sm-9">
- <label>
- <input type="checkbox" name="active" <?=($api_rw['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
- </label>
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <label>
+ <input type="checkbox" name="active" <?=($api_rw['active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['activate_api'];?>
+ </label>
+ </div>
</div>
- </div>
- <div class="form-group">
- <div class="col-sm-offset-3 col-sm-9">
- <p class="help-block"><?=$lang['admin']['api_info'];?></p>
- <div class="btn-group">
- <button class="btn btn-sm btn-success" name="admin_api[rw]" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
- <button class="btn btn-sm btn-default admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
+ <div class="form-group">
+ <div class="col-sm-offset-3 col-sm-9">
+ <div class="btn-group">
+ <button class="btn btn-sm btn-success" name="admin_api[rw]" type="submit" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-sm btn-default admin-ays-dialog" name="admin_api_regen_key[rw]" type="submit" href="#"><?=$lang['admin']['regen_api_key'];?></button>
+ </div>
</div>
</div>
- </div>
- </form>
- </div>
- </div>
+ </form>
+ </div>
+ </div>
</div>
</div>
+ </div>
</div>
</div>
@@ -294,7 +297,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
<div class="form-group">
<div class="col-sm-offset-3 col-sm-9">
- <button type="submit" class="btn btn-default" id="rspamd_ui" name="rspamd_ui" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button type="submit" class="btn btn-sm btn-success" id="rspamd_ui" name="rspamd_ui" href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</div>
</div>
</form>
@@ -703,7 +706,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<textarea class="form-control" name="blacklist" rows="5"><?=$f2b_data['blacklist'];?></textarea>
</div>
<div class="btn-group">
- <button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-success" data-action="edit_selected" data-item="self" data-id="f2b" data-api-url='edit/fail2ban' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<a href="#" role="button" class="btn btn-default" data-toggle="modal" data-container="netfilter-mailcow" data-target="#RestartContainer"><span class="glyphicon glyphicon-refresh"></span> <?= $lang['header']['restart_netfilter']; ?></a>
</div>
</form>
@@ -840,7 +843,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
</div>
</div>
</div>
- <button class="btn btn-default" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-sm btn-success" data-action="edit_selected" data-item="self" data-id="quarantine" data-api-url='edit/quarantine' data-api-attr='{"action":"settings"}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
</div>
</div>
@@ -885,7 +888,7 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
data-item="quota_notification"
data-id="quota_notification"
data-api-url='edit/quota_notification'
- data-api-attr='{}'><?=$lang['user']['save_changes'];?></a>
+ data-api-attr='{}'><span class="glyphicon glyphicon-check"></span> <?=$lang['user']['save_changes'];?></a>
</div>
</div>
</div>
@@ -965,8 +968,8 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<input type="checkbox" name="active" value="1" <?=($rsetting_details['active_int'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['active'];?>
</label>
</div>
- <button class="btn btn-default" data-action="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
- <button class="btn btn-danger" data-action="delete_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#"><?=$lang['admin']['remove'];?></button>
+ <button class="btn btn-sm btn-success" data-action="edit_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url='edit/rsetting' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-sm btn-danger" data-action="delete_selected" data-item="<?=$rsetting_details['id'];?>" data-id="rsettings" data-api-url="delete/rsetting" data-api-attr='{}' href="#"><?=$lang['admin']['remove'];?></button>
</form>
</div>
<?php
@@ -1049,15 +1052,13 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
?>
</table>
<p><div class="btn-group">
- <button class="btn btn-sm btn-default" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-sm btn-success" data-action="edit_selected" data-item="admin" data-id="app_links" data-reload="no" data-api-url='edit/app_links' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
<button class="btn btn-sm btn-default" type="button" id="add_app_link_row"><?=$lang['admin']['add_row'];?></button>
</div></p>
</form>
<legend data-target="#ui_texts" style="padding-top:20px" unselectable="on"><?=$lang['admin']['ui_texts'];?></legend>
<div id="ui_texts">
- <?php
- $ui_texts = customize('get', 'ui_texts');
- ?>
+ <?php $ui_texts = customize('get', 'ui_texts'); ?>
<form class="form" data-id="uitexts" role="form" method="post">
<div class="form-group">
<label for="title_name"><?=$lang['admin']['title_name'];?>:</label>
@@ -1075,11 +1076,24 @@ if (!isset($_SESSION['gal']) && $license_cache = $redis->Get('LICENSE_STATUS_CAC
<label for="help_text"><?=$lang['admin']['help_text'];?>:</label>
<textarea class="form-control" id="help_text" name="help_text" rows="7"><?=$ui_texts['help_text'];?></textarea>
</div>
+ <hr>
+ <div class="form-group">
+ <p class="help-block"><?=$lang['admin']['ui_header_announcement_help'];?></p>
+ <label for="ui_announcement_type"><?=$lang['admin']['ui_header_announcement'];?>:</label>
+ <p><select multiple data-width="100%" name="ui_announcement_type" class="selectpicker show-tick" data-max-options="1" title="<?=$lang['admin']['ui_header_announcement_select'];?>">
+ <option <?=($ui_texts['ui_announcement_type'] == 'info') ? 'selected' : null;?> value="info"><?=$lang['admin']['ui_header_announcement_type_info'];?></option>
+ <option <?=($ui_texts['ui_announcement_type'] == 'warning') ? 'selected' : null;?> value="warning"><?=$lang['admin']['ui_header_announcement_type_warning'];?></option>
+ <option <?=($ui_texts['ui_announcement_type'] == 'danger') ? 'selected' : null;?> value="danger"><?=$lang['admin']['ui_header_announcement_type_danger'];?></option>
+ </select></p>
+ <p><textarea class="form-control" id="ui_announcement_text" name="ui_announcement_text" rows="7"><?=$ui_texts['ui_announcement_text'];?></textarea></p>
+ <p><input type="checkbox" name="ui_announcement_active" <?=($ui_texts['ui_announcement_active'] == 1) ? 'checked' : null;?>> <?=$lang['admin']['ui_header_announcement_active'];?></p>
+ </div>
+ <hr>
<div class="form-group">
<label for="ui_footer"><?=$lang['admin']['ui_footer'];?>:</label>
<textarea class="form-control" id="ui_footer" name="ui_footer" rows="7"><?=$ui_texts['ui_footer'];?></textarea>
</div>
- <button class="btn btn-default" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
+ <button class="btn btn-sm btn-success" data-action="edit_selected" data-item="ui" data-id="uitexts" data-api-url='edit/ui_texts' data-api-attr='{}' href="#"><span class="glyphicon glyphicon-check"></span> <?=$lang['admin']['save'];?></button>
</form>
</div>
</div>
diff --git a/data/web/edit.php b/data/web/edit.php
index 5187b552..f75ca2fc 100644
--- a/data/web/edit.php
+++ b/data/web/edit.php
@@ -382,6 +382,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
+ <option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">
@@ -537,6 +538,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
+ <option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">
@@ -833,6 +835,7 @@ if (isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
+ <option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
<div class="form-group">
diff --git a/data/web/inc/footer.inc.php b/data/web/inc/footer.inc.php
index 99663434..b954bca8 100644
--- a/data/web/inc/footer.inc.php
+++ b/data/web/inc/footer.inc.php
@@ -182,13 +182,9 @@ $(document).ready(function() {
</script>
<div class="container footer">
- <?php
- if (!empty($UI_TEXTS['ui_footer'])):
- ?>
- <hr><?=$UI_TEXTS['ui_footer'];?>
- <?php
- endif;
- ?>
+ <?php if (!empty($UI_TEXTS['ui_footer'])) { ?>
+ <hr><?=$UI_TEXTS['ui_footer'];?>
+ <?php } ?>
</div>
</body>
</html>
diff --git a/data/web/inc/functions.customize.inc.php b/data/web/inc/functions.customize.inc.php
index 207eddbf..f4c74d86 100644
--- a/data/web/inc/functions.customize.inc.php
+++ b/data/web/inc/functions.customize.inc.php
@@ -113,12 +113,18 @@ function customize($_action, $_item, $_data = null) {
$apps_name = $_data['apps_name'];
$help_text = $_data['help_text'];
$ui_footer = $_data['ui_footer'];
+ $ui_announcement_text = $_data['ui_announcement_text'];
+ $ui_announcement_type = (in_array($_data['ui_announcement_type'], array('info', 'warning', 'danger'))) ? $_data['ui_announcement_type'] : false;
+ $ui_announcement_active = (!empty($_data['ui_announcement_active']) ? 1 : 0);
try {
$redis->set('TITLE_NAME', htmlspecialchars($title_name));
$redis->set('MAIN_NAME', htmlspecialchars($main_name));
$redis->set('APPS_NAME', htmlspecialchars($apps_name));
$redis->set('HELP_TEXT', $help_text);
$redis->set('UI_FOOTER', $ui_footer);
+ $redis->set('UI_ANNOUNCEMENT_TEXT', $ui_announcement_text);
+ $redis->set('UI_ANNOUNCEMENT_TYPE', $ui_announcement_type);
+ $redis->set('UI_ANNOUNCEMENT_ACTIVE', $ui_announcement_active);
}
catch (RedisException $e) {
$_SESSION['return'][] = array(
@@ -208,6 +214,9 @@ function customize($_action, $_item, $_data = null) {
$redis->del('UI_IMPRESS');
}
$data['ui_footer'] = ($ui_footer = $redis->get('UI_FOOTER')) ? $ui_footer : false;
+ $data['ui_announcement_text'] = ($ui_announcement_text = $redis->get('UI_ANNOUNCEMENT_TEXT')) ? $ui_announcement_text : false;
+ $data['ui_announcement_type'] = ($ui_announcement_type = $redis->get('UI_ANNOUNCEMENT_TYPE')) ? $ui_announcement_type : false;
+ $data['ui_announcement_active'] = ($redis->get('UI_ANNOUNCEMENT_ACTIVE') == 1) ? 1 : 0;
return $data;
}
catch (RedisException $e) {
diff --git a/data/web/inc/functions.ratelimit.inc.php b/data/web/inc/functions.ratelimit.inc.php
index efde5ec5..57a78e5f 100644
--- a/data/web/inc/functions.ratelimit.inc.php
+++ b/data/web/inc/functions.ratelimit.inc.php
@@ -25,7 +25,7 @@ function ratelimit($_action, $_scope, $_data = null) {
foreach ($objects as $object) {
$rl_value = intval($_data['rl_value']);
$rl_frame = $_data['rl_frame'];
- if (!in_array($rl_frame, array('s', 'm', 'h'))) {
+ if (!in_array($rl_frame, array('s', 'm', 'h', 'd'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
@@ -85,7 +85,7 @@ function ratelimit($_action, $_scope, $_data = null) {
foreach ($objects as $object) {
$rl_value = intval($_data['rl_value']);
$rl_frame = $_data['rl_frame'];
- if (!in_array($rl_frame, array('s', 'm', 'h'))) {
+ if (!in_array($rl_frame, array('s', 'm', 'h', 'd'))) {
$_SESSION['return'][] = array(
'type' => 'danger',
'log' => array(__FUNCTION__, $_action, $_scope, $_data_log),
diff --git a/data/web/inc/header.inc.php b/data/web/inc/header.inc.php
index 7ecf3d21..79e76de7 100644
--- a/data/web/inc/header.inc.php
+++ b/data/web/inc/header.inc.php
@@ -138,3 +138,11 @@
</div><!--/.container-fluid -->
</nav>
<form action="/" method="post" id="logout"><input type="hidden" name="logout"></form>
+ <?php if (!empty($UI_TEXTS['ui_announcement_text']) &&
+ in_array($UI_TEXTS['ui_announcement_type'], array('info', 'warning', 'danger')) &&
+ $UI_TEXTS['ui_announcement_active'] == 1 &&
+ parse_url($_SERVER['REQUEST_URI'], PHP_URL_PATH) != '/') { ?>
+ <div class="container">
+ <div class="alert alert-<?=$UI_TEXTS['ui_announcement_type'];?>"><?=$UI_TEXTS['ui_announcement_text'];?></div>
+ </div>
+ <?php } ?>
diff --git a/data/web/index.php b/data/web/index.php
index f0f622ed..3538c6b6 100644
--- a/data/web/index.php
+++ b/data/web/index.php
@@ -32,6 +32,9 @@ $_SESSION['index_query_string'] = $_SERVER['QUERY_STRING'];
<div class="panel-heading"><span class="glyphicon glyphicon-user" aria-hidden="true"></span> <?= $lang['login']['login']; ?></div>
<div class="panel-body">
<div class="text-center mailcow-logo"><img src="<?=($main_logo = customize('get', 'main_logo')) ? $main_logo : '/img/cow_mailcow.svg';?>" alt="mailcow"></div>
+ <?php if (!empty($UI_TEXTS['ui_announcement_text']) && in_array($UI_TEXTS['ui_announcement_type'], array('info', 'warning', 'danger')) && $UI_TEXTS['ui_announcement_active'] == 1) { ?>
+ <div class="alert alert-<?=$UI_TEXTS['ui_announcement_type'];?>"><?=$UI_TEXTS['ui_announcement_text'];?></div>
+ <?php } ?>
<legend><?= isset($_SESSION['oauth2_request']) ? $lang['oauth2']['authorize_app'] : $UI_TEXTS['main_name'];?></legend>
<?php
if (strpos($_SESSION['index_query_string'], 'mobileconfig') !== false) {
diff --git a/data/web/lang/lang.de.json b/data/web/lang/lang.de.json
index 925c3b4c..e6c39fd2 100644
--- a/data/web/lang/lang.de.json
+++ b/data/web/lang/lang.de.json
@@ -287,6 +287,15 @@
"transport_maps": "Transport Maps",
"transports_hint": "→ Transport Maps <b>überwiegen</b> senderabhängige Transport Maps.<br>\r\n→ Transport Maps ignorieren Mailbox-Einstellungen für ausgehende Verschlüsselung. Eine serverweite TLS-Richtlinie wird jedoch angewendet.<br>\r\n→ Der Transport erfolgt immer via \"smtp:\".<br>\r\n→ Adressen, die mit \"/localhost$/\" übereinstimmen, werden immer via \"local:\" transportiert, daher sind sie von einer Zieldefinition \"*\" ausgeschlossen.<br>\r\n→ Die Authentifizierung wird anhand des \"Next hop\" Parameters ermittelt. Hierbei würde bei einem beispielhaften Wert \"[host]:25\" immer zuerst \"host\" abfragt und <b>erst im Anschluss</b> \"[host]:25\". Dieses Verhalten schließt die <b>gleichzeitige Verwendung</b> von Einträgen der Art \"host\" sowie \"[host]:25\" aus.",
"ui_footer": "Footer (HTML zulässig)",
+ "ui_header_announcement": "Ankündigungen",
+ "ui_header_announcement_active": "Ankündigung aktivieren",
+ "ui_header_announcement_content": "Text (HTML zulässig)",
+ "ui_header_announcement_help": "Die Ankündigungsbox erzeugt einen deutlichen Hinweis für alle Benutzer und auf der Login-Seite der UI.",
+ "ui_header_announcement_select": "Ankündigungstyp auswählen",
+ "ui_header_announcement_type": "Typ",
+ "ui_header_announcement_type_info": "Info",
+ "ui_header_announcement_type_warning": "Wichtig",
+ "ui_header_announcement_type_danger": "Sehr wichtig",
"ui_texts": "UI Label und Texte",
"unban_pending": "ausstehend",
"unchanged_if_empty": "Unverändert, wenn leer",
diff --git a/data/web/lang/lang.en.json b/data/web/lang/lang.en.json
index 7399f8e5..c35088ac 100644
--- a/data/web/lang/lang.en.json
+++ b/data/web/lang/lang.en.json
@@ -286,6 +286,15 @@
"transport_maps": "Transport Maps",
"transports_hint": "→ A transport map entry <b>overrules</b> a sender-dependent transport map</b>.<br>\r\n→ Outbound TLS policy settings per-user are ignored and can only be enforced by TLS policy map entries.<br>\r\n→ The transport service for defined transports is always \"smtp:\".<br>\r\n→ Addresses matching \"/localhost$/\" will always be transported via \"local:\", therefore a \"*\" destination will not apply to those addresses.<br>\r\n→ To determine credentials for an exemplary next hop \"[host]:25\", Postfix <b>always</b> queries for \"host\" before searching for \"[host]:25\". This behavior makes it impossible to use \"host\" and \"[host]:25\" at the same time.",
"ui_footer": "Footer (HTML allowed)",
+ "ui_header_announcement": "Announcements",
+ "ui_header_announcement_active": "Set announcement active",
+ "ui_header_announcement_content": "Text (HTML allowed)",
+ "ui_header_announcement_help": "The announcement is visible for all logged in users and on the login screen of the UI.",
+ "ui_header_announcement_select": "Select announcement type",
+ "ui_header_announcement_type": "Type",
+ "ui_header_announcement_type_info": "Info",
+ "ui_header_announcement_type_warning": "Important",
+ "ui_header_announcement_type_danger": "Very important",
"ui_texts": "UI labels and texts",
"unban_pending": "unban pending",
"unchanged_if_empty": "If unchanged leave blank",
diff --git a/data/web/modals/mailbox.php b/data/web/modals/mailbox.php
index 66c741bb..e3dcc110 100644
--- a/data/web/modals/mailbox.php
+++ b/data/web/modals/mailbox.php
@@ -160,6 +160,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
+ <option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
</div>
@@ -375,6 +376,7 @@ if (!isset($_SESSION['mailcow_cc_role'])) {
<option value="s" <?=(isset($rl['frame']) && $rl['frame'] == 's') ? 'selected' : null;?>>msgs / second</option>
<option value="m" <?=(isset($rl['frame']) && $rl['frame'] == 'm') ? 'selected' : null;?>>msgs / minute</option>
<option value="h" <?=(isset($rl['frame']) && $rl['frame'] == 'h') ? 'selected' : null;?>>msgs / hour</option>
+ <option value="d" <?=(isset($rl['frame']) && $rl['frame'] == 'd') ? 'selected' : null;?>>msgs / day</option>
</select>
</div>
</div>