commit
3f493e043d
20 changed files with 232 additions and 79 deletions
16
README.md
16
README.md
|
@ -13,6 +13,22 @@ You can also [get a SAL](https://www.servercow.de/mailcow?lang=en#sal) which is
|
|||
|
||||
Or just spread the word: moo.
|
||||
|
||||
## Many thanks to our GitHub Sponsors ❤️
|
||||
A big thank you to everyone supporting us on GitHub Sponsors—your contributions mean the world to us! Special thanks to the following amazing supporters:
|
||||
|
||||
### 100$/Month Sponsors
|
||||
<a href="https://www.colba.net/" target=_blank><img
|
||||
src="https://avatars.githubusercontent.com/u/204464723" height="58"
|
||||
/></a>
|
||||
<a href="https://www.maehdros.com/" target=_blank><img
|
||||
src="https://avatars.githubusercontent.com/u/173894712" height="58"
|
||||
/></a>
|
||||
|
||||
### 50$/Month Sponsors
|
||||
<a href="https://github.com/vnukhr" target=_blank><img
|
||||
src="https://avatars.githubusercontent.com/u/7805987?s=52&v=4" height="58"
|
||||
/></a>
|
||||
|
||||
## Info, documentation and support
|
||||
|
||||
Please see [the official documentation](https://docs.mailcow.email/) for installation and support instructions. 🐄
|
||||
|
|
|
@ -1,20 +1,15 @@
|
|||
59,65d58
|
||||
< ng-show="::!activeUser.isSuperUser"
|
||||
60,65d58
|
||||
< var:ng-click="navButtonClick"
|
||||
< ng-href="/user">
|
||||
< <md-icon>build</md-icon>
|
||||
< <md-tooltip><var:string label:value="mailcow"/></md-tooltip>
|
||||
< <md-tooltip>mailcow <var:string label:value="Preferences"/></md-tooltip>
|
||||
< </md-button>
|
||||
< <md-button class="md-icon-button"
|
||||
83c76
|
||||
< onclick="document.getElementById('mc_logout').setAttribute('action', '/'); document.getElementById('mc_logout').submit();"
|
||||
< onclick="mc_logout();"
|
||||
---
|
||||
> ng-show="::activeUser.path.logoff.length"
|
||||
85c78
|
||||
< ng-href="#">
|
||||
---
|
||||
> ng-href="{{::activeUser.path.logoff}}">
|
||||
89,91d81
|
||||
< <form method="POST" id="mc_logout" action="user">
|
||||
< <input type="hidden" name="logout" value="1">
|
||||
< </form>
|
||||
|
|
|
@ -69,29 +69,34 @@ require_once 'functions.acl.inc.php';
|
|||
|
||||
$isSOGoRequest = $post['real_rip'] == getenv('IPV4_NETWORK') . '.248';
|
||||
$result = false;
|
||||
$protocol = $post['protocol'];
|
||||
if ($isSOGoRequest) {
|
||||
$protocol = null;
|
||||
// This is a SOGo Auth request. First check for SSO password.
|
||||
$sogo_sso_pass = file_get_contents("/etc/sogo-sso/sogo-sso.pass");
|
||||
if ($sogo_sso_pass === $post['password']){
|
||||
error_log('MAILCOWAUTH: SOGo SSO auth for user ' . $post['username']);
|
||||
set_sasl_log($post['username'], $post['real_rip'], "SOGO");
|
||||
$result = true;
|
||||
}
|
||||
}
|
||||
if ($result === false){
|
||||
$result = apppass_login($post['username'], $post['password'], $protocol, array(
|
||||
$result = apppass_login($post['username'], $post['password'], array($post['service'] => true), array(
|
||||
'is_internal' => true,
|
||||
'remote_addr' => $post['real_rip']
|
||||
));
|
||||
if ($result) error_log('MAILCOWAUTH: App auth for user ' . $post['username']);
|
||||
if ($result) {
|
||||
error_log('MAILCOWAUTH: App auth for user ' . $post['username']);
|
||||
set_sasl_log($post['username'], $post['real_rip'], $post['service']);
|
||||
}
|
||||
}
|
||||
if ($result === false){
|
||||
// Init Identity Provider
|
||||
$iam_provider = identity_provider('init');
|
||||
$iam_settings = identity_provider('get');
|
||||
$result = user_login($post['username'], $post['password'], array('is_internal' => true));
|
||||
if ($result) error_log('MAILCOWAUTH: User auth for user ' . $post['username']);
|
||||
if ($result) {
|
||||
error_log('MAILCOWAUTH: User auth for user ' . $post['username']);
|
||||
set_sasl_log($post['username'], $post['real_rip'], $post['service']);
|
||||
}
|
||||
}
|
||||
|
||||
if ($result) {
|
||||
|
|
|
@ -3,21 +3,20 @@ function auth_password_verify(request, password)
|
|||
return dovecot.auth.PASSDB_RESULT_USER_UNKNOWN, "No such user"
|
||||
end
|
||||
|
||||
json = require "cjson"
|
||||
ltn12 = require "ltn12"
|
||||
https = require "ssl.https"
|
||||
https.TIMEOUT = 5
|
||||
local json = require "cjson"
|
||||
local ltn12 = require "ltn12"
|
||||
local https = require "ssl.https"
|
||||
https.TIMEOUT = 30
|
||||
|
||||
local req = {
|
||||
username = request.user,
|
||||
password = password,
|
||||
real_rip = request.real_rip,
|
||||
protocol = {}
|
||||
service = request.service
|
||||
}
|
||||
req.protocol[request.service] = true
|
||||
local req_json = json.encode(req)
|
||||
local res = {}
|
||||
|
||||
local res = {}
|
||||
|
||||
local b, c = https.request {
|
||||
method = "POST",
|
||||
url = "https://nginx:9082",
|
||||
|
@ -29,11 +28,17 @@ function auth_password_verify(request, password)
|
|||
sink = ltn12.sink.table(res),
|
||||
insecure = true
|
||||
}
|
||||
|
||||
if c ~= 200 then
|
||||
dovecot.i_info("HTTP request failed with " .. c .. " for user " .. request.user)
|
||||
return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "Upstream error"
|
||||
end
|
||||
|
||||
local api_response = json.decode(table.concat(res))
|
||||
if api_response.success == true then
|
||||
return dovecot.auth.PASSDB_RESULT_OK, ""
|
||||
end
|
||||
|
||||
|
||||
return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Failed to authenticate"
|
||||
end
|
||||
|
||||
|
|
|
@ -53,7 +53,7 @@ mail_shared_explicit_inbox = yes
|
|||
mail_prefetch_count = 30
|
||||
passdb {
|
||||
driver = lua
|
||||
args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes cache_key=%u:%w
|
||||
args = file=/etc/dovecot/auth/passwd-verify.lua blocking=yes cache_key=%s:%u:%w
|
||||
result_success = return-ok
|
||||
result_failure = continue
|
||||
result_internalfail = continue
|
||||
|
|
|
@ -196,7 +196,7 @@ while (true) {
|
|||
logMsg("err", "Could not create user " . $user['email']);
|
||||
continue;
|
||||
}
|
||||
} else if ($row && intval($iam_settings['periodic_sync']) == 1) {
|
||||
} else if ($row && intval($iam_settings['periodic_sync']) == 1 && $row['authsource'] == "keycloak") {
|
||||
if ($mapper_key === false){
|
||||
logMsg("warning", "No matching attribute mapping found for user " . $user['email']);
|
||||
continue;
|
||||
|
|
|
@ -168,7 +168,7 @@ foreach ($response as $user) {
|
|||
logMsg("err", "Could not create user " . $user[$iam_settings['username_field']][0]);
|
||||
continue;
|
||||
}
|
||||
} else if ($row && intval($iam_settings['periodic_sync']) == 1) {
|
||||
} else if ($row && intval($iam_settings['periodic_sync']) == 1 && $row['authsource'] == "ldap") {
|
||||
if ($mapper_key === false){
|
||||
logMsg("warning", "No matching attribute mapping found for user " . $user[$iam_settings['username_field']][0]);
|
||||
continue;
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
# Whitelist generated by Postwhite v3.4 on Sat Mar 1 00:19:29 UTC 2025
|
||||
# Whitelist generated by Postwhite v3.4 on Tue Apr 1 00:20:51 UTC 2025
|
||||
# https://github.com/stevejenkins/postwhite/
|
||||
# 2000 total rules
|
||||
# 2067 total rules
|
||||
2a00:1450:4000::/36 permit
|
||||
2a01:111:f400::/48 permit
|
||||
2a01:111:f403:8000::/50 permit
|
||||
|
@ -26,7 +26,12 @@
|
|||
8.20.114.31 permit
|
||||
8.25.194.0/23 permit
|
||||
8.25.196.0/23 permit
|
||||
8.39.54.0/23 permit
|
||||
8.39.54.250/31 permit
|
||||
8.40.222.0/23 permit
|
||||
8.40.222.250/31 permit
|
||||
12.130.86.238 permit
|
||||
13.107.246.59 permit
|
||||
13.110.208.0/21 permit
|
||||
13.110.209.0/24 permit
|
||||
13.110.216.0/22 permit
|
||||
|
@ -60,8 +65,6 @@
|
|||
20.59.80.4/30 permit
|
||||
20.63.210.192/28 permit
|
||||
20.69.8.108/30 permit
|
||||
20.70.246.20 permit
|
||||
20.76.201.171 permit
|
||||
20.83.222.104/30 permit
|
||||
20.88.157.184/30 permit
|
||||
20.94.180.64/28 permit
|
||||
|
@ -70,14 +73,11 @@
|
|||
20.98.194.68/30 permit
|
||||
20.105.209.76/30 permit
|
||||
20.107.239.64/30 permit
|
||||
20.112.250.133 permit
|
||||
20.118.139.208/30 permit
|
||||
20.141.10.196 permit
|
||||
20.185.214.0/27 permit
|
||||
20.185.214.32/27 permit
|
||||
20.185.214.64/27 permit
|
||||
20.231.239.246 permit
|
||||
20.236.44.162 permit
|
||||
23.103.224.0/19 permit
|
||||
23.249.208.0/20 permit
|
||||
23.251.224.0/19 permit
|
||||
|
@ -103,6 +103,24 @@
|
|||
27.123.206.80/28 permit
|
||||
31.25.48.222 permit
|
||||
31.47.251.17 permit
|
||||
34.2.64.0/22 permit
|
||||
34.2.68.0/23 permit
|
||||
34.2.70.0/23 permit
|
||||
34.2.71.64/26 permit
|
||||
34.2.72.0/22 permit
|
||||
34.2.75.0/26 permit
|
||||
34.2.78.0/23 permit
|
||||
34.2.80.0/23 permit
|
||||
34.2.82.0/23 permit
|
||||
34.2.84.0/24 permit
|
||||
34.2.84.64/26 permit
|
||||
34.2.85.0/24 permit
|
||||
34.2.85.64/26 permit
|
||||
34.2.86.0/23 permit
|
||||
34.2.88.0/23 permit
|
||||
34.2.90.0/23 permit
|
||||
34.2.92.0/23 permit
|
||||
34.2.94.0/23 permit
|
||||
34.195.217.107 permit
|
||||
34.212.163.75 permit
|
||||
34.215.104.144 permit
|
||||
|
@ -215,7 +233,6 @@
|
|||
52.95.49.88/29 permit
|
||||
52.96.91.34 permit
|
||||
52.96.111.82 permit
|
||||
52.96.172.98 permit
|
||||
52.96.214.50 permit
|
||||
52.96.222.194 permit
|
||||
52.96.222.226 permit
|
||||
|
@ -255,6 +272,7 @@
|
|||
54.244.54.130 permit
|
||||
54.244.242.0/24 permit
|
||||
54.255.61.23 permit
|
||||
56.124.6.228 permit
|
||||
57.103.64.0/18 permit
|
||||
62.13.128.0/24 permit
|
||||
62.13.129.128/25 permit
|
||||
|
@ -341,6 +359,7 @@
|
|||
65.110.161.77 permit
|
||||
65.123.29.213 permit
|
||||
65.123.29.220 permit
|
||||
65.154.166.0/24 permit
|
||||
65.212.180.36 permit
|
||||
66.102.0.0/20 permit
|
||||
66.119.150.192/26 permit
|
||||
|
@ -1304,6 +1323,9 @@
|
|||
117.120.16.0/21 permit
|
||||
119.42.242.52/31 permit
|
||||
119.42.242.156 permit
|
||||
121.244.91.48 permit
|
||||
121.244.91.52 permit
|
||||
122.15.156.182 permit
|
||||
123.126.78.64/29 permit
|
||||
124.108.96.24/31 permit
|
||||
124.108.96.28/31 permit
|
||||
|
@ -1366,7 +1388,21 @@
|
|||
134.170.141.64/26 permit
|
||||
134.170.143.0/24 permit
|
||||
134.170.174.0/24 permit
|
||||
135.84.80.0/24 permit
|
||||
135.84.81.0/24 permit
|
||||
135.84.82.0/24 permit
|
||||
135.84.83.0/24 permit
|
||||
135.84.216.0/22 permit
|
||||
136.143.160.0/24 permit
|
||||
136.143.161.0/24 permit
|
||||
136.143.162.0/24 permit
|
||||
136.143.176.0/24 permit
|
||||
136.143.177.0/24 permit
|
||||
136.143.178.49 permit
|
||||
136.143.182.0/23 permit
|
||||
136.143.184.0/24 permit
|
||||
136.143.188.0/24 permit
|
||||
136.143.190.0/23 permit
|
||||
136.147.128.0/20 permit
|
||||
136.147.135.0/24 permit
|
||||
136.147.176.0/20 permit
|
||||
|
@ -1381,6 +1417,7 @@
|
|||
139.138.46.219 permit
|
||||
139.138.57.55 permit
|
||||
139.138.58.119 permit
|
||||
139.167.79.86 permit
|
||||
139.180.17.0/24 permit
|
||||
140.238.148.191 permit
|
||||
141.148.159.229 permit
|
||||
|
@ -1498,6 +1535,9 @@
|
|||
163.114.135.16 permit
|
||||
164.152.23.32 permit
|
||||
164.177.132.168/30 permit
|
||||
165.173.128.0/24 permit
|
||||
165.173.180.250/31 permit
|
||||
165.173.182.250/31 permit
|
||||
166.78.68.0/22 permit
|
||||
166.78.68.221 permit
|
||||
166.78.69.169 permit
|
||||
|
@ -1526,6 +1566,12 @@
|
|||
168.245.12.252 permit
|
||||
168.245.46.9 permit
|
||||
168.245.127.231 permit
|
||||
169.148.129.0/24 permit
|
||||
169.148.131.0/24 permit
|
||||
169.148.142.10 permit
|
||||
169.148.144.0/25 permit
|
||||
169.148.144.10 permit
|
||||
169.148.146.0/23 permit
|
||||
170.10.128.0/24 permit
|
||||
170.10.129.0/24 permit
|
||||
170.10.132.56/29 permit
|
||||
|
@ -1667,6 +1713,14 @@
|
|||
198.61.254.231 permit
|
||||
198.178.234.57 permit
|
||||
198.244.48.0/20 permit
|
||||
198.244.56.107 permit
|
||||
198.244.56.108 permit
|
||||
198.244.56.109 permit
|
||||
198.244.56.111 permit
|
||||
198.244.56.112 permit
|
||||
198.244.56.113 permit
|
||||
198.244.56.114 permit
|
||||
198.244.56.115 permit
|
||||
198.244.59.30 permit
|
||||
198.244.59.33 permit
|
||||
198.244.59.35 permit
|
||||
|
@ -1679,7 +1733,15 @@
|
|||
199.16.156.0/22 permit
|
||||
199.33.145.1 permit
|
||||
199.33.145.32 permit
|
||||
199.34.22.36 permit
|
||||
199.59.148.0/22 permit
|
||||
199.67.80.2 permit
|
||||
199.67.80.20 permit
|
||||
199.67.82.2 permit
|
||||
199.67.82.20 permit
|
||||
199.67.84.0/24 permit
|
||||
199.67.86.0/24 permit
|
||||
199.67.88.0/24 permit
|
||||
199.101.161.130 permit
|
||||
199.101.162.0/25 permit
|
||||
199.122.120.0/21 permit
|
||||
|
@ -1736,6 +1798,8 @@
|
|||
204.92.114.187 permit
|
||||
204.92.114.203 permit
|
||||
204.92.114.204/31 permit
|
||||
204.141.32.0/23 permit
|
||||
204.141.42.0/23 permit
|
||||
204.220.160.0/21 permit
|
||||
204.220.168.0/21 permit
|
||||
204.220.176.0/20 permit
|
||||
|
@ -1988,6 +2052,9 @@
|
|||
2603:1030:20e:3::23c permit
|
||||
2603:1030:b:3::152 permit
|
||||
2603:1030:c02:8::14 permit
|
||||
2607:13c0:0001:0000:0000:0000:0000:7000/116 permit
|
||||
2607:13c0:0002:0000:0000:0000:0000:1000/116 permit
|
||||
2607:13c0:0004:0000:0000:0000:0000:0000/116 permit
|
||||
2607:f8b0:4000::/36 permit
|
||||
2620:109:c003:104::/64 permit
|
||||
2620:109:c003:104::215 permit
|
||||
|
|
|
@ -5,6 +5,16 @@ document.addEventListener('DOMContentLoaded', function () {
|
|||
window.location.href = '/user';
|
||||
}
|
||||
});
|
||||
// logout function
|
||||
function mc_logout() {
|
||||
fetch("/", {
|
||||
method: "POST",
|
||||
headers: {
|
||||
"Content-Type": "application/x-www-form-urlencoded"
|
||||
},
|
||||
body: "logout=1"
|
||||
}).then(() => window.location.href = '/');
|
||||
}
|
||||
|
||||
// Custom SOGo JS
|
||||
|
||||
|
|
|
@ -9,25 +9,52 @@ function check_login($user, $pass, $app_passwd_data = false, $extra = null) {
|
|||
// Try validate admin
|
||||
if (!isset($role) || $role == "admin") {
|
||||
$result = admin_login($user, $pass);
|
||||
if ($result !== false) return $result;
|
||||
if ($result !== false){
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Try validate domain admin
|
||||
if (!isset($role) || $role == "domain_admin") {
|
||||
$result = domainadmin_login($user, $pass);
|
||||
if ($result !== false) return $result;
|
||||
if ($result !== false) {
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Try validate app password
|
||||
if (!isset($role) || $role == "app") {
|
||||
$result = apppass_login($user, $pass, $app_passwd_data);
|
||||
if ($result !== false) {
|
||||
if ($app_passwd_data['eas'] === true) {
|
||||
$service = 'EAS';
|
||||
} elseif ($app_passwd_data['dav'] === true) {
|
||||
$service = 'DAV';
|
||||
} else {
|
||||
$service = 'NONE';
|
||||
}
|
||||
$real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']);
|
||||
set_sasl_log($user, $real_rip, $service, $pass);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// Try validate user
|
||||
if (!isset($role) || $role == "user") {
|
||||
$result = user_login($user, $pass);
|
||||
if ($result !== false) return $result;
|
||||
}
|
||||
|
||||
// Try validate app password
|
||||
if (!isset($role) || $role == "app") {
|
||||
$result = apppass_login($user, $pass, $app_passwd_data);
|
||||
if ($result !== false) return $result;
|
||||
if ($result !== false) {
|
||||
if ($app_passwd_data['eas'] === true) {
|
||||
$service = 'EAS';
|
||||
} elseif ($app_passwd_data['dav'] === true) {
|
||||
$service = 'DAV';
|
||||
} else {
|
||||
$service = 'MAILCOWUI';
|
||||
}
|
||||
$real_rip = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']);
|
||||
set_sasl_log($user, $real_rip, $service);
|
||||
return $result;
|
||||
}
|
||||
}
|
||||
|
||||
// skip log and only return false if it's an internal request
|
||||
|
@ -415,21 +442,7 @@ function apppass_login($user, $pass, $app_passwd_data, $extra = null){
|
|||
|
||||
// verify password
|
||||
if (verify_hash($row['password'], $pass) !== false) {
|
||||
if ($is_internal){
|
||||
$remote_addr = $extra['remote_addr'];
|
||||
} else {
|
||||
$remote_addr = ($_SERVER['HTTP_X_REAL_IP'] ?? $_SERVER['REMOTE_ADDR']);
|
||||
}
|
||||
|
||||
$service = strtoupper($is_app_passwd);
|
||||
$stmt = $pdo->prepare("REPLACE INTO sasl_log (`service`, `app_password`, `username`, `real_rip`) VALUES (:service, :app_id, :username, :remote_addr)");
|
||||
$stmt->execute(array(
|
||||
':service' => $service,
|
||||
':app_id' => $row['app_passwd_id'],
|
||||
':username' => $user,
|
||||
':remote_addr' => $remote_addr
|
||||
));
|
||||
|
||||
$_SESSION['app_passwd_id'] = $row['app_passwd_id'];
|
||||
unset($_SESSION['ldelay']);
|
||||
return "user";
|
||||
}
|
||||
|
|
|
@ -350,6 +350,34 @@ function last_login($action, $username, $sasl_limit_days = 7, $ui_offset = 1) {
|
|||
}
|
||||
|
||||
}
|
||||
function set_sasl_log($username, $real_rip, $service){
|
||||
global $pdo;
|
||||
|
||||
try {
|
||||
if (!empty($_SESSION['app_passwd_id'])) {
|
||||
$app_password = $_SESSION['app_passwd_id'];
|
||||
} else {
|
||||
$app_password = 0;
|
||||
}
|
||||
|
||||
$stmt = $pdo->prepare('REPLACE INTO `sasl_log` (`username`, `real_rip`, `service`, `app_password`) VALUES (:username, :real_rip, :service, :app_password)');
|
||||
$stmt->execute(array(
|
||||
':username' => $username,
|
||||
':real_rip' => $real_rip,
|
||||
':service' => $service,
|
||||
':app_password' => $app_password
|
||||
));
|
||||
} catch (PDOException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'log' => array(__FUNCTION__, $_data_log),
|
||||
'msg' => array('mysql_error', $e)
|
||||
);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
function flush_memcached() {
|
||||
try {
|
||||
$m = new Memcached();
|
||||
|
|
|
@ -681,7 +681,7 @@ jQuery(function($){
|
|||
$(this).html('<div class="spinner-border" role="status"><span class="visually-hidden">Loading...</span></div> ');
|
||||
$.ajax({
|
||||
type: 'GET',
|
||||
url: 'inc/ajax/transport_check.php',
|
||||
url: '/inc/ajax/transport_check.php',
|
||||
dataType: 'text',
|
||||
data: $('#test_transport_form').serialize(),
|
||||
complete: function (data) {
|
||||
|
|
|
@ -90,13 +90,7 @@ jQuery(function($){
|
|||
console.log('error reading last logins');
|
||||
},
|
||||
success: function (data) {
|
||||
$('.last-ui-login').html('');
|
||||
$('.last-sasl-login').html('');
|
||||
if (data.ui.time) {
|
||||
$('.last-ui-login').html('<i class="bi bi-person-fill"></i> ' + lang.last_ui_login + ': ' + unix_time_format(data.ui.time));
|
||||
} else {
|
||||
$('.last-ui-login').text(lang.no_last_login);
|
||||
}
|
||||
if (data.sasl) {
|
||||
$('.last-sasl-login').append('<ul class="list-group">');
|
||||
$.each(data.sasl, function (i, item) {
|
||||
|
|
|
@ -238,7 +238,9 @@
|
|||
"iam_username_field": "Username Feld",
|
||||
"iam_binddn": "Bind DN",
|
||||
"iam_use_ssl": "Benutze SSL",
|
||||
"iam_use_tls": "Benutze TLS",
|
||||
"iam_use_ssl_info": "Wenn SSL aktiviert ist und der Port auf 389 gesetzt wurde, wird dieser automatisch auf 636 geändert.",
|
||||
"iam_use_tls": "Benutze StartTLS",
|
||||
"iam_use_tls_info": "Wenn TLS aktiviert wird, muss der Standardport deines LDAP-Servers (389) verwendet werden. SSL-Ports können dabei nicht verwendet werden.",
|
||||
"iam_version": "Version",
|
||||
"ignore_ssl_error": "Ignoriere SSL Fehler",
|
||||
"import": "Importieren",
|
||||
|
@ -1333,7 +1335,7 @@
|
|||
"tag_in_subfolder": "In Unterordner",
|
||||
"tag_in_subject": "In Betreff",
|
||||
"text": "Text",
|
||||
"tfa_info": "Zwei-Faktor-Authentifizierung hilft dabei, Ihr Konto zu schützen. Wenn Sie sie aktivieren, benötigen Sie möglicherweise App-Passwörter, um sich bei Apps oder Diensten anzumelden, die die Zwei-Faktor-Authentifizierung nicht unterstützen (z.B. Mailclients).",
|
||||
"tfa_info": "Zwei-Faktor-Authentifizierung hilft dabei, Ihr Konto zu schützen. Wenn Sie sie aktivieren, benötigen Sie App-Passwörter, um sich bei Apps oder Diensten anzumelden, die die Zwei-Faktor-Authentifizierung nicht unterstützen (z.B. Mailclients).",
|
||||
"title": "Title",
|
||||
"tls_enforce_in": "TLS eingehend erzwingen",
|
||||
"tls_enforce_out": "TLS ausgehend erzwingen",
|
||||
|
|
|
@ -245,7 +245,9 @@
|
|||
"iam_username_field": "Username Field",
|
||||
"iam_binddn": "Bind DN",
|
||||
"iam_use_ssl": "Use SSL",
|
||||
"iam_use_tls": "Use TLS",
|
||||
"iam_use_ssl_info": "If enabling SSL, and port is set to 389, it will be automatically overridden to use 636.",
|
||||
"iam_use_tls": "Use StartTLS",
|
||||
"iam_use_tls_info": "If enabling TLS, you must use the default port for your LDAP server (389). SSL ports cannot be used.",
|
||||
"iam_version": "Version",
|
||||
"ignore_ssl_error": "Ignore SSL Errors",
|
||||
"import": "Import",
|
||||
|
@ -1355,7 +1357,7 @@
|
|||
"tag_in_subfolder": "In subfolder",
|
||||
"tag_in_subject": "In subject",
|
||||
"text": "Text",
|
||||
"tfa_info": "Two-factor authentication helps protect your account. If you enable it, you may need app passwords to log in to apps or services that don't support two-factor authentication (e.g. Mailclients).",
|
||||
"tfa_info": "Two-factor authentication helps protect your account. If you enable it, you need app passwords to log in to apps or services that don't support two-factor authentication (e.g. Mailclients).",
|
||||
"title": "Title",
|
||||
"tls_enforce_in": "Enforce TLS incoming",
|
||||
"tls_enforce_out": "Enforce TLS outgoing",
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
<?php
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/prerequisites.inc.php';
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/triggers.user.inc.php';
|
||||
|
||||
if (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'admin') {
|
||||
header('Location: /admin/dashboard');
|
||||
|
|
|
@ -392,11 +392,11 @@
|
|||
<input type="hidden" name="authsource" value="ldap">
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
||||
<i style="font-size: 16px; cursor: pointer;" class="bi bi-patch-question-fill m-2 ms-0" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom" title="{{ lang.admin.iam_host_info }}"></i>
|
||||
<i style="font-size: 16px; cursor: pointer;" class="bi bi-patch-question-fill mx-2 ms-0" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom" title="{{ lang.admin.iam_host_info }}"></i>
|
||||
<label class="control-label" for="iam_ldap_host">{{ lang.admin.iam_host }}:</label>
|
||||
</div>
|
||||
<div class="col-12 col-md-9 col-lg-4 d-flex">
|
||||
<input type="text" class="form-control" id="iam_ldap_host" name="host" value="{{ iam_settings.host }}" required>
|
||||
<input type="text" class="form-control" id="iam_ldap_host" name="host" value="{{ iam_settings.host }}" required>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
|
@ -409,21 +409,37 @@
|
|||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
||||
<i style="font-size: 16px; cursor: pointer;" class="bi bi-patch-question-fill mx-2 ms-0" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom" title="{{ lang.admin.iam_use_ssl_info }}"></i>
|
||||
<label class="control-label">{{ lang.admin.iam_use_ssl }}</label>
|
||||
</div>
|
||||
<div class="col-12 col-md-9">
|
||||
<div class="col-12 col-md-9 d-flex align-items-center">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" name="use_ssl" value="1" {% if iam_settings.use_ssl == 1 %}checked{% endif %}>
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id="use_ssl"
|
||||
name="use_ssl"
|
||||
value="1"
|
||||
onchange="if(this.checked) document.getElementById('use_tls').checked = false"
|
||||
{% if iam_settings.use_ssl == 1 %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
<div class="row mb-2">
|
||||
<div class="col-md-3 d-flex align-items-center justify-content-md-end">
|
||||
<i style="font-size: 16px; cursor: pointer;" class="bi bi-patch-question-fill mx-2 ms-0" data-bs-toggle="tooltip" data-bs-html="true" data-bs-placement="bottom" title="{{ lang.admin.iam_use_tls_info }}"></i>
|
||||
<label class="control-label">{{ lang.admin.iam_use_tls }}</label>
|
||||
</div>
|
||||
<div class="col-12 col-md-9">
|
||||
<div class="col-12 col-md-9 d-flex align-items-center">
|
||||
<div class="form-check form-switch">
|
||||
<input class="form-check-input" type="checkbox" role="switch" name="use_tls" value="1" {% if iam_settings.use_tls == 1 %}checked{% endif %}>
|
||||
<input class="form-check-input"
|
||||
type="checkbox"
|
||||
role="switch"
|
||||
id="use_tls"
|
||||
name="use_tls"
|
||||
value="1"
|
||||
onchange="if(this.checked) document.getElementById('use_ssl').checked = false"
|
||||
{% if iam_settings.use_tls == 1 %}checked{% endif %}>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -184,7 +184,7 @@
|
|||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
<div class="ms-auto col-xl-3 col-lg-5 col-md-12 col-12 d-flex flex-column well flex-grow-1">
|
||||
<div class="ms-auto col-xl-3 col-lg-5 col-md-12 col-12 d-flex flex-column well flex-grow-1" id="recent-logins">
|
||||
<legend class="d-flex">
|
||||
<span>{{ lang.user.recent_successful_connections }}</span>
|
||||
<div id="spinner-last-login" class="ms-auto my-auto spinner-border spinner-border-sm d-none" role="status">
|
||||
|
@ -192,7 +192,6 @@
|
|||
</div>
|
||||
</legend>
|
||||
<hr>
|
||||
<h6 class="last-ui-login"></h6>
|
||||
<div class="d-flex">
|
||||
<span class="clear-last-logins mt-auto mb-2">
|
||||
{{ lang.user.clear_recent_successful_connections }}
|
||||
|
|
|
@ -199,7 +199,7 @@ services:
|
|||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: ghcr.io/mailcow/sogo:1.131
|
||||
image: ghcr.io/mailcow/sogo:1.133
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
|
@ -477,7 +477,7 @@ services:
|
|||
- acme
|
||||
|
||||
netfilter-mailcow:
|
||||
image: ghcr.io/mailcow/netfilter:1.62
|
||||
image: ghcr.io/mailcow/netfilter:1.61
|
||||
stop_grace_period: 30s
|
||||
restart: always
|
||||
privileged: true
|
||||
|
|
|
@ -236,7 +236,7 @@ function restore() {
|
|||
if [[ $(find "${RESTORE_LOCATION}" \( -name '*x86*' -o -name '*aarch*' \) -exec basename {} \; | sed 's/^\.//' | sed 's/^\.//') == "" ]]; then
|
||||
echo -e "\e[33mCould not find a architecture signature of the loaded backup... Maybe the backup was done before the multiarch update?"
|
||||
sleep 2
|
||||
echo -e "Continuing anyhow. If rspamd is crashing opon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m"
|
||||
echo -e "Continuing anyhow. If rspamd is crashing upon boot try remove the rspamd volume with docker volume rm ${CMPS_PRJ}_rspamd-vol-1 after you've stopped the stack.\e[0m"
|
||||
sleep 2
|
||||
docker stop $(docker ps -qf name=rspamd-mailcow)
|
||||
docker run -i --name mailcow-backup --rm \
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue