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
}