mirror of
https://github.com/mailcow/mailcow-dockerized.git
synced 2026-02-19 07:36:23 +00:00
Compare commits
5 Commits
staging
...
fix/autodi
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2e8897c2cf | ||
|
|
5ca900749c | ||
|
|
b005803fe0 | ||
|
|
ec77406dba | ||
|
|
ee15721550 |
@@ -14,7 +14,7 @@ jobs:
|
||||
pull-requests: write
|
||||
steps:
|
||||
- name: Mark/Close Stale Issues and Pull Requests 🗑️
|
||||
uses: actions/stale@v10.2.0
|
||||
uses: actions/stale@v10.1.1
|
||||
with:
|
||||
repo-token: ${{ secrets.STALE_ACTION_PAT }}
|
||||
days-before-stale: 60
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
# Whitelist generated by Postwhite v3.4 on Sun Feb 1 00:29:33 UTC 2026
|
||||
# Whitelist generated by Postwhite v3.4 on Thu Jan 1 00:24:01 UTC 2026
|
||||
# https://github.com/stevejenkins/postwhite/
|
||||
# 2102 total rules
|
||||
# 2105 total rules
|
||||
2a00:1450:4000::/36 permit
|
||||
2a01:111:f400::/48 permit
|
||||
2a01:111:f403:2800::/53 permit
|
||||
@@ -54,8 +54,8 @@
|
||||
8.36.116.0/24 permit
|
||||
8.39.144.0/24 permit
|
||||
12.130.86.238 permit
|
||||
13.107.213.51 permit
|
||||
13.107.246.51 permit
|
||||
13.107.213.38 permit
|
||||
13.107.246.38 permit
|
||||
13.108.16.0/20 permit
|
||||
13.110.208.0/21 permit
|
||||
13.110.209.0/24 permit
|
||||
@@ -2088,6 +2088,11 @@
|
||||
2001:748:400:3301::3 permit
|
||||
2001:748:400:3301::4 permit
|
||||
2404:6800:4000::/36 permit
|
||||
2603:1010:3:3::5b permit
|
||||
2603:1020:201:10::10f permit
|
||||
2603:1030:20e:3::23c permit
|
||||
2603:1030:b:3::152 permit
|
||||
2603:1030:c02:8::14 permit
|
||||
2607:f8b0:4000::/36 permit
|
||||
2620:109:c003:104::/64 permit
|
||||
2620:109:c003:104::215 permit
|
||||
@@ -2100,8 +2105,6 @@
|
||||
2620:10d:c09c:400::8:1 permit
|
||||
2620:119:50c0:207::/64 permit
|
||||
2620:119:50c0:207::215 permit
|
||||
2620:1ec:46::51 permit
|
||||
2620:1ec:bdf::51 permit
|
||||
2800:3f0:4000::/36 permit
|
||||
49.12.4.251 permit # checks.mailcow.email
|
||||
2a01:4f8:c17:7906::10 permit # checks.mailcow.email
|
||||
|
||||
@@ -60,97 +60,25 @@ $pdo = new PDO($dsn, $database_user, $database_pass, $opt);
|
||||
$iam_provider = identity_provider('init');
|
||||
$iam_settings = identity_provider('get');
|
||||
|
||||
$login_user = strtolower(trim($_SERVER['PHP_AUTH_USER']));
|
||||
$login_pass = trim(htmlspecialchars_decode($_SERVER['PHP_AUTH_PW']));
|
||||
// Passwordless autodiscover - no authentication required
|
||||
// Email will be extracted from the request body
|
||||
$login_user = null;
|
||||
$login_role = null;
|
||||
|
||||
if (empty($_SERVER['PHP_AUTH_USER']) || empty($_SERVER['PHP_AUTH_PW'])) {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => "none",
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => "Error: must be authenticated"
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
header('WWW-Authenticate: Basic realm="' . $_SERVER['HTTP_HOST'] . '"');
|
||||
header('HTTP/1.0 401 Unauthorized');
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$login_role = check_login($login_user, $login_pass, array('service' => 'EAS'));
|
||||
|
||||
if ($login_role === "user") {
|
||||
header("Content-Type: application/xml");
|
||||
echo '<?xml version="1.0" encoding="utf-8" ?>' . PHP_EOL;
|
||||
header("Content-Type: application/xml");
|
||||
echo '<?xml version="1.0" encoding="utf-8" ?>' . PHP_EOL;
|
||||
?>
|
||||
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
|
||||
<?php
|
||||
if(!$data) {
|
||||
try {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => $_SERVER['PHP_AUTH_USER'],
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => "Error: invalid or missing request data"
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
?>
|
||||
<Response>
|
||||
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="2477272013">
|
||||
<ErrorCode>600</ErrorCode>
|
||||
<Message>Invalid Request</Message>
|
||||
<DebugData />
|
||||
</Error>
|
||||
</Response>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
exit(0);
|
||||
}
|
||||
try {
|
||||
$discover = new SimpleXMLElement($data);
|
||||
$email = $discover->Request->EMailAddress;
|
||||
} catch (Exception $e) {
|
||||
$email = $_SERVER['PHP_AUTH_USER'];
|
||||
}
|
||||
|
||||
$username = trim($email);
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `name` FROM `mailbox` WHERE `username`= :username");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
die("Failed to determine name from SQL");
|
||||
}
|
||||
if (!empty($MailboxData['name'])) {
|
||||
$displayname = $MailboxData['name'];
|
||||
}
|
||||
else {
|
||||
$displayname = $email;
|
||||
}
|
||||
if(!$data) {
|
||||
try {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => $_SERVER['PHP_AUTH_USER'],
|
||||
"user" => "none",
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => $autodiscover_config['autodiscoverType']
|
||||
"service" => "Error: invalid or missing request data"
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
@@ -163,7 +91,139 @@ if ($login_role === "user") {
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($autodiscover_config['autodiscoverType'] == 'imap') {
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
?>
|
||||
<Response>
|
||||
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="<?=rand(1000000000, 9999999999);?>">
|
||||
<ErrorCode>600</ErrorCode>
|
||||
<Message>Invalid Request</Message>
|
||||
<DebugData />
|
||||
</Error>
|
||||
</Response>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
exit(0);
|
||||
}
|
||||
try {
|
||||
$discover = new SimpleXMLElement($data);
|
||||
$email = $discover->Request->EMailAddress;
|
||||
} catch (Exception $e) {
|
||||
// If parsing fails, return error
|
||||
try {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => "none",
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => "Error: could not parse email from request"
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
// Silently fail
|
||||
}
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
?>
|
||||
<Response>
|
||||
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="<?=rand(1000000000, 9999999999);?>">
|
||||
<ErrorCode>600</ErrorCode>
|
||||
<Message>Invalid Request</Message>
|
||||
<DebugData />
|
||||
</Error>
|
||||
</Response>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$username = trim((string)$email);
|
||||
try {
|
||||
$stmt = $pdo->prepare("SELECT `mailbox`.`name`, `mailbox`.`active` FROM `mailbox`
|
||||
INNER JOIN `domain` ON `mailbox`.`domain` = `domain`.`domain`
|
||||
WHERE `mailbox`.`username` = :username
|
||||
AND `mailbox`.`active` = '1'
|
||||
AND `domain`.`active` = '1'");
|
||||
$stmt->execute(array(':username' => $username));
|
||||
$MailboxData = $stmt->fetch(PDO::FETCH_ASSOC);
|
||||
}
|
||||
catch(PDOException $e) {
|
||||
// Database error - return error response with complete XML
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
?>
|
||||
<Response>
|
||||
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="<?=rand(1000000000, 9999999999);?>">
|
||||
<ErrorCode>500</ErrorCode>
|
||||
<Message>Database Error</Message>
|
||||
<DebugData />
|
||||
</Error>
|
||||
</Response>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
exit(0);
|
||||
}
|
||||
|
||||
// Mailbox not found or not active - return generic error to prevent user enumeration
|
||||
if (empty($MailboxData)) {
|
||||
try {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => $email,
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => "Error: mailbox not found or inactive"
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
// Silently fail
|
||||
}
|
||||
list($usec, $sec) = explode(' ', microtime());
|
||||
?>
|
||||
<Response>
|
||||
<Error Time="<?=date('H:i:s', $sec) . substr($usec, 0, strlen($usec) - 2);?>" Id="<?=rand(1000000000, 9999999999);?>">
|
||||
<ErrorCode>600</ErrorCode>
|
||||
<Message>Invalid Request</Message>
|
||||
<DebugData />
|
||||
</Error>
|
||||
</Response>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if (!empty($MailboxData['name'])) {
|
||||
$displayname = $MailboxData['name'];
|
||||
}
|
||||
else {
|
||||
$displayname = $email;
|
||||
}
|
||||
try {
|
||||
$json = json_encode(
|
||||
array(
|
||||
"time" => time(),
|
||||
"ua" => $_SERVER['HTTP_USER_AGENT'],
|
||||
"user" => $email,
|
||||
"ip" => $_SERVER['REMOTE_ADDR'],
|
||||
"service" => $autodiscover_config['autodiscoverType']
|
||||
)
|
||||
);
|
||||
$redis->lPush('AUTODISCOVER_LOG', $json);
|
||||
$redis->lTrim('AUTODISCOVER_LOG', 0, 100);
|
||||
}
|
||||
catch (RedisException $e) {
|
||||
$_SESSION['return'][] = array(
|
||||
'type' => 'danger',
|
||||
'msg' => 'Redis: '.$e
|
||||
);
|
||||
return false;
|
||||
}
|
||||
if ($autodiscover_config['autodiscoverType'] == 'imap') {
|
||||
?>
|
||||
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
|
||||
<User>
|
||||
@@ -238,6 +298,3 @@ if ($login_role === "user") {
|
||||
}
|
||||
?>
|
||||
</Autodiscover>
|
||||
<?php
|
||||
}
|
||||
?>
|
||||
|
||||
@@ -1007,9 +1007,9 @@ if (isset($_GET['query'])) {
|
||||
['db' => 'last_pw_change', 'dt' => 5, 'dummy' => true, 'order_subquery' => "JSON_EXTRACT(attributes, '$.passwd_update')"],
|
||||
['db' => 'in_use', 'dt' => 6, 'dummy' => true, 'order_subquery' => "(SELECT SUM(bytes) FROM `quota2` WHERE `quota2`.`username` = `m`.`username`) / `m`.`quota`"],
|
||||
['db' => 'name', 'dt' => 7],
|
||||
['db' => 'messages', 'dt' => 20, 'dummy' => true, 'order_subquery' => "SELECT SUM(messages) FROM `quota2` WHERE `quota2`.`username` = `m`.`username`"],
|
||||
['db' => 'tags', 'dt' => 23, 'dummy' => true, 'search' => ['join' => 'LEFT JOIN `tags_mailbox` AS `tm` ON `tm`.`username` = `m`.`username`', 'where_column' => '`tm`.`tag_name`']],
|
||||
['db' => 'active', 'dt' => 24],
|
||||
['db' => 'messages', 'dt' => 18, 'dummy' => true, 'order_subquery' => "SELECT SUM(messages) FROM `quota2` WHERE `quota2`.`username` = `m`.`username`"],
|
||||
['db' => 'tags', 'dt' => 20, 'dummy' => true, 'search' => ['join' => 'LEFT JOIN `tags_mailbox` AS `tm` ON `tm`.`username` = `m`.`username`', 'where_column' => '`tm`.`tag_name`']],
|
||||
['db' => 'active', 'dt' => 21],
|
||||
];
|
||||
|
||||
require_once $_SERVER['DOCUMENT_ROOT'] . '/inc/lib/ssp.class.php';
|
||||
|
||||
@@ -111,8 +111,7 @@
|
||||
"tags": "Štítky",
|
||||
"dry": "Simulovat synchronizaci",
|
||||
"internal": "Interní",
|
||||
"internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů.",
|
||||
"sender_allowed": "Povolit jako alias pro odesílání"
|
||||
"internal_info": "Interní aliasy jsou přístupné jen z vlastních domén nebo jejich aliasů."
|
||||
},
|
||||
"admin": {
|
||||
"access": "Přístupy",
|
||||
@@ -305,7 +304,7 @@
|
||||
"rspamd_com_settings": "Název nastavení se vygeneruje automaticky, viz ukázky nastavení níže. Více informací viz <a href=\"https://rspamd.com/doc/configuration/settings.html#settings-structure\" target=\"_blank\">Rspamd dokumentace</a>",
|
||||
"rspamd_global_filters": "Mapa globálních filtrů",
|
||||
"rspamd_global_filters_agree": "Budu opatrný!",
|
||||
"rspamd_global_filters_info": "Mapa globálních filtrů obsahuje různé seznamy povolených a zakázaných serverů.",
|
||||
"rspamd_global_filters_info": "Mapa globálních filtrů obsahuje různé seznamy povolených a zakázaných serverů",
|
||||
"rspamd_global_filters_regex": "Názvy stačí k vysvětlení. Položky musejí obsahovat jen platné regulární výrazy ve tvaru \"/vyraz/parametry\" (e.g. <code>/.+@domena\\.tld/i</code>).<br>\n Každý výraz bude podroben základní kontrole, přesto je možné Rspamd 'rozbít', nebude-li syntax zcela korektní.<br>\n Rspamd se pokusí po každé změně načíst mapu znovu. V případě potíží <a href=\"\" data-toggle=\"modal\" data-container=\"rspamd-mailcow\" data-target=\"#RestartContainer\">restartujte Rspamd</a>, aby se konfigurace načetla explicitně.",
|
||||
"rspamd_settings_map": "Nastavení Rspamd",
|
||||
"sal_level": "Úroveň 'Moo'",
|
||||
@@ -781,9 +780,7 @@
|
||||
"mta_sts_max_age_info": "Doba v sekundách, po niž poštovní servery mohou toho pravidlo držet v mezipaměti bez nutnosti obnovení.",
|
||||
"mta_sts_mx": "Server MX",
|
||||
"mta_sts_mx_info": "Dovoluje odesílání jen výslovně vypsaným poštovním serverům; odesílající server kontroluje, že server MX určený v DNS odpovídá pravidlu, a povolí doručení jen s platným certifikátem TLS (chrání přes útokem typu MITM).",
|
||||
"mta_sts_mx_notice": "Lze zadat více serverů MX (oddělte čárkou).",
|
||||
"sender_allowed": "Povolit jako alias pro odesílání",
|
||||
"sender_allowed_info": "Není-li povoleno, lze alias použít jen pro příjem pošty. Lze také obejít v Sender ACL a nastavit konkrétní schránky, jež tento alias mohou používat"
|
||||
"mta_sts_mx_notice": "Lze zadat více serverů MX (oddělte čárkou)."
|
||||
},
|
||||
"fido2": {
|
||||
"confirm": "Potvrdit",
|
||||
|
||||
@@ -111,8 +111,7 @@
|
||||
"validate": "Проверить",
|
||||
"validation_success": "Проверка прошла успешно",
|
||||
"internal": "Внутренний",
|
||||
"internal_info": "Внутренние псевдонимы доступны только из самого домена или доменов-псевдонимов.",
|
||||
"sender_allowed": "Разрешить отправку с этим псевдонимом"
|
||||
"internal_info": "Внутренние псевдонимы доступны только из самого домена или доменов-псевдонимов."
|
||||
},
|
||||
"admin": {
|
||||
"access": "Настройки доступа",
|
||||
@@ -782,9 +781,7 @@
|
||||
"mta_sts_max_age_info": "Время в секундах, в течение которого принимающие почтовые серверы могут кэшировать эту политику перед повторной загрузкой.",
|
||||
"mta_sts_mx": "Сервер MX",
|
||||
"mta_sts_mx_info": "Разрешает отправку только на явно указанные имена хостов почтовых серверов; отправляющий MTA проверяет, соответствует ли DNS-имя MX-хоста списку политик, и разрешает доставку только с подлинным TLS-сертификатом (защита от MITM).",
|
||||
"mta_sts_mx_notice": "Можно указать несколько MX-серверов (через запятую).",
|
||||
"sender_allowed": "Разрешить отправку с этим псевдонимом",
|
||||
"sender_allowed_info": "Если отключено, этот псевдоним может только принимать почту. Используйте ACL отправителя, чтобы переопределить и предоставить определенным почтовым ящикам разрешение на отправку."
|
||||
"mta_sts_mx_notice": "Можно указать несколько MX-серверов (через запятую)."
|
||||
},
|
||||
"fido2": {
|
||||
"confirm": "Подтвердить",
|
||||
|
||||
@@ -111,8 +111,7 @@
|
||||
"timeout2": "Časovna omejitev za povezavo do lokalnega gostitelja",
|
||||
"dry": "Simuliraj sinhronizacijo",
|
||||
"internal": "Notranje",
|
||||
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.",
|
||||
"sender_allowed": "Dovoli pošiljanje kot ta vzdevek"
|
||||
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen."
|
||||
},
|
||||
"admin": {
|
||||
"access": "Dostop",
|
||||
@@ -781,9 +780,7 @@
|
||||
"mta_sts_mx_info": "Omogoča pošiljanje samo na izrecno navedena imena gostiteljskih strežnikov poštnih strežnikov; pošiljajoči MTA preveri, ali se ime gostitelja DNS MX ujema s seznamom pravilnikov, in dovoljuje dostavo le z veljavnim potrdilom TLS (zaščita pred MITM).",
|
||||
"mta_sts_mx_notice": "Določiti je mogoče več strežnikov MX (ločenih z vejicami).",
|
||||
"internal": "Notranje",
|
||||
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen.",
|
||||
"sender_allowed": "Dovoli pošiljanje kot ta vzdevek",
|
||||
"sender_allowed_info": "Če je onemogočeno, lahko ta vzdevek samo prejema pošto. Za preglasitev in dodelitev dovoljenja za pošiljanje določenim poštnim predalom uporabite seznam za nadzor dostopa pošiljatelja."
|
||||
"internal_info": "Notranji vzdevki so dostopni samo iz lastne domene ali vzdevkov domen."
|
||||
},
|
||||
"footer": {
|
||||
"restart_container_info": "<b>Pomembno:</b> Eleganten ponovni zagon lahko traja nekaj časa, zato počakajte, da se konča.",
|
||||
|
||||
@@ -111,8 +111,7 @@
|
||||
"timeout2": "Thời gian chờ kết nối đến máy chủ cục bộ",
|
||||
"username": "Tên người dùng",
|
||||
"validate": "Xác thực",
|
||||
"validation_success": "Xác thực thành công",
|
||||
"sender_allowed": "Cho phép gửi dưới bí danh này"
|
||||
"validation_success": "Xác thực thành công"
|
||||
},
|
||||
"admin": {
|
||||
"access": "Truy cập",
|
||||
|
||||
@@ -24,7 +24,7 @@
|
||||
"sogo_access": "管理 SOGo 存取權",
|
||||
"sogo_profile_reset": "重設 SOGo 個人資料",
|
||||
"spam_alias": "臨時別名",
|
||||
"spam_policy": "封鎖名單/允許名單",
|
||||
"spam_policy": "黑名單/白名單",
|
||||
"spam_score": "垃圾郵件分數",
|
||||
"syncjobs": "同步任務",
|
||||
"tls_policy": "TLS 規則",
|
||||
@@ -1180,7 +1180,7 @@
|
||||
"no_last_login": "沒有最後 UI 登入訊息",
|
||||
"no_record": "沒有紀錄",
|
||||
"open_logs": "開啟日誌",
|
||||
"open_webmail_sso": "網頁信箱",
|
||||
"open_webmail_sso": "网络邮件",
|
||||
"password": "密碼",
|
||||
"password_now": "目前密碼 (確認更改)",
|
||||
"password_repeat": "密碼 (再次輸入)",
|
||||
|
||||
@@ -117,7 +117,7 @@ services:
|
||||
- rspamd
|
||||
|
||||
php-fpm-mailcow:
|
||||
image: ghcr.io/mailcow/phpfpm:8.2.29-1
|
||||
image: ghcr.io/mailcow/phpfpm:8.2.29
|
||||
command: "php-fpm -d date.timezone=${TZ} -d expose_php=0"
|
||||
depends_on:
|
||||
- redis-mailcow
|
||||
@@ -200,7 +200,7 @@ services:
|
||||
- phpfpm
|
||||
|
||||
sogo-mailcow:
|
||||
image: ghcr.io/mailcow/sogo:5.12.4-1
|
||||
image: ghcr.io/mailcow/sogo:5.12.4
|
||||
environment:
|
||||
- DBNAME=${DBNAME}
|
||||
- DBUSER=${DBUSER}
|
||||
@@ -252,7 +252,7 @@ services:
|
||||
- sogo
|
||||
|
||||
dovecot-mailcow:
|
||||
image: ghcr.io/mailcow/dovecot:2.3.21.1-1
|
||||
image: ghcr.io/mailcow/dovecot:2.3.21.1
|
||||
depends_on:
|
||||
- mysql-mailcow
|
||||
- netfilter-mailcow
|
||||
|
||||
122
helper-scripts/dev_tests/view_autodiscover.sh
Executable file
122
helper-scripts/dev_tests/view_autodiscover.sh
Executable file
@@ -0,0 +1,122 @@
|
||||
#!/bin/bash
|
||||
|
||||
# Autodiscover XML Debug Script
|
||||
# Usage: ./view_autodiscover.sh [OPTIONS] [email@domain.com]
|
||||
|
||||
# Function to display help
|
||||
show_help() {
|
||||
cat << EOF
|
||||
Autodiscover XML Debug Script
|
||||
|
||||
Usage: $0 [OPTIONS] [email@domain.com]
|
||||
|
||||
OPTIONS:
|
||||
-h, --help Show this help message
|
||||
-d, --domain FQDN Override autodiscover domain (default: autodiscover.DOMAIN)
|
||||
Example: -d mail.example.com
|
||||
|
||||
EXAMPLES:
|
||||
$0 user@example.com
|
||||
Test autodiscover for user@example.com using autodiscover.example.com
|
||||
|
||||
$0 -d mail.example.com user@example.com
|
||||
Test autodiscover for user@example.com using mail.example.com
|
||||
|
||||
$0 -d localhost:8443 user@example.com
|
||||
Test autodiscover using localhost:8443 (useful for development)
|
||||
|
||||
EOF
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Initialize variables
|
||||
EMAIL=""
|
||||
DOMAIN_OVERRIDE=""
|
||||
|
||||
# Parse command line arguments
|
||||
while [[ $# -gt 0 ]]; do
|
||||
case $1 in
|
||||
-h|--help)
|
||||
show_help
|
||||
;;
|
||||
-d|--domain)
|
||||
DOMAIN_OVERRIDE="$2"
|
||||
shift 2
|
||||
;;
|
||||
-*)
|
||||
echo "Error: Unknown option $1"
|
||||
echo "Use -h or --help for usage information"
|
||||
exit 1
|
||||
;;
|
||||
*)
|
||||
EMAIL="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Check if xmllint is available
|
||||
if ! command -v xmllint &> /dev/null; then
|
||||
echo "WARNING: xmllint not found. Output will not be formatted."
|
||||
echo "Install with: apt install libxml2-utils (Debian/Ubuntu) or yum install libxml2 (CentOS/RHEL)"
|
||||
echo ""
|
||||
USE_XMLLINT=false
|
||||
else
|
||||
USE_XMLLINT=true
|
||||
fi
|
||||
|
||||
# Get email address from user input if not provided
|
||||
if [ -z "$EMAIL" ]; then
|
||||
read -p "Enter email address to test: " EMAIL
|
||||
fi
|
||||
|
||||
# Validate email format
|
||||
if [[ ! "$EMAIL" =~ ^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$ ]]; then
|
||||
echo "Error: Invalid email address format"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Extract domain from email
|
||||
EMAIL_DOMAIN="${EMAIL#*@}"
|
||||
|
||||
# Determine autodiscover URL
|
||||
if [ -n "$DOMAIN_OVERRIDE" ]; then
|
||||
AUTODISCOVER_URL="https://${DOMAIN_OVERRIDE}/Autodiscover/Autodiscover.xml"
|
||||
echo "Testing Autodiscover for: $EMAIL"
|
||||
echo "Override domain: $DOMAIN_OVERRIDE"
|
||||
else
|
||||
AUTODISCOVER_URL="https://autodiscover.${EMAIL_DOMAIN}/Autodiscover/Autodiscover.xml"
|
||||
echo "Testing Autodiscover for: $EMAIL"
|
||||
fi
|
||||
|
||||
echo "URL: $AUTODISCOVER_URL"
|
||||
echo "============================================"
|
||||
echo ""
|
||||
|
||||
# Make the request
|
||||
RESPONSE=$(curl -k -s -X POST "$AUTODISCOVER_URL" \
|
||||
-H "Content-Type: text/xml" \
|
||||
-d "<?xml version=\"1.0\" encoding=\"utf-8\"?>
|
||||
<Autodiscover xmlns=\"http://schemas.microsoft.com/exchange/autodiscover/request/2006\">
|
||||
<Request>
|
||||
<EMailAddress>$EMAIL</EMailAddress>
|
||||
<AcceptableResponseSchema>http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a</AcceptableResponseSchema>
|
||||
</Request>
|
||||
</Autodiscover>")
|
||||
|
||||
# Check if response is empty
|
||||
if [ -z "$RESPONSE" ]; then
|
||||
echo "Error: No response received from server"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Format and display output
|
||||
if [ "$USE_XMLLINT" = true ]; then
|
||||
echo "$RESPONSE" | xmllint --format - 2>&1
|
||||
else
|
||||
echo "$RESPONSE"
|
||||
fi
|
||||
|
||||
echo ""
|
||||
echo "============================================"
|
||||
echo "Response length: ${#RESPONSE} bytes"
|
||||
Reference in New Issue
Block a user