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
Use Redis for forwarded_hosts, some fixes
74359f6d
data/web/admin.php | 39 ++++++--------
data/web/inc/functions.inc.php | 115 ++++++++++++++++++++++++-----------------
data/web/inc/spf.inc.php | 11 ++--
data/web/inc/vars.inc.php | 2 +-
data/web/lang/lang.de.php | 1 +
data/web/lang/lang.en.php | 1 +
6 files changed, 95 insertions(+), 74 deletions(-)
Diff
diff --git a/data/web/admin.php b/data/web/admin.php
index df442b68..b2962079 100644
--- a/data/web/admin.php
+++ b/data/web/admin.php
@@ -292,24 +292,25 @@ $tfa_data = get_tfa();
</thead>
<tbody>
<?php
- $forwarding_hosts = get_forwarding_hosts();
- if ($forwarding_hosts) {
- foreach ($forwarding_hosts as $host) {
+ $fwd_hosts = get_forwarding_hosts();
+ if (!empty($fwd_hosts)) {
+ foreach ($fwd_hosts as $host => $attr) {
?>
<tr id="data">
- <td><?=htmlspecialchars(strtolower($host->host));?></td>
- <td><?=htmlspecialchars(strtolower($host->source));?></td>
+ <td><?=htmlspecialchars($host);?></td>
+ <td><?=htmlspecialchars($attr['source']);?></td>
+ <td><?=($attr['keep_spam'] == "no") ? $lang['admin']['yes'] : $lang['admin']['no'];?></td>
<td style="text-align: right;">
<div class="btn-group">
- <a href="delete.php?forwardinghost=<?=$host->host;?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['admin']['remove'];?></a>
+ <a href="delete.php?forwardinghost=<?=htmlspecialchars($host);?>" class="btn btn-xs btn-danger"><span class="glyphicon glyphicon-trash"></span> <?=$lang['admin']['remove'];?></a>
</div>
</td>
</td>
</tr>
-
<?php
}
- } else {
+ }
+ else {
?>
<tr id="no-data"><td colspan="4" style="text-align: center; font-style: italic;"><?=$lang['admin']['no_record'];?></td></tr>
<?php
@@ -321,24 +322,18 @@ $tfa_data = get_tfa();
</form>
<legend><?=$lang['admin']['add_forwarding_host'];?></legend>
<p class="help-block"><?=$lang['admin']['forwarding_hosts_add_hint'];?></p>
- <form class="form-horizontal" role="form" method="post">
- <div class="form-group">
- <label class="control-label col-sm-2" for="hostname"><?=$lang['edit']['host'];?>:</label>
- <div class="col-sm-10">
- <input type="text" class="form-control" name="hostname" id="hostname" required>
- </div>
- </div>
+ <form class="form-inline" role="form" method="post">
<div class="form-group">
- <label class="control-label col-sm-2" for="filter_spam"><?=$lang['user']['spamfilter'];?>:</label>
- <div class="col-sm-10">
- <input type="checkbox" class="form-control" name="filter_spam" id="filter_spam">
- </div>
+ <label for="hostname"><?=$lang['edit']['host'];?></label>
+ <input class="form-control" id="hostname" name="hostname" placeholder="example.org" required>
</div>
<div class="form-group">
- <div class="col-sm-offset-2 col-sm-10">
- <button type="submit" name="add_forwarding_host" class="btn btn-default"><?=$lang['admin']['add'];?></button>
- </div>
+ <select data-width="200px" class="form-control" id="filter_spam" name="filter_spam" title="<?=$lang['user']['spamfilter'];?>" required>
+ <option value="1"><?=$lang['admin']['active'];?></option>
+ <option value="0"><?=$lang['admin']['inactive'];?></option>
+ </select>
</div>
+ <button type="submit" name="add_forwarding_host" class="btn btn-default"><span class="glyphicon glyphicon-plus"></span> <?=$lang['admin']['add'];?></button>
</form>
</div>
</div>
diff --git a/data/web/inc/functions.inc.php b/data/web/inc/functions.inc.php
index 2000aad2..a2b2fba8 100644
--- a/data/web/inc/functions.inc.php
+++ b/data/web/inc/functions.inc.php
@@ -5100,14 +5100,29 @@ function get_u2f_registrations($username) {
return $sel->fetchAll(PDO::FETCH_OBJ);
}
function get_forwarding_hosts() {
- global $pdo;
- $sel = $pdo->prepare("SELECT * FROM `forwarding_hosts`");
- $sel->execute();
- return $sel->fetchAll(PDO::FETCH_OBJ);
+ global $redis;
+ $data = array();
+ try {
+ $wl_hosts = $redis->hGetAll('WHITELISTED_FWD_HOST');
+ if (!empty($wl_hosts)) {
+ foreach ($wl_hosts as $host => $source) {
+ $data[$host]['keep_spam'] = ($redis->hGet('KEEP_SPAM', $host)) ? "yes" : "no";
+ $data[$host]['source'] = $source;
+ }
+ }
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'] = array(
+ 'type' => 'danger',
+ 'msg' => 'Redis: '.$e
+ );
+ return false;
+ }
+ return $data;
}
function add_forwarding_host($postarray) {
require_once 'spf.inc.php';
- global $pdo;
+ global $redis;
global $lang;
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'] = array(
@@ -5117,20 +5132,21 @@ function add_forwarding_host($postarray) {
return false;
}
$source = $postarray['hostname'];
- $host = $postarray['hostname'];
- $filter_spam = !empty($postarray['filter_spam']);
- $hosts = array();
- if (preg_match('/^[0-9a-fA-F:\/]+$/', $host)) { // IPv6 address
- $hosts = array($host);
- }
- elseif (preg_match('/^[0-9\.\/]+$/', $host)) { // IPv4 address
+ $host = trim($postarray['hostname']);
+ $filter_spam = $postarray['filter_spam'];
+ if (isset($postarray['filter_spam']) && $postarray['filter_spam'] == 1) {
+ $filter_spam = 1;
+ }
+ else {
+ $filter_spam = 0;
+ }
+ if (filter_var($host, FILTER_VALIDATE_IP)) {
$hosts = array($host);
- }
+ }
else {
$hosts = get_outgoing_hosts_best_guess($host);
}
- if (!$hosts)
- {
+ if (!$hosts) {
$_SESSION['return'] = array(
'type' => 'danger',
'msg' => 'Invalid host specified: '. htmlspecialchars($host)
@@ -5138,23 +5154,22 @@ function add_forwarding_host($postarray) {
return false;
}
foreach ($hosts as $host) {
- if ($source == $host)
- $source = '';
- try {
- $stmt = $pdo->prepare("REPLACE INTO `forwarding_hosts` (`host`, `source`, `filter_spam`) VALUES (:host, :source, :filter_spam)");
- $stmt->execute(array(
- ':host' => $host,
- ':source' => $source,
- ':filter_spam' => $filter_spam ? 1 : 0,
- ));
- }
- catch (PDOException $e) {
- $_SESSION['return'] = array(
- 'type' => 'danger',
- 'msg' => 'MySQL: '.$e
- );
- return false;
- }
+ try {
+ $redis->hSet('WHITELISTED_FWD_HOST', $host, $source);
+ if ($filter_spam == 0) {
+ $redis->hSet('KEEP_SPAM', $host, 1);
+ }
+ elseif ($redis->hGet('KEEP_SPAM', $host)) {
+ $redis->hDel('KEEP_SPAM', $host);
+ }
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'] = array(
+ 'type' => 'danger',
+ 'msg' => 'Redis: '.$e
+ );
+ return false;
+ }
}
$_SESSION['return'] = array(
'type' => 'success',
@@ -5162,7 +5177,7 @@ function add_forwarding_host($postarray) {
);
}
function delete_forwarding_host($postarray) {
- global $pdo;
+ global $redis;
global $lang;
if ($_SESSION['mailcow_cc_role'] != "admin") {
$_SESSION['return'] = array(
@@ -5171,20 +5186,26 @@ function delete_forwarding_host($postarray) {
);
return false;
}
- $host = $postarray['forwardinghost'];
- try {
- $stmt = $pdo->prepare("DELETE FROM `forwarding_hosts` WHERE `host` = :host");
- $stmt->execute(array(
- ':host' => $host,
- ));
- }
- catch (PDOException $e) {
- $_SESSION['return'] = array(
- 'type' => 'danger',
- 'msg' => 'MySQL: '.$e
- );
- return false;
- }
+ if (!is_array($postarray['forwardinghost'])) {
+ $hosts = array();
+ $hosts[] = $postarray['forwardinghost'];
+ }
+ else {
+ $hosts = $postarray['forwardinghost'];
+ }
+ foreach ($hosts as $host) {
+ try {
+ return $redis->hDel('WHITELISTED_FWD_HOST', $host);
+ return $redis->hDel('KEEP_SPAM', $host);
+ }
+ catch (RedisException $e) {
+ $_SESSION['return'] = array(
+ 'type' => 'danger',
+ 'msg' => 'Redis: '.$e
+ );
+ return false;
+ }
+ }
$_SESSION['return'] = array(
'type' => 'success',
'msg' => sprintf($lang['success']['forwarding_host_removed'], htmlspecialchars($host))
diff --git a/data/web/inc/spf.inc.php b/data/web/inc/spf.inc.php
index 09a724f5..18dd2893 100644
--- a/data/web/inc/spf.inc.php
+++ b/data/web/inc/spf.inc.php
@@ -1,4 +1,6 @@
<?php
+error_reporting(0);
+
function get_spf_allowed_hosts($domain)
{
$hosts = array();
@@ -85,10 +87,11 @@ function get_mx_hosts($domain)
$hosts = array();
try {
$mx_records = dns_get_record($domain, DNS_MX);
- foreach ($mx_records as $mx_record)
- {
- $new_hosts = get_a_hosts($mx_record['target']);
- $hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
+ if ($mx_records) {
+ foreach ($mx_records as $mx_record) {
+ $new_hosts = get_a_hosts($mx_record['target']);
+ $hosts = array_unique(array_merge($hosts,$new_hosts), SORT_REGULAR);
+ }
}
}
catch (Exception $e) {
diff --git a/data/web/inc/vars.inc.php b/data/web/inc/vars.inc.php
index faef565d..67c6c34e 100644
--- a/data/web/inc/vars.inc.php
+++ b/data/web/inc/vars.inc.php
@@ -1,5 +1,5 @@
<?php
-error_reporting(E_ERROR | E_WARNING);
+error_reporting(E_ERROR);
//error_reporting(E_ALL);
/*
diff --git a/data/web/lang/lang.de.php b/data/web/lang/lang.de.php
index b0c86b09..a6a856e6 100644
--- a/data/web/lang/lang.de.php
+++ b/data/web/lang/lang.de.php
@@ -450,6 +450,7 @@ $lang['admin']['configuration'] = 'Konfiguration';
$lang['admin']['password'] = 'Passwort';
$lang['admin']['password_repeat'] = 'Passwort (Wiederholung)';
$lang['admin']['active'] = 'Aktiv';
+$lang['admin']['inactive'] = 'Inaktiv';
$lang['admin']['action'] = 'Aktion';
$lang['admin']['add_domain_admin'] = 'Domain-Administrator hinzufügen';
$lang['admin']['admin_domains'] = 'Domain-Zuweisungen';
diff --git a/data/web/lang/lang.en.php b/data/web/lang/lang.en.php
index e5ebe008..4b361afe 100644
--- a/data/web/lang/lang.en.php
+++ b/data/web/lang/lang.en.php
@@ -462,6 +462,7 @@ $lang['admin']['configuration'] = 'Configuration';
$lang['admin']['password'] = 'Password';
$lang['admin']['password_repeat'] = 'Confirmation password (repeat)';
$lang['admin']['active'] = 'Active';
+$lang['admin']['inactive'] = 'Inactive';
$lang['admin']['action'] = 'Action';
$lang['admin']['add_domain_admin'] = 'Add Domain administrator';
$lang['admin']['admin_domains'] = 'Domain assignments';