Private/Get-AdUserFromDomainsByMail.ps1
function Get-AdUserFromDomainsByMail { <# .SYNOPSIS Look up a user by e-mail in multiple child domains (pure ADSISearcher). .PARAMETER Email SMTP address to resolve (mail attribute). .PARAMETER Domains Array of DNS domain names to search in order .PARAMETER Properties Attribute(s) you want back – defaults to samAccountName + distinguishedName. Provide an array for multiple, e.g. @('samAccountName','manager') .OUTPUTS PSCustomObject { Domain ; Property1 ; Property2 … } – or $null if not found. #> [CmdletBinding()] param( [Parameter(Mandatory)][string] $Email, [Parameter(Mandatory)][string[]] $Domains, [string[]] $Properties = @('samAccountName','distinguishedName') ) # Escape specials per RFC 4515 (only needed for \ * ( ) ) $safeMail = $Email -replace '([\\\*\(\)])', { '\{0:x2}' -f [byte][char]$args[0].Value } # Build common LDAP filter once $ldapFilter = "(&(objectCategory=person)(objectClass=user)(mail=$safeMail)" + "(!(userAccountControl:1.2.840.113556.1.4.803:=2)))" foreach ($dnsDomain in $Domains) { # Convert DNS "child.thermo.com" → "DC=child,DC=thermo,DC=com" $dcParts = $dnsDomain -split '\.' | ForEach-Object { "DC=$_" } $nc = $dcParts -join ',' try { $searchRoot = [ADSI]"GC://$nc" $searcher = New-Object DirectoryServices.DirectorySearcher $searcher.SearchRoot = $searchRoot $searcher.SearchScope = 'Subtree' $searcher.PageSize = 100 $searcher.Filter = $ldapFilter $null = $searcher.PropertiesToLoad.Clear() $null = $searcher.PropertiesToLoad.AddRange($Properties) $result = $searcher.FindOne() if ($result) { $obj = [pscustomobject]@{ Domain = $dnsDomain } foreach ($p in $Properties) { $obj | Add-Member -NotePropertyName $p ` -NotePropertyValue $result.Properties[$p][0] } return $obj } } catch { Write-Warning "Error searching domain $dnsDomain : $_" } } Write-Verbose "User not found in any supplied domain." return $null } |