O365 / Exchange one-liners

This post is way overdue, but better late than never right?

I spent a few good months late last year working on a O365 migration project and I thought I would share some of the powershell commands that I used for various tasks throughout the project. I have gathered some of these from various blogs (many from exchangeserverpro.com) and the Microsoft KB articles. I thought it might be useful to have them in once place and could prove useful to you folk in the wild.

First thing’s first – Connecting. Here is a write up of the process and the per-requisite software you need, but below is what I’ve used to connect my ps session.

Set-ExecutionPolicy Unrestricted -Force   
$O365CREDS = Get-Credential
$ONPREMCREDS = Get-Credential
$SESSION = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri https://ps.outlook.com/powershell -Credential $O365CREDS -Authentication Basic -AllowRedirection
Import-PSSession $SESSION
Connect-MsolService -Credential $O365CREDS

#Test connectivity
Get-Mailbox yourmailboxname
Disable Clutter

This was a real annoyance for our users

Get-Mailbox User@vkarps.com | Set-Clutter -Enable $False
Set maximum send / receive size limit for all users with @domainname address

Note: This command might need to change based on the size of your tenant (There are a few documented methods out there). I found that if you have a large number of users, you will constantly get prompted to authenticate or the command will fail once it reaches the threshold.

Get-Mailbox *@vkarps.com | Set-Mailbox -MaxReceiveSize 150MB -MaxSendSize 150MB

Another thing to keep in mind with this one is that you’re limited to your Send / Receive connectors, so keep an eye out on those limits.

Setup Out of Office
Set-MailboxAutoReplyConfiguration -Identity user@vkarps.com -AutoReplyStateEnabled -ExternalMessage "I'm on vacation" -InternalMessage "I'm on vacation"
Migration batch operations
Get current migraiton batches in your tenant
Get the migration progress of each mailbox in a migraiton batch
Get-MigrationUser -BatchId "vKARPS-Batch3-Finance" | Get-MigrationUserStatistics | FT -AutoSize
Create migration batch from csv, but dont start syncing.

Here I have allowed for a bad item limit of 100 and set allowincremental syncs to true. This is so that when the batch it started, it will not automatically cutover.

 New-MigrationBatch -Name "vKARPS-Batch4-Legal" -SourceEndpoint Australia -TargetDeliveryDomain vkarps.mail.onmicrosoft.com -CSVData ([System.IO.File]::ReadAllBytes("c:ScriptsLegalUsers.csv")) -AllowIncrementalSyncs $True -BadItemLimit 100 -NotificationEmails admin@vkarps.com
Start a migration batch
Start-MigrationBatch -Identity "vKARPS-Batch4-Legal"
Stop a migration batch
Stop-MigrationBatch -Identity "vKARPS-Batch4-Legal"
Remove a user from a migration batch, without deleting the batch.

Note that the batch must be in a stopped state.

Remove-MigrationUser -Identity noob.user@vkarps.com
Get details about a user that is been migrated
Get-MigraitonUser -identity financeteam@vkarps.com
Get detailed migraiton log for a user.

This is useful when troubleshooting migration issues

Get-MigrationUserStatistics noob@vkarps.com -IncludeReport -Diagnostics | Export-Clixml noob@vkarps.com.xml
Mailbox Assessment

These are some one-liners to extract information to help target mailboxes for assesment to see if theyre ready to migrate to O365. This was also helpful to find relationships between user mailboxes and shared mailboxes. Note that these are to be run on the on-premises exchange servers.

Get last logon time

This was useful to identify mailboxes which have not been used in a while or are too large to be migrated. In my case most these were candidates for deletion, saving us licenses in Exchange Online or having difficult conversations to reduce mailbox sizes. Placing in a delimiter allows you to easily separate the columns in excel (text to columns function).

Get-Mailbox | Get-MailboxStatistics | Select-Object DisplayName,LastLoggedOnUserAccount,LastLogonTime,LastLogoffTime,ItemCount,TotalItemSize | Export-Csv -Delimiter ~ -NoTypeInformation C:\temp\MailboxLastLogon.csv
Get Mailbox permissions

This command will list the permissions for each mailbox if one or more accounts have access to it, apart from itself. You may have to do some further filtering on accounts, depending on your environment

Get-Mailbox -ResultSize unlimited | Get-MailboxPermission | where {$_.user.tostring() -ne "NT AUTHORITY\SELF" -and $_.IsInherited -eq $false} | Select Identity,User,@{Name='Access Rights';Expression={[string]::join(', ', $_.AccessRights)}} | Export-Csv -NoTypeInformation C:\Temp\MailboxPermissions.csv
Get Mailbox Type

This is helpful to quickly filter on the types of mailboxes and identity any that are not setup correctly. For example if a shared mailbox is setup as a user mailbox.

 Get-Mailbox -ResultSize unlimited | Select-Object SamAccountName,DisplayName,RecipientTypeDetails,PrimarySMTPAddress | Export-CSV C:\temp\MailboxType.csv
MSOL user operations
Assign License

This will obviously vary depending on what license you wish to apply, but here is the syntax

Set-MSolUserLicense -UserPrincipalName user@vkarps.com -UsageLocation AU
Set-MSolUserLicense -UserPrincipalName user@vkarps.com -AddLicenses vkarps:EXCHANGESTANDARD

Remove License
Set-MSolUserLicense -UserPrincipalName user@vkarps.com -RemoveLicenses vkarps:EXCHANGESTANDARD

Check License Status for users with @DOMAINNAME address
Get-MsolUser -All | Where-Object {$_.UserPrincipalName -like "*@vkarps.com"}

Check license status for list of users in a .csv file

The csv file needs to name ‘name’ in the first line, each following line should contain a valid UPN.

Import-CSV C:\Scripts\NewUsers.csv | ForEach {Get-MsolUser -UserPrincipalName "$($_.Name)"}
Change UPN for MSOL user

I came across instances where user accounts were created with UPNs for other domains / namespaces which were replicated created in the cloud. It can also happen if the UPN is changed after the account has been provisioned in Exchange Online. This issue becomes apparent when you try to migrate the user to Exchange Online. Here is an article which explains the issue:

Set-MsolUserPrincipalName -UserPrincipalName "noob.user@lab.vkarps.com" -NewUserPrincipalName "noob.user@vkarps.onmicrosoft.com"

Set-MsolUserPrincipalName -UserPrincipalName "noob.user@vkarps.onmicrosoft.com" -NewUserPrincipalName "noob.user@vkarps.com"
Deleting mailbox and user from Exchange Online

This may be required for a number of reasons, in my case it was due to duplicate mailboxes (one on-premises and the other on O365). Note: The mailbox will be deleted and cannot be recovered.

Remove-msoluser –userprincipalname noob.user@vkarps.com
Get-msoluser –userprincipalname noob.user@vkarps.com -ReturnDeletedUsers  fl *objectID*
Remove-MsolUser -ObjectID -RemoveFromRecycleBin -Force

You may have to give it a couple of minutes before running the next command

Get-mailbox -SoftdeletedMailbox noob.user@vkarps.com | Remove-Mailbox -PermanentlyDelete -Force -Confirm:$fals