我正在尝试通过 HTTP 302 重定向方法配置自动发现服务,该方法重定向到通过 HTTPS 正确提供 autodiscover.xml 的域。使用此配置,iPhone 和 Android 上正确提供了 POP/IMAP/SMTP 和 EAS 自动发现设置,因此我相信服务配置正确且 XML 有效负载正确。此外https://testconnectivity.microsoft.com/在 Outlook 自动发现 ed Exchange ActiveSync 自动发现上都给出了积极的结果。
该问题仅发生在 Outlook for Office 365 和 Windows App Mail(在 Windows 10 上)。在这两种情况下,在注册表单中填写电子邮件地址后,对自动发现的请求都正常(我添加了生成的 XML 的打印输出,它是正确的)。但是,有第二个屏幕要求输入密码,这就是问题所在。基本上,向原始域(通过 HTTP 的域)发出了一个新的 GET 请求(/AutoDiscover/AutoDiscover.xml),但在这种情况下不会发生 302 重定向,并且会出现一个新窗口,显示未找到参数。就像输入密码后的第二次调用会期望与 302 重定向不同的答案。
为了更好地描述我的配置:
- 我请求自动发现的电子邮件地址:user@domain1.com
- DNS的配置:autodiscover.domain1.com CNAME to autodiscover.domain2.com
- autodiscover.domain1.com(通过 DNS 中的 CNAME 的 autodiscover.domain2.com 的 IP)仅通过 HTTP 应答,并执行 302 重定向到https://autodiscover.domain2.com/AutoDiscover/AutoDiscover.xml(不区分大小写)
- autodiscover.domain2.com 具有 Apache 规则,因此文件 AutoDiscover.xml(不区分大小写)由 PHP 脚本生成,该脚本分析请求内容并根据请求内容使用 EAS 或 Outlook 的适当 XML 进行回答。
我也尝试设置一个 SRV 记录直接指向 autodiscover.domain2.com 但结果是一样的。
我非常确信 XML 有效负载是正确的,因为在 Android 和 iPhone 上,EAS 配置良好,只有 Outlook 和 App Mail 无法使其正常工作。
任何帮助表示赞赏!
这是虚拟主机的配置:
<VirtualHost *:80>
ServerName autodiscover.domain2.com
ServerAlias autodiscover.*
ServerAlias autoconfig.*
DocumentRoot /var/www/autodiscover.domain2.com/public_html
ErrorLog /var/log/autodiscover.domain2.com_error_log
CustomLog /var/log/autodiscover.domain2.com_access_log combined
</VirtualHost>
<VirtualHost *:443>
ServerName atodiscover.domain2.com
ServerAlias autoconfig.domain2.com
DocumentRoot /var/www/autodiscover.domain2.com/public_html
ErrorLog /var/log/autodiscover.domain2.com_error_log
CustomLog /var/log/autodiscover.domain2.com_access_log combined
ScriptAlias /AutoDiscover/AutoDiscover.xml /var/www/autodiscover.domain2.com/public_html/outlook.php
ScriptAlias /Autodiscover/Autodiscover.xml /var/www/autodiscover.domain2.com/public_html/outlook.php
ScriptAlias /autodiscover/autodiscover.xml /var/www/autodiscover.domain2.com/public_html/outlook.php
SSLEngine on
SSLCertificateFile /path/to/ssl.cert
SSLCertificateKeyFile /path/to/ssl.key
SSLProtocol all -SSLv2 -SSLv3 -TLSv1 -TLSv1.1
</VirtualHost>
这是.htaccess:
RewriteEngine On
# thunderbird
RewriteRule ^.*config-v1\.1\.xml$ https://autodiscover.domain2.com/thunderbird.php [NC,L]
# redirect autodiscover.xml to https of domain2 (302)
RewriteCond %{HTTPS} off
RewriteRule ^.*autodiscover\.xml$ https://autodiscover.domain2.com%{REQUEST_URI} [NC,L,R=302]
# redirect autodiscover.xml to outlook.php
RewriteCond %{HTTP_HOST} ^autodiscover\.domain2\.com$ [NC]
RewriteRule ^.*autodiscover\.xml$ https://autodiscover.domain2.com/outlook.php [NC,L]
# redirect autodiscover.json to outlook.json.php
RewriteCond %{HTTP_HOST} ^autodiscover\.domain2\.com$ [NC]
RewriteRule ^.*autodiscover\.json$ https://autodiscover.domain2.com/outlook.json.php [NC,L]
这是放在 /var/www/html/autodiscover.domain2.com/public_html/ 中的 outlook.php 脚本:
<?php
header("Content-Type: application/xml");
$data = file_get_contents("php://input");
preg_match("/\<EMailAddress\>(.*?)\<\/EMailAddress\>/", $data, $matches);
if($matches == false || count($matches)!=2) exit(0);
$ar = explode('@' ,$matches[1]);
if(count($ar)!=2) exit(0);
$account = $ar[0];
$domain = $ar[1];
$email = $matches[1];
$provider = 'domain2.com';
$buf = '';
if(preg_match('/mobilesync/',$data))
{
$buf = '<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/mobilesync/responseschema/2006">
<Culture>en:us</Culture>
<User>
<DisplayName>'.$email.'</DisplayName>
<EMailAddress>'.$email.'</EMailAddress>
</User>
<Action>
<Settings>
<Server>
<Type>MobileSync</Type>
<Url>https://eas.domain2.com/Microsoft-Server-ActiveSync</Url>
<Name>https://eas.domain2.com/Microsoft-Server-ActiveSync</Name>
</Server>
</Settings>
</Action>
</Response>
</Autodiscover>';
}
else
{
$buf = '<?xml version="1.0" encoding="utf-8" ?>
<Autodiscover xmlns="http://schemas.microsoft.com/exchange/autodiscover/responseschema/2006">
<Response xmlns="http://schemas.microsoft.com/exchange/autodiscover/outlook/responseschema/2006a">
<User>
<DisplayName>'.$email.'</DisplayName>
</User>
<Account>
<AccountType>email</AccountType>
<Action>settings</Action>
<Protocol>
<Type>POP3</Type>
<Server>pop.'.$provider.'</Server>
<Port>995</Port>
<LoginName>'.$email.'</LoginName>
<DomainRequired>off</DomainRequired>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
<DomainRequired>off</DomainRequired>
</Protocol>
<Protocol>
<Type>IMAP</Type>
<Server>imap.'.$provider.'</Server>
<Port>993</Port>
<DomainRequired>off</DomainRequired>
<LoginName>'.$email.'</LoginName>
<SPA>off</SPA>
<SSL>on</SSL>
<AuthRequired>on</AuthRequired>
</Protocol>
<Protocol>
<Type>SMTP</Type>
<Server>smtp.'.$provider.'</Server>
<Port>465</Port>
<DomainRequired>off</DomainRequired>
<LoginName>'.$email.'</LoginName>
<SPA>off</SPA>
<Encryption>SSL</Encryption>
<AuthRequired>on</AuthRequired>
<UsePOPAuth>off</UsePOPAuth>
<SMTPLast>off</SMTPLast>
</Protocol>
</Account>
</Response>
</Autodiscover>';
}
echo $buf;
这是outlook.json.php:
<?php
$url = 'https://eas.domain2.com/Microsoft-Server-ActiveSync';
header('Content-type: application/json');
if (strtolower($_GET['Protocol']) == 'activesync') {
echo '{"Protocol":"ActiveSync","Url":"' . $url . '"}';
}
elseif (strtolower($_GET['Protocol']) == 'autodiscoverv1') {
echo '{"Protocol":"AutodiscoverV1","Url":"https://' . $_SERVER['HTTP_HOST'] . '/Autodiscover/Autodiscover.xml"}';
}
else {
http_response_code(400);
echo '{"ErrorCode":"InvalidProtocol","ErrorMessage":"The given protocol value \u0027' . $_GET['Protocol'] . '\u0027 is invalid. Supported values are \u0027ActiveSync,AutodiscoverV1\u0027"}';
}