diff --git a/data/conf/dovecot/auth/mailcowauth.php b/data/conf/dovecot/auth/mailcowauth.php
index 667419c57..c625522ba 100644
--- a/data/conf/dovecot/auth/mailcowauth.php
+++ b/data/conf/dovecot/auth/mailcowauth.php
@@ -79,7 +79,9 @@ if ($isSOGoRequest) {
}
}
if ($result === false){
- $result = apppass_login($post['username'], $post['password'], array($post['service'] => true), array(
+ // If it's a SOGo Request, don't check for protocol access
+ $service = ($isSOGoRequest) ? false : array($post['service'] => true);
+ $result = apppass_login($post['username'], $post['password'], $service, array(
'is_internal' => true,
'remote_addr' => $post['real_rip']
));
diff --git a/data/conf/dovecot/auth/passwd-verify.lua b/data/conf/dovecot/auth/passwd-verify.lua
index 18c18dbe3..ea847932d 100644
--- a/data/conf/dovecot/auth/passwd-verify.lua
+++ b/data/conf/dovecot/auth/passwd-verify.lua
@@ -29,13 +29,23 @@ function auth_password_verify(request, password)
insecure = true
}
- if c ~= 200 then
+ -- Returning PASSDB_RESULT_PASSWORD_MISMATCH will reset the user's auth cache entry.
+ -- Returning PASSDB_RESULT_INTERNAL_FAILURE keeps the existing cache entry,
+ -- even if the TTL has expired. Useful to avoid cache eviction during backend issues.
+ if c ~= 200 and c ~= 401 then
dovecot.i_info("HTTP request failed with " .. c .. " for user " .. request.user)
- return dovecot.auth.PASSDB_RESULT_INTERNAL_FAILURE, "Upstream error"
+ return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Upstream error"
end
- local api_response = json.decode(table.concat(res))
- if api_response.success == true then
+ local response_str = table.concat(res)
+ local is_response_valid, response_json = pcall(json.decode, response_str)
+
+ if not is_response_valid then
+ dovecot.i_info("Invalid JSON received: " .. response_str)
+ return dovecot.auth.PASSDB_RESULT_PASSWORD_MISMATCH, "Invalid response format"
+ end
+
+ if response_json.success == true then
return dovecot.auth.PASSDB_RESULT_OK, ""
end
diff --git a/data/conf/sogo/sogo.conf b/data/conf/sogo/sogo.conf
index 8455f0cf3..2c8d80a12 100644
--- a/data/conf/sogo/sogo.conf
+++ b/data/conf/sogo/sogo.conf
@@ -16,6 +16,9 @@
SOGoFoldersSendEMailNotifications = YES;
SOGoForwardEnabled = YES;
+ // Added with SOGo 5.12 - Allows users to cleanup there maildirectories by deleting mails oder than X
+ SOGoEnableMailCleaning = YES;
+
// Fixes "MODIFICATION_FAILED" error (HTTP 412) in Clients when accepting invitations from external services
SOGoDisableOrganizerEventCheck = YES;
@@ -91,7 +94,7 @@
//SoDebugBaseURL = YES;
//ImapDebugEnabled = YES;
//SOGoEASDebugEnabled = YES;
- SOGoEASSearchInBody = YES; // Experimental. Enabled since 2023-10
+ SOGoEASSearchInBody = YES;
//LDAPDebugEnabled = YES;
//PGDebugEnabled = YES;
//MySQL4DebugEnabled = YES;
diff --git a/data/web/inc/triggers.user.inc.php b/data/web/inc/triggers.user.inc.php
index 30bf0fe64..4dee75a37 100644
--- a/data/web/inc/triggers.user.inc.php
+++ b/data/web/inc/triggers.user.inc.php
@@ -78,6 +78,7 @@ if (isset($_POST["verify_tfa_login"])) {
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
if (intval($user_details['attributes']['sogo_access']) == 1 &&
intval($user_details['attributes']['force_pw_update']) != 1 &&
+ getenv('SKIP_SOGO') != "y" &&
!$is_dual) {
header("Location: /SOGo/so/{$_SESSION['mailcow_cc_username']}");
die();
@@ -143,6 +144,7 @@ if (isset($_POST["login_user"]) && isset($_POST["pass_user"])) {
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
if (intval($user_details['attributes']['sogo_access']) == 1 &&
intval($user_details['attributes']['force_pw_update']) != 1 &&
+ getenv('SKIP_SOGO') != "y" &&
!$is_dual) {
header("Location: /SOGo/so/{$login_user}");
die();
diff --git a/data/web/index.php b/data/web/index.php
index 1e91cb785..f306f1aed 100644
--- a/data/web/index.php
+++ b/data/web/index.php
@@ -11,7 +11,7 @@ if (isset($_SESSION['mailcow_cc_role']) && isset($_SESSION['oauth2_request'])) {
elseif (isset($_SESSION['mailcow_cc_role']) && $_SESSION['mailcow_cc_role'] == 'user') {
$user_details = mailbox("get", "mailbox_details", $_SESSION['mailcow_cc_username']);
$is_dual = (!empty($_SESSION["dual-login"]["username"])) ? true : false;
- if (intval($user_details['attributes']['sogo_access']) == 1 && !$is_dual) {
+ if (intval($user_details['attributes']['sogo_access']) == 1 && !$is_dual && getenv('SKIP_SOGO') != "y") {
header("Location: /SOGo/so/{$_SESSION['mailcow_cc_username']}");
} else {
header("Location: /user");
diff --git a/data/web/lang/lang.zh-cn.json b/data/web/lang/lang.zh-cn.json
index f9bb481da..486e8dcc3 100644
--- a/data/web/lang/lang.zh-cn.json
+++ b/data/web/lang/lang.zh-cn.json
@@ -108,7 +108,8 @@
"timeout2": "本地主机连接超时时间",
"username": "用户名",
"validate": "验证",
- "validation_success": "验证成功"
+ "validation_success": "验证成功",
+ "dry": "模拟同步(Dry run)"
},
"admin": {
"access": "权限管理",
@@ -994,7 +995,7 @@
"neutral_danger": "无危险等级",
"notified": "已发送通知",
"qhandler_success": "已成功向系统发送请求,现在你可以关闭这个窗口了。",
- "qid": "Rspamd QID",
+ "qid": "Rspamd 队列ID(QID)",
"qinfo": "隔离系统会把已被拒绝接收的邮件以及作为拷贝发送到垃圾箱的邮件保存到数据库中 (发件人不会知道)。\r\n
\"学习为垃圾并删除\" 会根据贝叶斯定理将消息作为垃圾学习并计算其模糊特征以拒绝未来收到相似消息。\r\n
请注意,这取决于你的系统资源,学习多个消息可能会花费较长时间。
黑名单中项目会被隔离系统排除。",
"qitem": "隔离项目",
"quarantine": "隔离",