So, I'm back with more questions about getting the Distribution Group SMTP addresses for the Accepted Senders, ModeratedBy and the ManagedBy.
So the script I've got, works almost perfectly. However, when I pull the list of smtp addresses from the acceptmessagesonlyfromsendorsormembers using the display name, it works unless there is a special character in the name or additional spaces. So the display name format is "Last, First", and as long as the formatting follows that rule, we're fine. However if the last name has a space in it such as "Mac Gruber, Steven" or "#IT-Dept" it doesn't grab the SMTP address.
I'm pretty sure that the problem is in the Split logic I'm using to get the display name from the list of canonical names that are listed in the acceptmessagesonlyfromsendersormembers property.
For reference the script is below.
$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
Any help is, as always, greatly appreciated.
Ryan
Ok, so the issue is that your cmdlet is outputting CanonicalName, which is a calculated property and not something actually stored in AD. With a little help from JRV's answer here, we have a function that will convert CanonicalName to DistinguishedName. DN can be passed to Get-ADUser
directly, which simplifies things. First, the function, slightly modified to accept piped input nicely:
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 $_
}
}
}
}
That allows us to pipe something like 'MyDomain.Net/Users/Big Jimmy'
into the function and have it return 'CN=Big Jimmy,OU=Users,DC=MyDomain,DC=Net'
to the pipeline.
Moving on, let's take one of your calculated properties:
@{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 '; '}}
Now, we don't actually need the ForEach-Object
loop in there. Everything here will take an array of things and process each item and pass it down the pipeline appropriately. So I'm going to drop that, and just for ease of reading I'm going to put each part of the pipeline on its own line. What we'll do is take the CanonicalNames output from $_.acceptmessagesonlyfromsendersormembers
, pipe it to our new function which converts them to DNs, pipe that into Get-ADUser
, expand the property, filter for SMTP, clean up the strings, and join them.
@{n='Accepted Senders';e= {($_.acceptmessagesonlyfromsendersormembers |
Convert-CanonicalName |
Get-AdUser -Property ProxyAddresses |
Select-Object -Expand ProxyAddresses |
Where-Object {$_ -cmatch '^SMTP:'}) -replace '^SMTP:' -join '; '}}
You should be able to modify your other items similarly with the same results. Admittedly I don't have an Exchange server to test against, but if you're getting an array of CNs then this should do the job.