适用于: 2015
2019
订阅版
通过将 Microsoft Teams 服务与本地Exchange Server集成,可为托管在本地) Exchange Server (的邮箱启用 Teams 日历功能和云语音邮件集成。 有关详细信息,请参阅 Exchange 和 Microsoft Teams 交互方式 文档。
本主题适用于与任何受支持的 Exchange Server 版本的集成。 查看Exchange Server可支持性矩阵,了解哪些版本的Exchange Server处于受支持状态。
开始之前你需要了解哪些信息?
完成此任务的估计时间:15 分钟
在可以执行此过程或其他过程之前,你需要被分配适当的权限。 若要查看所需的权限,请参阅 Exchange 和 Shell 基础结构权限 主题。
有关可能适用于本主题中的过程的键盘快捷方式的信息,请参阅 Exchange 管理中心中的键盘快捷方式。
有关兼容性的信息,请参阅Skype for Business与 Office 应用的兼容性。
配置 Exchange Server 与 O365 之间的集成
步骤 1:在Exchange Server和Exchange Online之间配置 OAuth 身份验证
执行在 Exchange 和 Exchange Online 组织之间配置 OAuth 身份验证文档中概述的步骤。
步骤 2:创建Microsoft Teams 日历计划程序服务使用的新邮件用户帐户
必须在 Exchange 服务器上执行此步骤。 它创建邮件用户并分配必要的管理角色权限。 下一步将使用此帐户向Microsoft Teams 计划应用程序授予日历委派所需的权限。
为 Exchange 组织指定已验证域。 此域应与用于本地 Exchange 帐户的主简单邮件传输协议 (SMTP) 域使用的域相同。 以下过程中称为 <your Verified Domain>
此域。 此外, <DomainControllerFQDN>
应该是域控制器 (FQDN) 的完全限定域名。
$user = New-MailUser -Name "TeamsScheduler" -ApplicationAccount -ExternalEmailAddress "TeamsScheduler-ApplicationAccount@<your Verified Domain>" -DomainController <DomainControllerFQDN>
此命令在地址列表中隐藏新邮件用户:
Set-MailUser -Identity $user.Identity -HiddenFromAddressListsEnabled $true -DomainController <DomainControllerFQDN>
基于 UserApplication
角色创建新角色:
New-ManagementRole -Name "TeamsSchedulerRole" -Parent "UserApplication" -DomainController <DomainControllerFQDN>
从除 GetDelegate 之外的新角色中删除所有 cmdlet,因为这是计划 (委派) 服务所需的唯一命令:
Get-ManagementRoleEntry "TeamsSchedulerRole\*" -DomainController <DomainControllerFQDN> | Where-Object { $_.Name -ne "GetDelegate" } | Remove-ManagementRoleEntry -DomainController <DomainControllerFQDN>
将 TeamsSchedulerRole
角色分配给新帐户:
New-ManagementRoleAssignment -Role "TeamsSchedulerRole" -User $user.Identity -DomainController <DomainControllerFQDN>
步骤 3:创建并启用旧版 Skype for Business Online 集成
重要
Microsoft将在不久的将来弃用旧版 Skype for Business Online 第一方应用程序。 目前,此应用程序依赖于此应用程序,因此必须保持配置状态。 未能配置此合作伙伴应用程序将中断某些功能 (例如,外出语音邮件问候语的功能) 。 Microsoft会在删除应用程序安全时通知你。
使用之前在 步骤 2 中创建的帐户创建新的合作伙伴应用程序。 在本地 Exchange 组织中,在 Exchange 命令行管理程序中 (EMS) 运行以下命令:
New-PartnerApplication -Name "SfBOnline" -ApplicationIdentifier "00000004-0000-0ff1-ce00-000000000000" -Enabled $true -LinkedAccount $user.Identity
步骤 4:为 Teams 日历计划程序服务集成创建并启用合作伙伴应用程序
若要为Exchange Server (本地环境中的用户启用日历委派) 必须为 配置专用的Teams Calendar Scheduler Service
合作伙伴应用程序。
为此,请在本地 Exchange 服务器上的 Exchange 命令行管理程序中运行以下命令, (EMS) ,为 Teams Calendar Scheduler Service
创建新的合作伙伴应用程序。
此应用程序使用之前在 步骤 2 中创建的帐户:
New-PartnerApplication -Name "TeamsScheduler" -ApplicationIdentifier "7557eb47-c689-4224-abcf-aef9bd7573df" -Enabled $true -LinkedAccount $user.Identity
步骤 5:创建并启用合作伙伴应用程序以实现云语音邮件集成
若要为本地环境中的用户启用云语音邮件,必须为 配置专用的合作伙伴应用程序Cloud Voicemail
。
为此,请在本地 Exchange 服务器上的 Exchange 命令行管理程序 (EMS) 中运行以下命令,为 创建一个新的合作伙伴应用程序 Cloud Voicemail
:
New-PartnerApplication -Name "CloudVoicemail" -ApplicationIdentifier "db7de2b5-2149-435e-8043-e080dd50afae" -Enabled $true
步骤 6:导出Exchange Server身份验证证书
运行 PowerShell 脚本以导出Exchange Server身份验证证书的公钥,将在下一步中导入到 Microsoft Teams 组织。
将以下文本保存到名为 的 PowerShell 脚本文件, ExportAuthCert.ps1
例如 。
$thumbprint = (Get-AuthConfig).CurrentCertificateThumbprint
if((Test-Path $env:SYSTEMDRIVE\OAuthConfig) -eq $false)
{
New-Item -Path $env:SYSTEMDRIVE\OAuthConfig -Type Directory
}
Set-Location -Path $env:SYSTEMDRIVE\OAuthConfig
$oAuthCert = Get-ChildItem -Path Cert:\LocalMachine\My | Where-Object {$_.Thumbprint -match $thumbprint}
$certType = [System.Security.Cryptography.X509Certificates.X509ContentType]::Cert
$certBytes = $oAuthCert.Export($certType)
$CertFile = "$env:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer"
[System.IO.File]::WriteAllBytes($CertFile, $certBytes)
在本地 Exchange 组织中的 Exchange 命令行管理程序中,运行创建的 PowerShell 脚本。 例如:.\ExportAuthCert.ps1
步骤 7:上传Exchange Server身份验证证书
接下来,使用 Microsoft Graph PowerShell 模块将上一步中导出的本地身份验证证书上传到Microsoft Entra 访问控制服务 (ACS) 。 如果未安装模块,请以管理员身份打开Windows PowerShell窗口,并运行以下命令:
Install-Module -Name Microsoft.Graph.Applications
打开安装了 Microsoft Graph cmdlet 的Windows PowerShell工作区。 此步骤中的所有命令都必须使用连接到 Microsoft Graph 控制台的Windows PowerShell运行。
将以下文本保存到名为 的 PowerShell 脚本文件,
UploadAuthCert.ps1
例如 。Connect-MgGraph -Scopes Application.ReadWrite.All $CertFile = "$env:SYSTEMDRIVE\OAuthConfig\OAuthCert.cer" $objFSO = New-Object -ComObject Scripting.FileSystemObject $CertFile = $objFSO.GetAbsolutePathName($CertFile) $cer = [System.Security.Cryptography.X509Certificates.X509Certificate2]::new($CertFile) $binCert = $cer.GetRawCertData() $credValue = [System.Convert]::ToBase64String($binCert) $serviceNames = @("db7de2b5-2149-435e-8043-e080dd50afae", "7557eb47-c689-4224-abcf-aef9bd7573df", "00000004-0000-0ff1-ce00-000000000000") foreach ($serviceName in $serviceNames) { Write-Host "[+] Trying to query the service principals for service: $serviceName" -ForegroundColor Cyan $p = Get-MgServicePrincipal -Filter "AppId eq '$serviceName'" Write-Host "[+] Trying to query the keyCredentials for service: $serviceName" -ForegroundColor Cyan $servicePrincipalKeyInformation = Get-MgServicePrincipal -Filter "AppId eq '$serviceName'" -Select "keyCredentials" $keyCredentialsLength = $servicePrincipalKeyInformation.KeyCredentials.Length if ($keyCredentialsLength -gt 0) { Write-Host "[+] $keyCredentialsLength existing key(s) found - we keep them if they have not expired" -ForegroundColor Cyan $newCertAlreadyExists = $false $servicePrincipalObj = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphServicePrincipal $keyCredentialsArray = @() foreach ($cred in $servicePrincipalKeyInformation.KeyCredentials) { $thumbprint = [System.Convert]::ToBase64String($cred.CustomKeyIdentifier) Write-Host "[+] Processing existing key: $($cred.DisplayName) thumbprint: $thumbprint" -ForegroundColor Cyan if ($newCertAlreadyExists -ne $true) { $newCertAlreadyExists = ($cer.Thumbprint).Equals($thumbprint, [System.StringComparison]::OrdinalIgnoreCase) } if ($cred.EndDateTime -lt (Get-Date)) { Write-Host "[+] This key has expired on $($cred.EndDateTime) and will not be retained" -ForegroundColor Yellow continue } $keyCredential = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphKeyCredential $keyCredential.Type = "AsymmetricX509Cert" $keyCredential.Usage = "Verify" $keyCredential.Key = $cred.Key $keyCredentialsArray += $keyCredential } if ($newCertAlreadyExists -eq $false) { Write-Host "[+] New key: $($cer.Subject) thumbprint: $($cer.Thumbprint) will be added" -ForegroundColor Cyan $keyCredential = New-Object -TypeName Microsoft.Graph.PowerShell.Models.MicrosoftGraphKeyCredential $keyCredential.Type = "AsymmetricX509Cert" $keyCredential.Usage = "Verify" $keyCredential.Key = [System.Text.Encoding]::ASCII.GetBytes($credValue) $keyCredentialsArray += $keyCredential $servicePrincipalObj.KeyCredentials = $keyCredentialsArray Update-MgServicePrincipal -ServicePrincipalId $p.Id -BodyParameter $servicePrincipalObj } else { Write-Host "[+] New key: $($cer.Subject) thumbprint: $($cer.Thumbprint) already exists and will not be uploaded again" -ForegroundColor Yellow } } else { $params = @{ type = "AsymmetricX509Cert" usage = "Verify" key = [System.Text.Encoding]::ASCII.GetBytes($credValue) } Write-Host "[+] This is the first key which will be added to this service principal" -ForegroundColor Cyan Update-MgServicePrincipal -ServicePrincipalId $p.Id -KeyCredentials $params } }
运行你在上一步中创建的 PowerShell 脚本。 例如:
.\UploadAuthCert.ps1
在启动脚本之后,将显示凭据对话框。 输入 Microsoft Online Microsoft Entra 组织中的租户管理员帐户的凭据。 运行脚本后,将连接到 Microsoft Graph 会话Windows PowerShell保持打开状态。 在下一步中,你将使用该会话来运行 PowerShell 脚本。
步骤 8:验证证书是否已上传到第一方服务主体
在连接到 Microsoft Graph 会话的 PowerShell 中,运行以下命令
(Get-MgServicePrincipal -Filter "AppId eq '7557eb47-c689-4224-abcf-aef9bd7573df'" -Select "keyCredentials").KeyCredentials | Format-List * (Get-MgServicePrincipal -Filter "AppId eq 'db7de2b5-2149-435e-8043-e080dd50afae'" -Select "keyCredentials").KeyCredentials | Format-List * (Get-MgServicePrincipal -Filter "AppId eq '00000004-0000-0ff1-ce00-000000000000'" -Select "keyCredentials").KeyCredentials | Format-List *
确认你看到列出的密钥,其中包含与 Exchange OAuth 证书开始日期和结束日期匹配的开始日期和结束数据
验证是否成功
通过验证某些功能是否正常工作,验证配置是否正确。
确认 Exchange 混合配置中的云语音邮件功能
- 向具有活动
Out of Office
语音邮件问候语的用户拨打 Teams 电话。 - 留下语音邮件。
- 在通话期间收听问候语:
- 如果 CloudVoicemail 合作伙伴应用程序 正在运行,你将听到
Out of Office
问候语。 - 如果不起作用,将改为播放常规问候语。
- 如果 CloudVoicemail 合作伙伴应用程序 正在运行,你将听到
- 呼叫后,检查语音邮件是否已成功传递到用户的邮箱。
- 向具有活动
确认移动客户端的对话历史记录在 Outlook
Conversation History
文件夹中可见。使用 EWSEditor 确认存档的聊天邮件已存放在文件夹中的用户本地邮箱中
Purges
。或者,在 OAuth 握手期间检查流量。 OAuth 流量是不同的,与基本身份验证不同。 关键指标是令牌交换中是否存在颁发者标识符,例如:
7557eb47-c689-4224-abcf-aef9bd7573df@<realm>
db7de2b5-2149-435e-8043-e080dd50afae@<realm>
-
00000004-0000-0ff1-ce00-000000000000@<realm>
旧版第一方应用使用方案中的 ()
这些标识符还可能带有前导斜杠,例如:
/7557eb47-c689-4224-abcf-aef9bd7573df@<realm>
。 这些令牌不包括用户名或密码,这突出了 OAuth 的核心原则:无需凭据交换的身份验证。如果想要确保成功使用 OAuth,请确保知道预期内容,并了解流量应该是什么样子。 以下是 预期的结果。
下面是 设置示例,但你可以使用任何想要执行此过程的网络跟踪工具。
如何禁用旧版Skype for Business Online 集成
谨慎
目前不要删除旧版Skype for Business联机合作伙伴应用程序。 删除此第一方应用程序将中断不同功能的功能,例如外出语音邮件问候语,这仍依赖于旧的第一方应用程序。 Microsoft会在安全删除此应用程序后通知你。
具有应用程序 ID 00000004-0000-0ff1-ce00-000000000000
的旧版第一方Skype for Business Online 应用程序不久将弃用。 作为这项工作的一部分,引入了 Teams 日历计划程序服务和云语音邮件的专用第一方应用程序。
按照本部分中的步骤删除使用旧版第一方 Skype for Business Online
应用程序的任何合作伙伴应用程序:
Get-PartnerApplication | Where-Object { $_.ApplicationIdentifier -eq "00000004-0000-0ff1-ce00-000000000000" -and $_.Enabled -eq $true } | Remove-PartnerApplication