Powershell 当显示名中有特殊字符时,获取通讯组中所有显示名的SMTP地址

Powershell 当显示名中有特殊字符时,获取通讯组中所有显示名的SMTP地址,powershell,exchange-server-2013,Powershell,Exchange Server 2013,因此,我回来问更多关于获取已接受发件人、主持人和ManagedBy的通讯组SMTP地址的问题 所以我的剧本,几乎完美无瑕。但是,当我使用显示名称从AcceptMessagesOnly发件人或成员中提取smtp地址列表时,除非名称或其他空格中有特殊字符,否则该列表有效。所以显示名格式是Last,First,只要格式遵循这个规则,我们就可以了。但是,如果姓氏中有空格,如Mac Gruber、Steven或it Dept,则不会获取SMTP地址 我很确定问题出在我用来从acceptmessageson

因此,我回来问更多关于获取已接受发件人、主持人和ManagedBy的通讯组SMTP地址的问题

所以我的剧本,几乎完美无瑕。但是,当我使用显示名称从AcceptMessagesOnly发件人或成员中提取smtp地址列表时,除非名称或其他空格中有特殊字符,否则该列表有效。所以显示名格式是Last,First,只要格式遵循这个规则,我们就可以了。但是,如果姓氏中有空格,如Mac Gruber、Steven或it Dept,则不会获取SMTP地址

我很确定问题出在我用来从acceptmessagesonlyfromsendersormembers属性中列出的规范名称列表中获取显示名称的拆分逻辑中

下面是脚本供参考

$props = @(
    "DisplayName"
    "SamAccountName"
    "PrimarySmtpAddress"
    @{n='Accepted Senders';e= {($_.acceptmessagesonlyfromsendersormembers | Foreach-Object {
    (Get-AdUser -Filter "DisplayName -eq '$($_.Split('/')][-1])'" -Property ProxyAddresses |
        Select-Object -Expand ProxyAddresses | Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:'}) -join '; '}}
    "ModerationEnabled"
    @{N="ModeratedBy";E= {($_.ModeratedBy | ForEach-Object {
    (Get-AdUser -Filter "DisplayName -eq '$($_.Split("/")[-1])'" -Property ProxyAddresses |
        Select-Object -Expand ProxyAddresses | Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:'}) -join '; '}}
    @{Name="Internal Senders Only";E={$_.RequireSenderAuthenticationEnabled}}
    @{N="ManagedBy";E= {($_.ManagedBy | ForEach-Object {
    (Get-AdUser -Filter "DisplayName -eq '$($_.Split("/")[-1])'" -Property ProxyAddresses |
        Select-Object -Expand ProxyAddresses | Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:'}) -join '; '}}
        )
Get-DistributionGroup -ResultSize Unlimited | Select-Object $props -First 1000 | export-Csv x:\xxx.csv -NoTypeInformation
一如既往,我们非常感谢您的帮助


Ryan

好的,问题是您的cmdlet正在输出CanonicalName,这是一个计算属性,而不是实际存储在AD中的内容。在JRV回答的帮助下,我们有了一个将CanonicalName转换为DifferentizedName的函数。DN可以直接传递给ADUser,这简化了事情。首先是函数,稍作修改以很好地接受管道输入:

Function Convert-CanonicalName{   
    Param(
            [Parameter(Mandatory, ValueFromPipeline)]
            [string[]]$CanonicalName
    )
BEGIN{
    Try{
        $NameTranslate = New-Object -ComObject NameTranslate
        [void]$NameTranslate.GetType().InvokeMember('Init', 'InvokeMethod', $NULL, $NameTranslate, @(3, 2))
    }
    Catch{
        Throw $_
    }
}
PROCESS{
    ForEach($User in $CanonicalName){
        Try{
            [void]$NameTranslate.GetType().InvokeMember('Set', 'InvokeMethod', $NULL, $NameTranslate, @(8,$User))
            $NameTranslate.GetType().InvokeMember('Get', 'InvokeMethod', $NULL, $NameTranslate, @(1))
        }
        Catch{
            Throw $_
        }
    }
}
}
这允许我们将类似“MyDomain.Net/Users/Big Jimmy”的内容导入函数,并让它将“CN=Big Jimmy,OU=Users,DC=MyDomain,DC=Net”返回到管道中

接下来,让我们看一个计算属性:

@{n='Accepted Senders';e= {($_.acceptmessagesonlyfromsendersormembers | Foreach-Object {
(Get-AdUser -Filter "DisplayName -eq '$($_.Split('/')][-1])'" -Property ProxyAddresses |
    Select-Object -Expand ProxyAddresses | Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:'}) -join '; '}}
现在,我们实际上不需要ForEach对象循环。这里的所有内容都将包含一系列内容,处理每个项目,并将其适当地传递到管道中。所以我要放下它,为了便于阅读,我将把管道的每一部分放在它自己的线上。我们将要做的是从$\获取CanonicalNames输出。AcceptMessagesOnly从SendersOrMembers,将其传递到我们的新函数,该函数将它们转换为DNs,将其传递到Get ADUser,展开属性,筛选SMTP,清理字符串,并加入它们

@{n='Accepted Senders';e= {($_.acceptmessagesonlyfromsendersormembers | 
    Convert-CanonicalName |
    Get-AdUser -Property ProxyAddresses |
    Select-Object -Expand ProxyAddresses | 
    Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:' -join '; '}}

您应该能够以同样的结果修改其他项目。诚然,我没有可测试的Exchange服务器,但如果您获得了CNs阵列,那么这应该可以完成这项工作。

因此我想真正的问题是。。。当Get ADUser为-identity参数接受DifferentizedName时,为什么要尝试将DisplayName从DifferentizedName中解析出来,这样您甚至不需要使用-filter,只需要Get ADUser$\uUx属性ProxyAddressesOkay,尝试使用您建议的方法进行更新,但未返回已接受发件人(managedby或moderatedby)的任何电子邮件地址。这里是我更新的内容供参考。我不能复制整个东西,所以我只把我从接受的发件人$prop@{n=Accepted Senders e={$\.AcceptMessagesOnly fromSendersOrMembers | Foreach对象{Get AdUser$\属性ProxyAddresses | Select-Expand ProxyAddresses | Where对象{${uCmatch'^SMTP:'}替换'^SMTP:'}-join'}很抱歉,输出的不是DifferentiedName,而是CanonicalName,Get ADUser不接受我能确定的CN。而且,我似乎也不能用它来过滤。如果你有办法做到这一点,那就太棒了。编辑文章以反映CN而不是DNN,效果非常好!不过,我有一个问题,也许你可以帮忙。我们目前正在使用Get ADUser为acceptedsenders列表中的每个用户提取SMTP地址。但是,有时组本身就是一个可接受的发送者。发生这种情况时,我们不会获取用户的SMTP地址,因为他们不是广告用户,只是一个已通过电子邮件发送的启用对象。你能想办法同时获得这些邮件的SMTP地址吗?我们正在尝试与邮件收件人合作,而不是与ADUser合作,但它不合作。Lol总是有Get-ADObject-Property代理地址,您也可以像Get-ADUser一样通过管道将DN传递给它。这将发现DLs和用户,问题已解决。因此,我们有了解决方案,切换IGN以使ADObject解决最终问题。我想指出的是,我们还找到了第二个解决方案,取得了相同的结果。我把它包括在这里作为参考@{Name='Accepted Senders';Expression={$\.acceptMessagesOnly from sendersorMembers | Foreach Object{Get Recipient-Identity$\\-split$separator[-1]| Select primarySMTPaddress.primarySMTPaddress}-join','},引用的分隔符实际上是domain.com