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
}