PowerShell Script to Retrieve Active Directory User Login Names from Email Addresses


39 views

When managing Active Directory environments, administrators often need to correlate email addresses with user login names. This is particularly useful when you have a list of email addresses (from audit reports, mailing lists, or spreadsheets) and need to retrieve corresponding account information.

Here's a robust PowerShell solution that queries Active Directory using email addresses as the search criteria:

# Import the Active Directory module
Import-Module ActiveDirectory

# Define the email address list (could be from a file)
$emailList = @(
    "user1@domain.com",
    "user2@domain.com",
    "user3@domain.com"
)

# Initialize an array to store results
$results = @()

foreach ($email in $emailList) {
    try {
        $user = Get-ADUser -Filter "EmailAddress -eq '$email'" -Properties *
        
        if ($user) {
            $result = [PSCustomObject]@{
                EmailAddress = $email
                SamAccountName = $user.SamAccountName
                UserPrincipalName = $user.UserPrincipalName
                DisplayName = $user.DisplayName
                Enabled = $user.Enabled
                LastLogonDate = $user.LastLogonDate
            }
            $results += $result
        }
    }
    catch {
        Write-Warning "Error processing email $email : $_"
    }
}

# Output results
$results | Format-Table -AutoSize

For production environments, you'll likely want to read from a CSV file and export results:

# Read emails from CSV (column named 'Email')
$emailList = Import-Csv -Path "C:\temp\user_emails.csv" | Select-Object -ExpandProperty Email

$results = foreach ($email in $emailList) {
    Get-ADUser -Filter "EmailAddress -eq '$email'" -Properties EmailAddress, SamAccountName, UserPrincipalName, Enabled |
    Select-Object EmailAddress, SamAccountName, UserPrincipalName, Enabled
}

# Export to CSV
$results | Export-Csv -Path "C:\temp\user_mapping_results.csv" -NoTypeInformation

For domains with thousands of users, this optimized approach reduces memory usage:

$emailHash = @{}
Import-Csv "C:\temp\emails.csv" | ForEach-Object { $emailHash[$_.Email] = $true }

Get-ADUser -Filter * -Properties EmailAddress | Where-Object {
    $emailHash.ContainsKey($_.EmailAddress)
} | Select-Object SamAccountName, EmailAddress, UserPrincipalName

Adding proper error handling ensures the script runs smoothly:

$logFile = "C:\temp\ad_email_query_$(Get-Date -Format 'yyyyMMdd').log"
Start-Transcript -Path $logFile

try {
    # Main script logic here
    # ...
}
catch {
    Write-Error "Script failed: $_"
    exit 1
}
finally {
    Stop-Transcript
}

If you need to search across multiple domains in a forest:

$domains = Get-ADForest | Select-Object -ExpandProperty Domains

foreach ($domain in $domains) {
    $params = @{
        Server = $domain
        Filter = "EmailAddress -eq 'target@email.com'"
        Properties = "SamAccountName", "EmailAddress"
    }
    Get-ADUser @params
}

As Windows administrators, we often need to correlate user email addresses with their actual Active Directory login names. This becomes crucial when dealing with bulk operations, audit reports, or troubleshooting access issues. The native Get-ADUser cmdlet doesn't provide a direct email-to-username mapping solution.

Here's a robust PowerShell script that queries Active Directory and returns login names along with additional account information. The script handles both individual email lookups and bulk processing from a text file.


# Import required module
Import-Module ActiveDirectory

function Get-LoginNameByEmail {
    param (
        [Parameter(Mandatory=$true)]
        [string]$Email
    )
    
    try {
        $user = Get-ADUser -Filter {EmailAddress -eq $Email} -Properties *
        
        if ($user) {
            [PSCustomObject]@{
                EmailAddress = $Email
                SamAccountName = $user.SamAccountName
                UserPrincipalName = $user.UserPrincipalName
                DisplayName = $user.DisplayName
                Enabled = $user.Enabled
                LastLogonDate = $user.LastLogonDate
            }
        } else {
            Write-Warning "No user found with email: $Email"
        }
    }
    catch {
        Write-Error "Error processing email $Email : $_"
    }
}

# Single email lookup example
Get-LoginNameByEmail -Email "john.doe@company.com"

# Bulk processing from file
$emailList = Get-Content "C:\temp\user_emails.txt"
$results = foreach ($email in $emailList) {
    Get-LoginNameByEmail -Email $email
}

# Export results to CSV
$results | Export-Csv -Path "C:\temp\user_mapping_results.csv" -NoTypeInformation

When processing large numbers of email addresses, consider these optimizations:


# Optimized bulk processing with parallel execution
$emailList = Get-Content "C:\temp\large_email_list.txt"
$results = $emailList | ForEach-Object -Parallel {
    Import-Module ActiveDirectory
    $user = Get-ADUser -Filter {EmailAddress -eq $_} -Properties SamAccountName, UserPrincipalName -ErrorAction SilentlyContinue
    if ($user) {
        [PSCustomObject]@{
            Email = $_
            LoginName = $user.SamAccountName
            UPN = $user.UserPrincipalName
        }
    }
} -ThrottleLimit 10

$results | Export-Csv -Path "C:\temp\optimized_results.csv" -NoTypeInformation

For production environments, add comprehensive error handling and logging:


function Get-ADUserByEmail {
    param (
        [string]$Email,
        [string]$LogPath = "C:\logs\ad_email_lookup.log"
    )
    
    $logMessage = "[$(Get-Date)] Processing email: $Email"
    Add-Content -Path $LogPath -Value $logMessage
    
    try {
        $user = Get-ADUser -Filter {EmailAddress -eq $Email} -Properties SamAccountName, DisplayName, Enabled -ErrorAction Stop
        
        if (-not $user) {
            $logMessage = "[$(Get-Date)] WARNING: No AD user found for email $Email"
            Add-Content -Path $LogPath -Value $logMessage
            return $null
        }
        
        return $user
    }
    catch [Microsoft.ActiveDirectory.Management.ADIdentityNotFoundException] {
        $logMessage = "[$(Get-Date)] ERROR: AD user not found for email $Email"
        Add-Content -Path $LogPath -Value $logMessage
        return $null
    }
    catch {
        $logMessage = "[$(Get-Date)] ERROR: Unexpected error processing email $Email - $($_.Exception.Message)"
        Add-Content -Path $LogPath -Value $logMessage
        return $null
    }
}

For environments with thousands of users, consider caching all users first:


# Cache all users with email addresses
$allUsers = Get-ADUser -Filter * -Properties EmailAddress, SamAccountName | 
            Where-Object {$_.EmailAddress}

# Create lookup hashtable
$emailToLoginMap = @{}
$allUsers | ForEach-Object {
    $emailToLoginMap[$_.EmailAddress] = $_.SamAccountName
}

# Example lookup
$emailToLoginMap["jane.smith@company.com"]

This solution can be extended to work with Exchange Online or other directory services:


# Hybrid environment example
function Get-UserIdentity {
    param (
        [string]$Email
    )
    
    # Try on-prem AD first
    $adUser = Get-ADUser -Filter {EmailAddress -eq $Email} -Properties SamAccountName -ErrorAction SilentlyContinue
    
    if ($adUser) {
        return @{
            Source = "OnPremAD"
            LoginName = $adUser.SamAccountName
        }
    }
    
    # Fallback to Exchange Online
    try {
        $exoUser = Get-EXOMailbox -Identity $Email -ErrorAction SilentlyContinue
        if ($exoUser) {
            return @{
                Source = "ExchangeOnline"
                LoginName = $exoUser.UserPrincipalName
            }
        }
    }
    catch {
        Write-Warning "Exchange Online module not available"
    }
    
    return $null
}