eMail And UPN to lowercase

Hi Team

Can anyone spot anything wrong in this script. I am trying to set all email addresses and UPN to lowercase. 

There are no errors and it would look as though the code is fine. However on checking an AD account the case has not changed. 

Connect-QADService -Service "AR Service-HERE" -Proxy

# Specify the OU where the user accounts are located
$ou = "OU-HERE"

# Get all user accounts in the OU
$users = Get-QADUser -SearchRoot $ou

# Loop through each user account and set the email address and UPN to lowercase
foreach ($user in $users) {
    $email = $user.Email
    $upn = $user.UserPrincipalName
    if ($email) {
        $user.Email = $email.ToLower()
        Set-QADUser -Identity $user -ObjectAttributes @{email=$user.Email}
    }
    if ($upn) {
        $user.UserPrincipalName = $upn.ToLower()
        Set-QADUser -Identity $user -ObjectAttributes @{userprincipalname=$user.UserPrincipalName}
    }
}

Parents
  • Try this change:

    $email = [string]$user.email

    $upn = [string]$user.userprincipalname

  • Thanks Johnny. Yeah same result. No errors logged but email and UPN stay in the same case and not changed to lower. 

  • What are you seeing in the AR change history of the objects you believe you are affecting?

  • Just to update. 

    I tried so many different ways to get this to work, even using native AD Powershell and was same result. 

    This however does work. and eMail , UPN and SamAccount all lowercase. 

    $DateYear = $((Get-Date).ToString('yyyy'))
    $DateMonth = $((Get-Date).ToString('MMM'))
    $DateDay = $((Get-Date).ToString('dd'))
    #Time
    $Time = Get-Date -Format "HH-mm"
    
    #Create Folder structure based on Date
    New-Item -ItemType Directory -Path "PATH-HERE\$DateYear\$DateMonth\$DateDay" -Force
    New-Item -ItemType Directory -Path "PATH-HERE\$DateYear\$DateMonth\$DateDay\Logs" -Force
    
    $logfile = "PATH-HERE\$DateYear\$DateMonth\$DateDay\Logs\Log-$time.txt"
    
    # Set the distinguished name of the OU where you want to update the user objects
    $OU = "OU-HERE"
    
    # Get all user objects in the specified OU
    $users = Get-QADUser -SearchRoot $OU -SizeLimit 0
    
    # Function to check for uppercase characters
    
    function CheckUpper {
       Param ($text)
       $c = 0
       $position = foreach ($character in $text.ToCharArray())
       {
         $c++
         if ([Char]::IsUpper($character))
         {
           return $c;
         }
       }
       return 0;
    }
    
    # Loop through each user and set the email , UPN and SamAccount to lowercase
    
    foreach($User in $Users)
     {
        If ($User.Email -ne $null) {
            $SAM = $User.SamAccountName
            $Eail = $User.Email
            $UPN = $User.userPrincipalName
    		if (CheckUpper($Email) -gt 0) {
               $LowerCaseEmail = $User.Email.Tolower()
    		   Write-host $SAM "contains uppercase eMail Address. converting $Email -> $LowerCaseEmail" -foreground red
               Set-QADUser -identity "$SAM" -Email $LowerCaseEmail -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    		}
            if (CheckUpper($UPN) -gt 0) {
               $LowercaseUPN = $User.userPrincipalName.Tolower()
    		   Write-host $SAM "contains uppercase UPN. converting $UPN -> $LowercaseUPN" -foreground red
               Set-QADUser -identity "$SAM" -userPrincipalName $LowercaseUPN -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    
    		}
    
            if (CheckUpper($SAM) -gt 0) {
               $LowercaseSAM = $User.SamAccountName.Tolower()
    		   Write-host $SAM "contains uppercase SamAccount. converting $SAM -> $LowercaseSA" -foreground red
               Set-QADUser -identity "$SAM" -SamAccountName $LowercaseSA -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    
    		}
    
    		else {
    		   #Local Powershell Console output. Testing
               #=================================================================================
               #Write-host $SAM "already lowercase eMail - $Email" -foreground green
               #Write-host $SAM "already lowercase UPN - $UPN" -foreground green
               #Write-host $SAM "already lowercase SamAccountName - $SAM" -foreground green
               #=================================================================================
               Write-output "Account" $SAM "already lowercase eMail - $Email" | Out-File $logfile -Append
               Write-output "Account" $SAM "already lowercase UPN - $UPN" | Out-File $logfile -Append
               Write-output "Account" $SAM "already lowercase SamAccountName - $SAM" | Out-File $logfile -Append
    		}
        }
    }

Reply
  • Just to update. 

    I tried so many different ways to get this to work, even using native AD Powershell and was same result. 

    This however does work. and eMail , UPN and SamAccount all lowercase. 

    $DateYear = $((Get-Date).ToString('yyyy'))
    $DateMonth = $((Get-Date).ToString('MMM'))
    $DateDay = $((Get-Date).ToString('dd'))
    #Time
    $Time = Get-Date -Format "HH-mm"
    
    #Create Folder structure based on Date
    New-Item -ItemType Directory -Path "PATH-HERE\$DateYear\$DateMonth\$DateDay" -Force
    New-Item -ItemType Directory -Path "PATH-HERE\$DateYear\$DateMonth\$DateDay\Logs" -Force
    
    $logfile = "PATH-HERE\$DateYear\$DateMonth\$DateDay\Logs\Log-$time.txt"
    
    # Set the distinguished name of the OU where you want to update the user objects
    $OU = "OU-HERE"
    
    # Get all user objects in the specified OU
    $users = Get-QADUser -SearchRoot $OU -SizeLimit 0
    
    # Function to check for uppercase characters
    
    function CheckUpper {
       Param ($text)
       $c = 0
       $position = foreach ($character in $text.ToCharArray())
       {
         $c++
         if ([Char]::IsUpper($character))
         {
           return $c;
         }
       }
       return 0;
    }
    
    # Loop through each user and set the email , UPN and SamAccount to lowercase
    
    foreach($User in $Users)
     {
        If ($User.Email -ne $null) {
            $SAM = $User.SamAccountName
            $Eail = $User.Email
            $UPN = $User.userPrincipalName
    		if (CheckUpper($Email) -gt 0) {
               $LowerCaseEmail = $User.Email.Tolower()
    		   Write-host $SAM "contains uppercase eMail Address. converting $Email -> $LowerCaseEmail" -foreground red
               Set-QADUser -identity "$SAM" -Email $LowerCaseEmail -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    		}
            if (CheckUpper($UPN) -gt 0) {
               $LowercaseUPN = $User.userPrincipalName.Tolower()
    		   Write-host $SAM "contains uppercase UPN. converting $UPN -> $LowercaseUPN" -foreground red
               Set-QADUser -identity "$SAM" -userPrincipalName $LowercaseUPN -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    
    		}
    
            if (CheckUpper($SAM) -gt 0) {
               $LowercaseSAM = $User.SamAccountName.Tolower()
    		   Write-host $SAM "contains uppercase SamAccount. converting $SAM -> $LowercaseSA" -foreground red
               Set-QADUser -identity "$SAM" -SamAccountName $LowercaseSA -Control @{'OperationReason'="Set via AR script called something something"} | Out-File $logfile -Append
    
    		}
    
    		else {
    		   #Local Powershell Console output. Testing
               #=================================================================================
               #Write-host $SAM "already lowercase eMail - $Email" -foreground green
               #Write-host $SAM "already lowercase UPN - $UPN" -foreground green
               #Write-host $SAM "already lowercase SamAccountName - $SAM" -foreground green
               #=================================================================================
               Write-output "Account" $SAM "already lowercase eMail - $Email" | Out-File $logfile -Append
               Write-output "Account" $SAM "already lowercase UPN - $UPN" | Out-File $logfile -Append
               Write-output "Account" $SAM "already lowercase SamAccountName - $SAM" | Out-File $logfile -Append
    		}
        }
    }

Children
  • Although say that. It runs fine outside of ARS. But when its executed via AR i get this error 

    At line: 42 char:39. You cannot call a method on a null-valued expression.

    Which it something in this function it does not like 

    function CheckUpper {
       Param ($text)
       $c = 0
       $position = foreach ($character in $text.ToCharArray())
       {
         $c++
         if ([Char]::IsUpper($character))
         {
           return $c;
         }
       }
       return 0;
    }

  • Outside of Active Roles you could run the following

    $OU = "<Some OU>"
    
    $Users = Get-QADUSer -SearchRoot $OU
    
    ForEach($User in $USers)
    {
        $Attributes = @{}
        Write-Host "User: $($User.SamAccountName)"
    
        if(-not [string]::IsNullOrEmpty($User.mail))
        {
            If(-not ($USer.mail -clike ($USer.mail).ToLower()))
            {
                Write-Host "`tCorrecting Mail"
                $Attributes.add("Mail",($User.mail).ToLower())
            }
        }
        
        if(-not [string]::IsNullOrEmpty($USer.UserPrincipalName))
        {
            If(-not ($USer.UserPrincipalName -clike ($USer.UserPrincipalName).ToLower()))
            {
                Write-Host "`tCorrecting UPN"
                $Attributes.add("UserPrincipalName",($User.UserPrincipalName).ToLower())
            }
        }
    
        If($Attributes.Count -gt 0)
        {
            Write-Host "`tProcessing required corrections"
            Set-QADUSer -Identity $USer.dn -ObjectAttributes $Attributes -proxy | out-null
        }
        Else
        {
            Write-Host "`tNo corrections required"
        }
    }

    Or from with a policy script, executed pre create or modify

    function onPreCreate($Request)
    {
        if($Request.Class -ne "User") {return}
    
        ChangeCase $Request
    }
    
    function onPreModify($Request)
    {
        if($Request.Class -ne "User") {return}
    
        ChangeCase $Request
    }
    
    
    function IsAttributeModified ([string]$AttributeName, $Request)
    {
        $objEntry = $Request.GetPropertyItem($AttributeName, $Constants.ADSTYPE_CASE_IGNORE_STRING)
        if($objEntry -eq $null) { return $false }
        if($objEntry.ControlCode -eq 0) { return $false }
        return $true
    }
    
    function ChangeCase($request)
    {
        $Message = ""
        
        $Message = "User: $($Request.get("SamAccountName"))"
    
        if(IsAttributeModified  -AttributeName "Mail" -Request $Request)
        {
            $Message = "$($Message)`n`tMail attribute in request"
            if(-not ($Request.Get("mail") -clike ($Request.Get("mail")).ToLower()))
            {
                $Message = "$($Message)`n`tCorrecting Mail"
                $Message = "$($Message)`n`t`tFrom: $($Request.Get("mail"))"
                $Message = "$($Message)`n`t`tTo: $($Request.Get("mail").ToLower())"
                $Request.put("Mail",($Request.Get("mail")).ToLower())
            }
            else
            {
                $Message = "$($Message)`n`tNo Mail correction required" 
            }
        }
        
        if(IsAttributeModified  -AttributeName "UserPrincipalName" -Request $Request)
        {
            if(-not ($Request.Get("UserPrincipalName") -clike ($Request.Get("UserPrincipalName")).ToLower()))
            {
                $Message = "$($Message)`n`tCorrecting UPN"
                $Message = "$($Message)`n`t`tFrom: $($Request.Get("UserPrincipalName"))"
                $Message = "$($Message)`n`t`tTo: $($Request.Get("UserPrincipalName").ToLower())"
                
                $Request.Put("UserPrincipalName",($Request.Get("UserPrincipalName")).ToLower())
            }
            else
            {
                $Message = "$($Message)`n`tNo UPN correction required"
            }
        }
        
        $EventLog.ReportEvent($Constants.EDS_EVENTLOG_WARNING_TYPE,$Message) 
    }

    As   suggests, you could do this one a user by user basis, on modification to the mail or userprinciaplNAme attribute via workflow, where you Modify the requested changes, so that it sets the mail or userPrincipalName to be the value submitted converted to lowercase, IE:

    The advantage to the later, is there is no coding, and easier to control when it is fired