将 UserPrincipalName 设置为与 PrimarySMTPAddress 相同?

Set the UserPrincipalName to be the same as PrimarySMTPAddress?

我需要修复以下脚本,其目标是将 UserprincipalName 设置为与 ProxyAddress SMTP: (PrimarySMTP) 条目相同。

$paramGetADUser = @{
    Filter      = "Enabled -eq 'True'"
    Properties  = 'EmailAddress', 'UserPrincipalName', 'SamAccountName'
    SearchBase  = 'OU=Users,DC=Domain,DC=com'
    SearchScope = 'Subtree'
}

$ADUsers = Get-ADUser @paramGetADUser |
    Where-Object { $_.UserPrincipalName -ne $_.EmailAddress } |
    Select-Object Name, EmailAddress, UserPrincipalName, SamAccountName

foreach ($ADuser in $ADUsers)
{
    Write-Host "Processing $($ADuser.Name)" -ForegroundColor Yellow
    
    $paramSetADUser = @{
        Identity = $ADuser.SamAccountName
        UserPrincipalName = $_.EmailAddress
    }
    
    Set-ADUser @paramSetADUser
    
    Get-ADUser -Identity $ADuser.SamAccountName |
    Select-Object Name, EmailAddress, UserPrincipalName |
    Format-Table -AutoSize
}

当没有 EmailAddress 值时,上面的脚本会以某种方式重置或将 UserPrincipalName 设置为空,这很危险,不是我想要的。

如何防止上述问题并实现 UPN = PrimarySMTPAddress 的标准化?

对您当前代码的小修改,而不是使用 EmailAddress,使用 mail 并使用 AD Filter / LDAP Filter 仅查询具有此属性集的用户:

$paramGetADUser = @{
    LDAPFilter  = "(&(!userAccountControl:1.2.840.113556.1.4.803:=2)(mail=*))"
    Properties  = 'mail', 'UserPrincipalName', 'SamAccountName'
    SearchBase  = 'OU=Users,DC=Domain,DC=com'
    SearchScope = 'Subtree'
}

foreach ($ADuser in Get-ADUser @paramGetADUser) {

    if($ADUser.UserPrincipalName -eq $ADuser.mail) {
        continue
    }
    
    Write-Host "Processing $($ADuser.Name)" -ForegroundColor Yellow
    
    $paramSetADUser = @{
        Identity = $ADuser.SamAccountName
        UserPrincipalName = $ADuser.mail
    }
    
    Set-ADUser @paramSetADUser
    
    Get-ADUser -Identity $ADuser.SamAccountName |
    Select-Object Name, EmailAddress, UserPrincipalName |
    Format-Table -AutoSize
}

您的问题是关于从用户 ProxyAddress 属性(Exchange 也从中获取)获取主电子邮件地址的问题是正确的。
据我所知,您不应依赖用户 mail 属性,该属性的值可能与实际用于发送电子邮件的值完全不同。

我建议如下:

# Get-ADUser by default already returns objects with these properties:
# DistinguishedName, Enabled, GivenName, Name, ObjectClass, ObjectGUID, SamAccountName, SID, Surname, UserPrincipalName
$paramGetADUser = @{
    Filter      = "Enabled -eq 'True'"
    Properties  = 'ProxyAddresses', 'EmailAddress'
    SearchBase  = 'OU=Users,DC=Domain,DC=com'
    SearchScope = 'Subtree'
}

$result = Get-ADUser @paramGetADUser | ForEach-Object {
    $primaryMail = ($_.ProxyAddresses | Where-Object { $_ -clike 'SMTP:*' }) -replace '^SMTP:'
    if ([string]::IsNullOrWhiteSpace($primaryMail)) {
        Write-Warning "User $($_.SamAccountName) does not have a Primary Email Address.."
        continue
    }
    if ($_.UserPrincipalName -eq $primaryMail) {
        Write-Host "User $($_.SamAccountName) already has a correct UPN"
        # output unchanged
        $_ | Select-Object Name, EmailAddress, UserPrincipalName, SamAccountName, @{Name = 'IsUpdated'; Expression = {'No'}}
    }
    else {
        Write-Host "Setting UPN for user $($_.SamAccountName) to '$primaryMail'"
        $_ | Set-ADUser -UserPrincipalName $primaryMail

        # refresh and output
        Get-ADUser -Identity $_.DistinguishedName | 
        Select-Object Name, EmailAddress, UserPrincipalName, SamAccountName, @{Name = 'IsUpdated'; Expression = {'Yes'}}
    }
}

# output on screen
$result | Format-Table -AutoSize

# output to CSV file
$result | Export-Csv -Path 'X:\somewhere\UserPrincipalNames.csv' -NoTypeInformation