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
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($msg) exit } #########################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($msg) exit } ################################################## $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($msg) exit } 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($msg) exit } ######################################################## $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($msg) exit } 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($msg) exit } #################################################################### $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($msg) exit } 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($msg) exit } ############################################## $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($msg) exit } 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 ##########################################################################
Tech Wizard