Powershell : Extracting Email Addresses from Firstname and Surname Data

Recently, I faced a common IT administrative task: extracting email addresses from Active Directory for a list of users but in the format of "Firstname Surname" this task which seemed like a straightforward quickly revealed some interesting challenges where the data was not samAccount name or any valid computer based data, but human derived data.

I started with a simple text file containing a list of users in the format:

John Smith
Jane Doe
Robert-J Johnson
Sarah-MB Williams
Michael Brown
Sam Taylor

My goal was clear: look up each user in Active Directory and extract their SMTP email address that ends with "@bythepowerofgreyskull.com". I also needed to make sure I was only retrieving information for enabled accounts.

First Attempt: The Basics

I started with a basic PowerShell script that would:

  1. Read the list of users from a text file
  2. Split each line into first name and last name
  3. Query AD for matching users
  4. Extract their email addresses

Here's what my initial approach looked like:

# Read the list of users
$users = Get-Content -Path "UserList.txt"
$results = @()

foreach ($user in $users) {
    # Split into first name and last name
    $nameParts = $user -split " ", 2
    $firstName = $nameParts[0]
    $lastName = $nameParts[1]
    
    # Search AD
    $adUser = Get-ADUser -Filter "GivenName -like '$firstName*' -and Surname 
    -eq '$lastName'" -Properties EmailAddress
    
    # Extract email
    $results += [PSCustomObject]@{
        FullName = $user
        FirstName = $firstName
        LastName = $lastName
        Email = $adUser.EmailAddress
    }
}

# Export to CSV
$results | Export-Csv -Path "C:\Path\To\UserEmails.csv" -NoTypeInformation
The First Challenge: Hyphenated Names

I quickly realized that some of the names in my list had hyphens in the first name, like "Adam-J" or "Adam-PR". This was causing issues with AD lookups because these naming conventions don't always match exactly with what's stored in Active Directory.

I added some logic to handle hyphenated first names:

# Handle first names with hyphens
if ($firstName -match "-") {
    $firstNameParts = $firstName -split "-"
    $firstName = $firstNameParts[0]  # Use only the first part for searching
}

This modification would allow "Adam-J" to match with "Adam" in Active Directory.

The Second Challenge: Multiple Results

When I ran the script and checked the output, I noticed another issue. Some results showed:

"FullName","FirstName","LastName","Email"
"John Smith","John","Smith","System.Object[]"
"Jayne Doe","Jayne","Doe","System.Object[]"

The "System.Object[]" indicated that the script was returning multiple AD user objects for a single name lookup. This happens when there are several accounts with similar names in AD.

I needed to handle this situation by properly selecting one account from multiple matches:

if ($adUsers -is [array]) {
    # Try to find exact match first
    $exactMatch = $adUsers | Where-Object { $_.GivenName -eq $firstName -and 
       $_.Surname -eq $lastName } | Select-Object -First 1
    
    if ($exactMatch) {
        $email = $exactMatch.EmailAddress
    }
    else {
        # If no exact match, take the first result
        $email = $adUsers[0].EmailAddress
    }
}
else {
    # Single user found
    $email = $adUsers.EmailAddress
}
The Third Challenge: Specific Domain Emails

My next discovery came when examining the log file. I needed to specifically look for email addresses in the "@bythepowerofgreyskull.com" domain, not just any email address. In Active Directory, users can have multiple email attributes, and I needed to ensure I was getting the correct one.

This required me to look at both the primary email address and the proxyAddresses attribute:

function Get-SeverntrentEmail {
    param ($User)
    
    # First check if the main EmailAddress is a severntrent.co.uk address
    if ($User.EmailAddress -like "*@bythepowerofgreyskull.com") {
        return $User.EmailAddress
    }
    
    # If not, check proxyAddresses for severntrent.co.uk addresses
    if ($User.proxyAddresses) {
        # Look for primary SMTP address first that matches severntrent.co.uk
        $primarySmtp = $User.proxyAddresses | Where-Object { 
            $_ -like "SMTP:*@bythepowerofgreyskull" 
        } | Select-Object -First 1
        
        if ($primarySmtp) {
            # Remove the "SMTP:" prefix
            return ($primarySmtp -replace "SMTP:", "")
        }
        
        # If no primary, look for any secondary smtp addresses
        $secondarySmtp = $User.proxyAddresses | Where-Object { 
            $_ -like "smtp:*@severntrent.co.uk" 
        } | Select-Object -First 1
        
        if ($secondarySmtp) {
            # Remove the "smtp:" prefix
            return ($secondarySmtp -replace "smtp:", "")
        }
    }
    
    # If no severntrent.co.uk email found, return null
    return $null
}
The Final Challenge: Only Enabled Accounts

The last requirement was to only include enabled accounts in the results. The logs were showing instances where multiple users were found, but some were disabled. I needed to modify the AD query to filter for enabled accounts only:

# Search only for enabled accounts
$adUsers = Get-ADUser -Filter "GivenName -like '$firstName*' -and Surname 
-eq '$lastName' -and Enabled -eq `$true" -Properties EmailAddress, proxyAddresses

And then only include results in the output if they had a valid email:

# Only add to results if we found an email
if ($email) {
    $results += [PSCustomObject]@{
        FullName = $user
        FirstName = $firstName
        LastName = $lastName
        Email = $email
    }
}

The Final Solution

After addressing all these challenges, I ended up with a comprehensive PowerShell script that:

  1. Reads a list of users from a text file
  2. Properly handles hyphenated first names
  3. Queries only enabled AD accounts
  4. Handles multiple matching users appropriately
  5. Extracts only @severntrent.co.uk email addresses
  6. Logs all operations for troubleshooting
  7. Creates a clean CSV output with only valid results

Here's the core part of the final script:

# Process each user in the list
foreach ($user in $users) {
    # Split into first name and last name
    $nameParts = $user -split " ", 2
    
    if ($nameParts.Count -eq 2) {
        $firstName = $nameParts[0]
        $lastName = $nameParts[1]
        
        # Handle hyphenated first names
        if ($firstName -match "-") {
            $firstNameParts = $firstName -split "-"
            $firstName = $firstNameParts[0]
        }
        
        # Search AD for enabled users only
        $adUsers = Get-ADUser -Filter "GivenName -like '$firstName*' -and Surname
         -eq '$lastName' -and Enabled -eq `$true" -Properties EmailAddress, proxyAddresses
        
        # Process results
        if ($adUsers) {
            $email = $null
            
            # Extract email using the custom function
            if ($adUsers -is [array]) {
                $exactMatch = $adUsers | Where-Object { $_.GivenName -eq $firstName 
            -and $_.Surname -eq $lastName } | Select-Object -First 1
                
                if ($exactMatch) {
                    $email = Get-SeverntrentEmail -User $exactMatch
                }
                else {
                    foreach ($adUser in $adUsers) {
                        $potentialEmail = Get-SeverntrentEmail -User $adUser
                        if ($potentialEmail) {
                            $email = $potentialEmail
                            break
                        }
                    }
                }
            }
            else {
                # Single user found
                $email = Get-SeverntrentEmail -User $adUsers
            }
            
            # Only add to results if a valid email was found
            if ($email) {
                $results += [PSCustomObject]@{
                    FullName = $user
                    FirstName = $firstName
                    LastName = $lastName
                    Email = $email
                }
            }
        }
    }
}

Lessons Learned

This project reminded me of several important lessons when working with Active Directory automation:

  1. Names are messy - People's names can be formatted in various ways, and your scripts need to be flexible enough to handle these variations.
  2. Multiple accounts exist - In large organizations, it's common to have multiple accounts for similar names (duplicates, test accounts, etc.). Always have a strategy for handling this.
  3. Check account status - Not all accounts in AD are active. Remember to filter for enabled accounts when appropriate.
  4. Email attributes are complex - AD stores email information in multiple attributes (EmailAddress, proxyAddresses, etc.). Make sure you're looking in the right places.
  5. Logging is essential - Detailed logging saved me countless hours of troubleshooting and helped track down edge cases.

The final script now runs smoothly against our user list, producing a clean CSV file containing only enabled users with their @bythepowerofgreyskull.com email addresses. What started as a seemingly simple task turned into an interesting journey through the nuances of Active Directory automation.

Previous Post Next Post

نموذج الاتصال