Fix AD users UPN for Office 365 – Run Daily

Update -9/30/2016 — Included Users that gets migrated to O365, these can be detected as RemoteUsermailbox.

This script is very useful & is extension to my other script Fix Office 365 UPN

https://msexchange.me/2016/07/21/fix-office-365-upn/

What it does extra is :

  • It can be scheduled to run daily & process the incremental changes
  • If there is change in SMTP address than also it can detect & update UPN
  • It also has a logic to take care of Users without mailboxes to change the default suffix for them to internet routable suffix.
  • It can slo be used to process all the users (just change the variable $fullrun = “Sunday” to the current day & it will execute to change all the UPNs)

This script you can use when you are done with all the UPN fixing & now you want that further fix is done automatically.

This can be utilized in environments where changing user provisioning process is becoming a challenge & you need a temporary or permanent workaround to mitigate the limitation of provisioning tool.

This is the logic of the script:

Logic for mailboxes:

If (weekday) _ increment

  • Fetch mailboxes that have integer values in extension attribute4 (to check if mailbox is employee mailbox, change it according to your environment)
  • Further filter it with newly created mailboxes
  • If fetching has issues or error out, script will exit & will not process further (example not able to access dc)
  • Further check if UPN matches windows email
  • If number of changes is more than 100 than also script will exit.
  • Update the UPN with windowsemailaddress
  • Log & report
  • Recycle Log & report after 60 days

If(weekend)_ full

  • Fetch mailboxes that have integer values in extension attribute4  (to check if mailbox is employee mailbox, change it according to your enviornemnt 
  • If fetching has issues or error out, script will exit & will not process further(example not able to access dc)
  • Further check if UPN matches windows email
  • If number of changes is more than 100 than also script will exit.
  • Update the UPN with windowsemailaddress
  • Log & report
  • Recycle Log & report after 60 days

Logic for Users without mailboxes:

 If (weekday) _ increment

  •  Fetch Users without mailboxes that have integer values in extension attribute4  &  UPN matches internal domain
  •  Further filter it with newly created Users
  •  If fetching has issues or error out script will exit & will not process further(example not able to access dc)
  • If number of changes is more than 100than also script will exit.
  • Update the UPN — update @internetroutabledomain
  • Log & report
  • Recycle Log & report after 60 days 

If(weekend)_ full

  • Fetch Users without mailboxes that have integer values in extension attribute1 or employeeid &  UPN matches internal domain
  • If fetching has issues or error out script will exit & will not process further(example not able to access dc)
  • If number of changes is more than 100 than also script will exit.
  • Update the UPN  update @internetroutabledomain
  • Log & report
  • Recycle Log & report after 60 days

Note: Exchange Shell & AD Shell is required for executing this script.

Extract the zip file from below link & You can scheduled this script solution or run it using the batch file to see the results on the screen

https://gallery.technet.microsoft.com/scriptcenter/Fix-Office-365-UPN-Run-210f90ee

######################################################################### 
#            Author: Vikas Sukhija 
#            Reviewer: 
#            date: 7/6/2016 
#            Modified:7/11/2016                         
#            Description: Fix o365 UPN 
#            Update: Added reporting 
#            Update: modified to run daily on new users/full on weekends 
#            Update: error checking 
#            Update: included users without mailboxes 
#            Update: Added count logic (exit if changes are more than specified number) 
#            Update: Added readonly & implementation mode 
#            Update: Added the logic to cater user with email address 
#            Update: Add the logic to cater migrated O365 users 
######################################################################### 
 
$mode = "Write" #################Value should be write for implementation mode 
 
if($mode -eq "Write") {Write-host "Script will run inimplmentation mode & changes will be processed" -foregroundcolor magenta} 
else{Write-host "Script will run as readonly & no changes will be processed" -foregroundcolor green} 
 
$date1 = get-date -format d 
$date1 = $date1.ToString().Replace("/","-"$time = get-date -format t 
 
$time = $time.ToString().Replace(":""-"$time = $time.ToString().Replace(" """) 
 
$logs = ".\Logs" + "\" + "Processed_PS_" + $date1 + "_" + $time + "_.log" 
$report = ".\report" + "\" + "Report_mailboxes" + $date1 + "_" + $time + "_.csv" 
 
$report1 = ".\report" + "\" + "Report_Users" + $date1 + "_" + $time + "_.csv" 
 
$limit = (Get-Date).AddDays(-60) #for report recycling 
$path1 = ".\report\" 
$path2 = ".\Logs\" 
 
$exdomain2 = "@internaldomain.local" 
 
$repdmain = "@internetdomain.com" 
 
$collection = @() 
$collection1 = @() 
 
$coll1 =@() 
$coll2=@() 
 
$fullrun = "Sunday" 
 
$regex = '^\d+$' 
 
$countofchanges = "100" 
 
 
$email1 = "AADSyncAlert@lab.com" 
$from = "DoNotReply@lab.com" 
$smtpserver = "smtp server" 
 
Start-Transcript -Path $logs 
 
get-date 
 
If ((Get-PSSnapin | where {$_.Name -match "Microsoft.Exchange.Management.PowerShell.E2010"}) -eq $null) 
{ 
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.E2010 
} 
 
import-module activedirectory 
 
if ($error -ne $null) 
      { 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Script Error on module import exit" 
$msg.Body = $error 
$smtp.Send($msgexit 
}  
 
#########################update All users UPN##################### 
$day = get-date 
 
if($day.dayofweek -like $fullrun){ 
 
Write-host "Running Full Run fix UPN mailboxes" -foregroundcolor green 
 
$users = get-mailbox -resultsize unlimited | where{($_.CustomAttribute1 -match $regex-and ($_.ExchangeUserAccountControl -eq "None")} 
 
#############Exit if error in fetching users####### 
 
if ($error -ne $null) 
      { 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Script Error Full Run Mailbox exit" 
$msg.Body = $error 
$smtp.Send($msgexit 
}  
 
################################################## 
 
$users | foreach-object{ 
 
$user = $_.samaccountname 
 
$mbx=Get-User $user | Where { -Not [string]::IsNullOrEmpty($_.WindowsEmailAddress) }  
 
 
if($mbx){ 
 
    if($mbx.UserPrincipalName -eq $mbx.WindowsEmailAddress) {Write-host "$user is already setup as "$mbx.UserPrincipalName"" -foregroundcolor blue  
 
    } else{$coll1 +=$mbx} 
} 
 
else{ 
 
$mbx=Get-User $user 
write-host "$user ..doesn't have ..WindowsEmailAddress" -foregroundcolor magenta 
 
} 
 
} 
 
if($coll1.count -lt $countofchanges){ 
 
$count1=$coll1.count 
$count1 
 
$coll1 | foreach-object{ 
 
$sam$_.samaccountname 
 
$mbcoll = "" | select Name,ExistingUPN,WindowsEmailAddress,ModifiedUPN 
 
if($mode -eq "Write"){Set-User -identity $_ -UserPrincipalName $_.WindowsEmailAddress.ToString()} 
 
if($error){Write-host "Error occured Updating UPN for $sam as "$_.WindowsEmailAddress"" -foregroundcolor yellow 
        $mbcoll.Name = $_.Name 
    $mbcoll.ExistingUPN = $_.UserPrincipalName 
    $mbcoll.WindowsEmailAddress = $_.WindowsEmailAddress 
    $mbcoll.ModifiedUPN = "Error" 
        $error.clear()} 
        Else{ 
    Write-host "Updating UPN for $sam as "$_.WindowsEmailAddress"" -foregroundcolor magenta 
    $mbcoll.Name = $_.Name 
    $mbcoll.ExistingUPN = $_.UserPrincipalName 
    $mbcoll.WindowsEmailAddress = $_.WindowsEmailAddress 
    $mbcoll.ModifiedUPN = $_.WindowsEmailAddress } 
$collection +=$mbcoll 
} 
} 
else{ 
 
$count1=$coll1.count 
$count1 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Full Run Script Exit as changes to process are $count1 more than $countofchanges" 
$msg.Body = "UPN Fix Full Run Script Exit as changes to process are $count1 more than $countofchanges" 
$smtp.Send($msgexit 
} 
 
if($collection.count -gt "0"){ 
$collection  | export-csv $report -notypeinfo 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
$attach = new-object Net.Mail.Attachment($report)  
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Full Run Mailbox Report" 
$msg.Body = "UPN Fix Full Run Mailbox Report" 
$msg.Attachments.Add($attach$smtp.Send($msg) 
 
} 
} 
 
################################Update only increment users mailboxes UPN###################### 
else{ 
 
Write-host "Running Incremental Run fix UPN mailboxes" -foregroundcolor green 
 
$users = get-mailbox -resultsize unlimited | where {($_.CustomAttribute1 -match $regex-and ($_.ExchangeUserAccountControl -eq "None"-and ($_.WhenMailboxCreated -gt (get-date).adddays(-1))} 
 
#############Exit if not able to fetch users################ 
if ($error -ne $null) 
      { 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Script Error incremental Run Mailbox exit" 
$msg.Body = $error 
$smtp.Send($msgexit 
}  
 
######################################################## 
 
$users | foreach-object{ 
 
$user = $_.samaccountname 
 
$mbx=Get-User $user | Where { -Not [string]::IsNullOrEmpty($_.WindowsEmailAddress) }  
 
 
if($mbx){ 
 
    if($mbx.UserPrincipalName -eq $mbx.WindowsEmailAddress) {Write-host "$user is already setup as "$mbx.UserPrincipalName"" -foregroundcolor blue  
    } else{$coll1 +=$mbx} 
} 
 
else{ 
 
$mbx=Get-User $user 
write-host "$user ..doesn't have ..WindowsEmailAddress" -foregroundcolor magenta} 
 
} 
 
if($coll1.count -lt $countofchanges){ 
 
$count1=$coll1.count 
$count1 
 
$coll1 | foreach-object{ 
 
$sam$_.samaccountname 
 
$mbcoll = "" | select Name,ExistingUPN,WindowsEmailAddress,ModifiedUPN 
 
if($mode -eq "Write"){Set-User -identity $_ -UserPrincipalName $_.WindowsEmailAddress.ToString()} 
 
if($error){Write-host "Error occured Updating UPN for $sam as "$_.WindowsEmailAddress"" -foregroundcolor yellow 
        $mbcoll.Name = $_.Name 
    $mbcoll.ExistingUPN = $_.UserPrincipalName 
    $mbcoll.WindowsEmailAddress = $_.WindowsEmailAddress 
    $mbcoll.ModifiedUPN = "Error" 
        $error.clear()} 
        Else{ 
    Write-host "Updating UPN for $sam as "$_.WindowsEmailAddress"" -foregroundcolor magenta 
    $mbcoll.Name = $_.Name 
    $mbcoll.ExistingUPN = $_.UserPrincipalName 
    $mbcoll.WindowsEmailAddress = $_.WindowsEmailAddress 
    $mbcoll.ModifiedUPN = $_.WindowsEmailAddress } 
$collection +=$mbcoll 
} 
} 
else$count1=$coll1.count 
$count1 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Incremental Run Script Exit as changes to process are $count1 more than $countofchanges" 
$msg.Body = "UPN Fix Incremental Run Script Exit as changes to process are $count1 more than $countofchanges" 
$smtp.Send($msgexit 
} 
 
if($collection.count -gt "0"){ 
$collection  | export-csv $report -notypeinfo 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
$attach = new-object Net.Mail.Attachment($report)  
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Incremental Run Mailbox Report" 
$msg.Body = "UPN Fix Incremental Run Mailbox Report" 
$msg.Attachments.Add($attach$smtp.Send($msg) 
 
} 
} 
 
#######################Update UPN Of Users without mailboxes########################## 
 
$day = get-date 
 
if($day.dayofweek -like $fullrun){ 
 
Write-host "Running Full Run fix UPN Users" -foregroundcolor green 
 
$users1 = get-user -resultsize unlimited -WarningAction SilentlyContinue | where{(($_.UserPrincipalName -like "*$exdomain2"-and ($_.RecipientTypeDetails -eq "User"-and ($_.UserAccountControl -notlike "*AccountDisabled*"-and ($_.UserAccountControl -notlike "*Trust*")) -or ($_.RecipientTypeDetails -eq "RemoteUserMailbox")} 
 
##################Exit if not able to fetch users################### 
 
if ($error -ne $null) 
      { 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Script Error Full Run users exit" 
$msg.Body = $error 
$smtp.Send($msgexit 
}  
#################################################################### 
 
$users1 | foreach-object{ 
 
$usrex = $_ 
$user1 = $_.samaccountname 
 
$usr = get-aduser $user1 -Properties employeeid,extensionattribute4 
 
$emp1=$usr.employeeid 
$emp2=$usr.extensionattribute4 
 
if(($emp1 -match $regex-or ($emp2 -match $regex)){ $coll2 +=$usrex } 
else{ Write-host "$user1 ......is not employee" -foregroundcolor magenta} 
 
} 
 
if($coll2.count -lt $countofchanges){ 
 
$count2=$coll2.count 
$count2 
 
$coll2 | foreach-object{ 
 
$sam1 = $_.samaccountname 
$upn = $_.UserPrincipalName 
$rcptdet = $_.RecipientTypeDetails 
$winem = $_.WindowsEmailAddress 
 
$mbcoll1 = "" | select Name,ExistingUPN,ModifiedUPN 
 
if($rcptdet -eq "RemoteUserMailbox"){ 
 
    if($upn -ne $winem){$upn1 = $winem.ToString() 
        if($mode -eq "Write"){Set-User -identity $sam1 -UserPrincipalName $upn1} 
         
        if($error){Write-host "$sam1 UPN will not be fixed to $upn1" -foregroundcolor RED 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "error"  
        $error.clear()} 
        else{ 
        Write-host "$sam1 UPN will be set to $upn1" -foregroundcolor green 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = $upn1} 
        } 
         else{ 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "Not modified"} 
 
    } 
else{  
 
    $upn1 = [string]$upn -replace "$exdomain2","$repdmain" 
    if($mode -eq "Write"){Set-User -identity $sam1 -UserPrincipalName $upn1} 
        if($error){Write-host "$sam1 UPN will not be fixed to $upn1" -foregroundcolor RED 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "error"  
        $error.clear()} 
        else{ 
        Write-host "$sam1 UPN will be set to $upn1" -foregroundcolor green 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = $upn1} 
    } 
 
$collection1+=$mbcoll1 
} 
 
} 
 
else$count2=$coll2.count 
$count2 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Full USer Run Script Exit as changes to process are $count2 more than $countofchanges" 
$msg.Body = "UPN Full User Run Script Exit as changes to process are $count2 more than $countofchanges" 
$smtp.Send($msgexit 
} 
 
if($collection1){$collection1 | export-csv $report1 -notypeinfo 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
$attach = new-object Net.Mail.Attachment($report1)  
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Full Run User Report" 
$msg.Body = "UPN Fix Full Run User Report" 
$msg.Attachments.Add($attach$smtp.Send($msg)} 
 
} 
##############################Only incremental Users without mailboxes################### 
 
else { 
 
Write-host "Running Incremental Run fix UPN Users" -foregroundcolor green 
 
$users1 = get-user -resultsize unlimited -WarningAction SilentlyContinue |  where {(($_.UserPrincipalName -like "*$exdomain2")-and ($_.RecipientTypeDetails -eq "User"-and ($_.UserAccountControl -notlike "*AccountDisabled*"-and ($_.UserAccountControl -notlike "*Trust*"-and ($_.WhenCreated -gt (get-date).adddays(-1))) -or (($_.RecipientTypeDetails -eq "RemoteUserMailbox"-and ($_.WhenCreated -gt (get-date).adddays(-1)))} 
 
if ($error -ne $null) 
      { 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Script Error incremental Run users exit" 
$msg.Body = $error 
$smtp.Send($msgexit 
}  
 
############################################## 
$users1 | foreach-object{ 
 
$usrex = $_ 
$user1 = $_.samaccountname 
 
$usr = get-aduser $user1 -Properties employeeid,extensionattribute4 
 
$emp1=$usr.employeeid 
$emp2=$usr.extensionattribute4 
 
 
if(($emp1 -match $regex-or ($emp2 -match $regex)){ $coll2 +=$usrex } 
else{ Write-host "$user1 ......is not employee" -foregroundcolor magenta} 
 
} 
if($coll2.count -lt $countofchanges){ 
 
$count2=$coll2.count 
$count2 
 
$coll2 | foreach-object{ 
 
$sam1 = $_.samaccountname 
$upn = $_.UserPrincipalName 
$rcptdet = $_.RecipientTypeDetails 
$winem = $_.WindowsEmailAddress 
 
$mbcoll1 = "" | select Name,ExistingUPN,ModifiedUPN 
 
if($rcptdet -eq "RemoteUserMailbox"){ 
 
    if($upn -ne $winem){$upn1 = $winem.ToString() 
        if($mode -eq "Write"){Set-User -identity $sam1 -UserPrincipalName $upn1} 
         
        if($error){Write-host "$sam1 UPN will not be fixed to $upn1" -foregroundcolor RED 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "error"  
        $error.clear()} 
        else{ 
        Write-host "$sam1 UPN will be set to $upn1" -foregroundcolor green 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = $upn1} 
        } 
         else{ 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "Not modified"} 
 
    } 
else{ 
 
    $upn1 = [string]$upn -replace "$exdomain2","$repdmain" 
    if($mode -eq "Write"){Set-User -identity $sam1 -UserPrincipalName $upn1} 
        if($error){Write-host "$sam1 UPN will not be fixed to $upn1" -foregroundcolor RED 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = "error"  
        $error.clear()} 
        else{ 
        Write-host "$sam1 UPN will be set to $upn1" -foregroundcolor green 
        $mbcoll1.Name = $sam1 
        $mbcoll1.ExistingUPN = $upn 
        $mbcoll1.ModifiedUPN = $upn1} 
    } 
 
$collection1+=$mbcoll1 
} 
} 
else$count2=$coll2.count 
$count2 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from  
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Incremental USer Run Script Exit as changes to process are $count2 more than $countofchanges" 
$msg.Body = "UPN Incremental User Run Script Exit as changes to process are $count2 more than $countofchanges" 
$smtp.Send($msgexit 
} 
 
if($collection1){$collection1 | export-csv $report1 -notypeinfo 
 
$msg = new-object Net.Mail.MailMessage 
$smtp = new-object Net.Mail.SmtpClient($smtpServer$msg.From = $from 
$attach = new-object Net.Mail.Attachment($report1)  
 
#mail recipient 
$msg.To.Add($email1$msg.Subject = "UPN Fix Incremental Run User Report" 
$msg.Body = "UPN Fix Incremental Run User Report" 
$msg.Attachments.Add($attach$smtp.Send($msg)} 
 
} 
 
########################Recycle reports & logs############## 
Get-ChildItem -Path $path1  | Where-Object {   
$_.CreationTime -lt $limit } | Remove-Item -recurse -Force  
 
Get-ChildItem -Path $path2  | Where-Object {   
$_.CreationTime -lt $limit } | Remove-Item -recurse -Force  
 
get-date 
 
stop-transcript 
##########################################################################

 

Regards

Sukhija Vikas

http://msexchange.me

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s