Fatih Pense's Blog

My Office 365 PowerShell Adventure to fix Personal SharePoint URL

Friday, January 31st, 2020

We started using Office 365. I created a user for myself. Then I wanted to try different migration options and created another user with the same username.

I didn’t know that I would have a slightly different personal OneDrive URL. That is because the old user URL lives on some time even after you delete the user.

The URL had a small “1” at the end. At first, I thought it was fine. However, as time went on my annoyance grew bigger and bigger.

https://example-my.sharepoint.com/:x:/r/personal/fatih_pense_example_com1/_layouts/15/Doc.aspx?sourcedoc=.....xlsx&action=default&mobileredirect=true

Annoying URL

How can you solve this issue on the server-side?

You can change the URL of SharePoint sites but there is no way to change the personal URL.

I have tried creating a new user and the personal URL of the new user was fine! So this can be the first step! If only I can just move all my data to the new user… At this point, the only important data is mail and OneDrive files. I can use the client to move files for OneDrive. For email data exporting & importing .pst files can be an option. I didn’t want to sync all my emails to the client and sync it back to the server again.

Note that, unfortunately Teams chats won’t migrate. It is a good idea to change your old user account’s name to “DELETED”. Otherwise people will send messages to your old account. :)

After some research, it seems there is a way to do that server-side. Let’s write the steps:

  • Rename your old account to e.g. [email protected] from the admin console. Remove aliases!
  • Create a new user from the admin console.
  • You first disable the old mailbox. (fatih.pense2)
  • And restore the new mailbox from the old mailbox using the MailboxRestoreRequest feature.
  • You can delete the old user account from the admin console.

First, we connect to Exchange Online using a PowerShell window. (docs)

$credential = Get-Credential
 
$exchangeSession = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri "https://outlook.office365.com/powershell-liveid/" -Credential $credential -Authentication "Basic" -AllowRedirection
Import-PSSession $exchangeSession -DisableNameChecking

Now you can use Exchange specific commands! You can use the documentation for Exchange PowerShell for example Get-MailboxRestoreRequest cmdlet.

Disable-Mailbox -Identity "fatih.pense2" -Archive
 
New-MailboxRestoreRequest -SourceMailbox "[email protected]" -TargetMailbox "[email protected]" -AllowLegacyDnMismatch:$True;

MailboxRestoreRequest works like a job. So you have to check it from time to time.

Get-MailboxRestoreRequest | Get-MailboxRestoreRequestStatistics -IncludeReport | select -expand PercentComplete

To get a detailed report:

Get-MailboxRestoreRequest | Get-MailboxRestoreRequestStatistics -IncludeReport | Format-List > C:\temp\AllRestoreReports.txt

You can also filter the jobs by status and then apply commands to them!

Get-MailboxRestoreRequest
 
Get-MailboxRestoreRequest -Status Failed | Remove-MailboxRestoreRequest
 
Get-MailboxRestoreRequest -Status Queued | Get-MailboxRestoreRequestStatistics -IncludeReport | Format-List > C:\temp\AllRestoreReports.txt

I had to run the job multiple times after failures. It only syncs missing emails. It took several hours for 3-4 GB data, but in the end, it worked.

After the whole process completes. You can check all personal URLs with this script from Microsoft Documentation.

$TenantUrl = "https://<EXAMPLE>-admin.sharepoint.com/"
$LogFile = [Environment]::GetFolderPath("Desktop") + "\OneDriveSites.log"
Connect-SPOService -Url $TenantUrl
Get-SPOSite -IncludePersonalSite $true -Limit all -Filter "Url -like '-my.sharepoint.com/personal/'" | select Url | Out-File $LogFile -Force
Write-Host "Done! File saved as $($LogFile)."
#https://docs.microsoft.com/en-us/onedrive/list-onedrive-urls

It is the first time I have used PowerShell scripts this much. I think Microsoft’s design decisions are good. Piping commands with structured data and documenting them to reduce errors is a nice idea.

I also like Unix’s “everything is string, accept it and move on!” approach. The only problem is that I have always tried to avoid bash because of seemingly irregular syntax. There are a lot of alternatives for the Unix shell, but bash is the universal one we should compare with PowerShell. Interestingly, “BNF grammar for bash” seems small. But maybe I should learn German instead…