Bulk add emails to Active Directory accounts

· 3 min read
Bulk add emails to Active Directory accounts

Recently I had to make a lot of changes to Active Directory accounts migrated from several other forests and domains. Emails attribute needed to be created / changed to match the new domain requirement.

As the pattern of the email was know as first letter of the first name and last name with the domain, and the account where correctly created with first names and last names

Which need to result in : j.smith@email.com

The target email email domain needs to be specified here

$emailDomain = "example.com"  # Update with your email domain

A requirement was to exclude all the test accounts, services account, admin accounts to avoid filling these accounts attributes with invalid email addresses. I thought using some keywords would be the best and that could be adapt along the tests, this can be change with the following lines :

# Define a list of words to exclude from first names or last names
$excludeWords = @("adm*", "test*")  # Add any additional words to exclude

Another requirement was to target a specific OU in the Active Directory and last but not least, to have a report of the actions that would be done by the script.

# Specify the target OU and email domain
$ouPath = "OU=YourOU,DC=example,DC=com"  # Update with your OU path

This will generate a log in the specified folder here :

# Define the path for the HTML report file
$reportFilePath = "C:\Path\To\Report.html"

Here is the full script

  • $emaildomain needs to be specified
  • $oupath needs to match your requirement
  • $reportFilePath needs to refer to an existing folder
# Import the Active Directory module if it's not already loaded
if (-not (Get-Module -Name ActiveDirectory -ErrorAction SilentlyContinue)) {
    Import-Module ActiveDirectory
}

# Specify the target OU and email domain
$ouPath = "OU=YourOU,DC=example,DC=com"  # Update with your OU path
$emailDomain = "example.com"  # Update with your email domain

# Define the path for the HTML report file
$reportFilePath = "C:\Path\To\Report.html"

# Define a list of words to exclude from first names or last names
$excludeWords = @("adm*", "test*")  # Add any additional words to exclude

# Initialize arrays to store changes, ignored accounts, and disabled accounts
$changes = @()
$ignoredAccounts = @()
$disabledAccounts = @()

# Retrieve all user accounts in the specified OU with the given email domain
$users = Get-ADUser -Filter * -SearchBase $ouPath -Properties EmailAddress, Enabled

# Loop through each user and set/update the email attribute with the formatted name
foreach ($user in $users) {
    $firstName = $user.GivenName
    $lastName = $user.Surname

    # Check if the first name or last name contains any excluded words or patterns
    $exclude = $excludeWords | Where-Object { $firstName -like $_ -or $lastName -like $_ }

    if ($user.Enabled -eq $true) {
        if (-not $exclude) {
            # Generate the desired format for the email address (first letter of the first name and a dot)
            $formattedEmail = ($firstName.Substring(0, 1) + "." + $lastName).ToLower() + "@" + $emailDomain

            # Set/update the email attribute for the user
            Set-ADUser -Identity $user -EmailAddress $formattedEmail

            # Record the change in the report
            $change = [PSCustomObject]@{
                UserName = $user.SamAccountName
                OriginalEmail = $user.EmailAddress
                NewEmail = $formattedEmail
                Reason = "Email updated"
            }
            $changes += $change

            Write-Host "Updated email address for $($user.SamAccountName) to $formattedEmail"
        } else {
            # Record the ignored account in the list of ignored accounts
            $ignoredAccount = [PSCustomObject]@{
                UserName = $user.SamAccountName
                Reason = "Excluded due to word or pattern in first name or last name."
            }
            $ignoredAccounts += $ignoredAccount

            Write-Host "Excluded $($user.SamAccountName) due to word or pattern in first name or last name."
        }
    } else {
        # Record the disabled account in the list of disabled accounts
        $disabledAccount = [PSCustomObject]@{
            UserName = $user.SamAccountName
            Reason = "Account is disabled."
        }
        $disabledAccounts += $disabledAccount

        Write-Host "Account $($user.SamAccountName) is disabled."
    }
}

# Create an HTML report for changes
$changesReport = $changes | ConvertTo-Html -Property UserName, OriginalEmail, NewEmail, Reason | Out-String

# Create an HTML report for ignored accounts
$ignoredReport = $ignoredAccounts | ConvertTo-Html -Property UserName, Reason | Out-String

# Create an HTML report for disabled accounts
$disabledReport = $disabledAccounts | ConvertTo-Html -Property UserName, Reason | Out-String

# Combine all reports
$combinedReport = $changesReport + $ignoredReport + $disabledReport

# Save the combined report to the specified file path
$combinedReport | Out-File -FilePath $reportFilePath

Write-Host "Report saved to $reportFilePath"

and the result log file generated :