EN 
06.12.2025 Mikuláš WELCOME IN MY WORLD

This website is originally written in the Czech language. Most content is machine (AI) translated into English. The translation may not be exact and may contain errors.

Tento článek si můžete zobrazit v originální české verzi. You can view this article in the original Czech version.
PowerShell pro Azure AD, Exchange Online, práce s licencemi

PowerShell for Azure AD, Exchange Online, working with licenses

| Petr Bouška - Samuraj |
This article is just my notes. It contains brief information about using PowerShell to get information about users in Azure AD and mailboxes in Exchange Online (EXO). It also covers working with licenses and various bulk operations. Describes how to remove (block) a specific service, such as Exchange Online or Teams. Finally, this information is used to solve the problem where a user with an on-premises mailbox has a second mailbox in EXO.
displayed: 9 894x (7 359 CZ, 2 535 EN) | Comments [0]

Note: I am not an expert in this area and further steps may not be optimal, but they are functional. I have not studied whether it is more appropriate to use Azure Active Directory PowerShell for Graph (AzureAD) or Microsoft Azure Active Directory Module for Windows PowerShell (MSOnline). Or something else, and I use both. Similarly for Exchange Online, the recommended use is the EXO V2 module cmdlets.

PowerShell information about accounts

Certain information will be provided to us by PowerShell queries into Active Directory. More useful are Exchange extensions. The commands are the same for on-premises Exchange and Exchange Online (EXO), but some parameters and settings are only for one environment. For Exchange Online (EXO), Microsoft recommends using the new version with the EXO prefix for most commands, for example Get-EXOMailbox.

on-premises PowerShell ActiveDirectory

Active Directory module for Windows PowerShell

For a user in Active Directory, we can view Exchange attributes.

Get-ADUser novy -Properties * | FL UserPrincipalName, msExch*, proxyAddresses

Online PowerShell AzureAD

Azure Active Directory PowerShell

Using AzureAD commands, we won't see many attributes about the mail.

Install-Module -Name AzureAD
Connect-AzureAD

Get-AzureADUser -ObjectId bouska@firma.cz | FL UserPrincipalName, Mail, ProxyAddresses
Get-AzureADUserExtension -ObjectId bouska@firma.cz

Azure Active Directory (MSOnline)

Install-Module -Name MSOnline
Connect-MsolService

Get-MsolUser -UserPrincipalName bouska@firma.cz

on-premises Exchange Management Shell

Exchange Server PowerShell (Exchange Management Shell)

Get-Mailbox -Identity novy@firma.cz | FL PrimarySmtpAddress, ExchangeGuid, Database, RecipientType
Get-Recipient -Identity novy@firma.cz | FL PrimarySmtpAddress, ExchangeGuid, Database, RecipientType
Get-MailboxLocation -Identity novy@firma.cz | FL MailboxGuid, MailboxLocationType, DatabaseLocation
Get-RemoteMailbox
Get-MailUser
Get-User pokus@firma.cz | Select Name, *Recipient*

Exchange Online Management

Connect to Exchange Online PowerShell

Install-Module -Name ExchangeOnlineManagement -RequiredVersion 1.0.1
Import-Module ExchangeOnlineManagement
Connect-ExchangeOnline -UserPrincipalName admin@firma.cz -ShowProgress $true

Get-User pokus@firma.cz | Select Name, *Recipient*
Get-Mailbox -Identity pokus@firma.cz | FL PrimarySmtpAddress, ExchangeGuid, Database, RecipientType
Get-EXOMailbox -Identity pokus@firma.cz
Get-EXORecipient | FT Name, Reci*

Microsoft 365 and working with licenses

How to work with assigning and removing licenses, or just services/applications, can be inspired by various articles.

More often, the Microsoft Azure Active Directory Module for Windows PowerShell (MSOnline) is used in the examples, although both can be used.

Install-Module -Name MSOnline
Connect-MsolService

Subscriptions, license plans, and services

Microsoft 365 Subscription (subscription) contains license plans (Licensing plans), which define the services available to users. Services (Services), or also service plans (Service Plans), are products (applications), features, and capabilities available in the license plan. Each license plan contains a certain number of purchased licenses (Licenses). These are assigned to individual users.

In the commands, we use SkuPartNumber (LicensingPlan). The complete list, together with the license plan names, can be found in the table Product names and service plan identifiers for licensing (which is quite difficult to work with). Some extended examples are

  • ENTERPRISEPACK - Office 365 E3
  • ENTERPRISEPREMIUM_NOPSTNCONF - Office 365 E5 without Audio Conferencing
  • O365_BUSINESS_PREMIUM - Microsoft 365 Business Standard
  • O365_BUSINESS_ESSENTIALS - Microsoft 365 Business Basic
  • SPE_E3 - Microsoft 365 E3
  • SPE_E5 - Microsoft 365 E5

Somewhere they work with AccountSkuId, which is the name of the tenant (organization) together with the license plan, e.g. firma:ENTERPRISEPACK.

In the license plan there are services, or service plans, such as

  • TEAMS1 - Microsoft Teams
  • EXCHANGE_S_STANDARD - Exchange Online Plan 1
  • EXCHANGE_S_ENTERPRISE - Exchange Online Plan 2
  • MCOSTANDARD - Skype for Business Online
  • OFFICESUBSCRIPTION - Microsoft 365 Apps for enterprise
  • INTUNE_A - Microsoft Intune
  • INTUNE_O365 - Mobile Device Management for Office 365

Information about licenses, services, and users

List of available license plans (Licensing plans) and the number of licenses (Licenses)

PS C:\> Get-MsolAccountSku

AccountSkuId                    ActiveUnits WarningUnits ConsumedUnits
------------                    ----------- ------------ -------------
firmatest:ENTERPRISEPACK        0           25           0            
firmatest:O365_BUSINESS_PREMIUM 25          0            6            
firmatest:TEAMS_EXPLORATORY     100         0            1            

List of licenses assigned to a user

PS C:\> (Get-MsolUser -UserPrincipalName bouska@firma.cz).Licenses

ExtensionData          : System.Runtime.Serialization.ExtensionDataObject
AccountSku             : Microsoft.Online.Administration.AccountSkuIdentifier
AccountSkuId           : firmatest:O365_BUSINESS_PREMIUM
GroupsAssigningLicense : {}
ServiceStatus          : {Microsoft.Online.Administration.ServiceStatus, Microsoft.Online.Administration.ServiceStatus,
Microsoft.Online.Administration.ServiceStatus...}

PS C:\> (Get-MsolUser -UserPrincipalName bouska@firma.cz).Licenses.Accountsku.Skupartnumber
O365_BUSINESS_PREMIUM

List of services in a given license plan of the company

PS C:\> (Get-MsolAccountSku | where {$_.AccountSkuId -eq "firma:ENTERPRISEPACK"}).ServiceStatus

ServicePlan                  ProvisioningStatus
-----------                  ------------------
POWER_VIRTUAL_AGENTS_O365_P2 Success           
CDS_O365_P2                  Success           
PROJECT_O365_P2              Success           
DYN365_CDS_O365_P2           Success           
MICROSOFTBOOKINGS            Success           
KAIZALA_O365_P3              Success           
MICROSOFT_SEARCH             Success           
WHITEBOARD_PLAN2             Success           
MIP_S_CLP1                   Success           
MYANALYTICS_P2               Success           
BPOS_S_TODO_2                Success           
FORMS_PLAN_E3                Success           
STREAM_O365_E3               Success           
Deskless                     Success           
FLOW_O365_P2                 Success           
POWERAPPS_O365_P2            Success           
TEAMS1                       Success           
PROJECTWORKMANAGEMENT        Success           
SWAY                         Success           
INTUNE_O365                  Success           
YAMMER_ENTERPRISE            Success           
RMS_S_ENTERPRISE             Success           
OFFICESUBSCRIPTION           Success           
MCOSTANDARD                  Success           
SHAREPOINTWAC                Success           
SHAREPOINTENTERPRISE         Success           
EXCHANGE_S_ENTERPRISE        Success           

List of services the given user has access to

PS C:\> (Get-MsolUser -UserPrincipalName bouska@firma.cz).Licenses.ServiceStatus

ServicePlan                     ProvisioningStatus 
-----------                     ------------------ 
POWER_VIRTUAL_AGENTS_O365_P2    Success            
CDS_O365_P2                     Success            
PROJECT_O365_P2                 Success            
DYN365_CDS_O365_P2              Success            
MICROSOFT_SEARCH                PendingProvisioning
WHITEBOARD_PLAN1                Success            
MYANALYTICS_P2                  Success            
DYN365BC_MS_INVOICING           Success            
KAIZALA_O365_P2                 Success            
STREAM_O365_SMB                 Success            
Deskless                        Success            
BPOS_S_TODO_1                   Success            
MICROSOFTBOOKINGS               Success            
FORMS_PLAN_E1                   Success            
FLOW_O365_P1                    Success            
POWERAPPS_O365_P1               Success            
O365_SB_Relationship_Management Success            
TEAMS1                          Success            
PROJECTWORKMANAGEMENT           Success            
SWAY                            Success            
INTUNE_O365                     PendingActivation  
SHAREPOINTWAC                   Success
OFFICE_BUSINESS                 Success            
YAMMER_ENTERPRISE               Success            
EXCHANGE_S_STANDARD             Success            
MCOSTANDARD                     Success            
SHAREPOINTSTANDARD              Success     

List of users who have the Office 365 E3 (ENTERPRISEPACK) license assigned

Get-MsolUser | Where-Object {$_.Licenses.AccountSku.SkuPartNumber -eq "ENTERPRISEPACK" -and $_.IsLicensed -eq $True}

List of available license plans and their services

foreach($sku in (Get-MsolAccountSku)) { 
  foreach($sp in $sku.ServiceStatus) { 
    New-Object -TypeName PSObject -Property @{"AccountSkuId"=$sku.AccountSkuId;"ServicePlan"=$sp.ServicePlan.ServiceName} 
  }
}

List of available license plans where a certain service is located

PS C:\> foreach($sku in (Get-MsolAccountSku)) { 
  foreach($sp in $sku.ServiceStatus | where {$_.ServicePlan.ServiceName -like "INTUNE*"}) { 
    New-Object -TypeName PSObject -Property @{"AccountSkuId"=$sku.AccountSkuId;"ServicePlan"=$sp.ServicePlan.ServiceName} 
  }
}

ServicePlan AccountSkuId                         
----------- ------------                         
INTUNE_O365 firma:ENTERPRISEPREMIUM_NOPSTNCONF
INTUNE_A    firma:SPE_E5                      
INTUNE_O365 firma:SPE_E5                      
INTUNE_A    firma:SPE_E3                      
INTUNE_O365 firma:SPE_E3                      
INTUNE_O365 ccfirma:O365_BUSINESS_ESSENTIALS    

Assigning and removing licenses

Assign a license to a user

Set-MsolUserLicense -UserPrincipalName bouska@firma.cz -AddLicenses "firma:ENTERPRISEPREMIUM_NOPSTNCONF"

In order to assign a license to a user, the account must have the UsageLocation set to a valid country code

Set-MsolUser -UserPrincipalName bouska@firma.cz -UsageLocation CZ

Remove a license from a user

Set-MsolUserLicense -UserPrincipalName bouska@firma.cz -RemoveLicenses "firma:ENTERPRISEPREMIUM_NOPSTNCONF"

Replace one license with another (will be performed as a single operation)

Set-MsolUserLicense -UserPrincipalName bouska@firma.cz -AddLicenses "firma:ENTERPRISEPREMIUM_NOPSTNCONF" `
 -RemoveLicenses "firma:ENTERPRISEPACK"

Removing a service from a license

We can create a special license object where we turn off a specific service

$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPACK" -DisabledPlans "EXCHANGE_S_ENTERPRISE"

We can also turn off multiple services (sometimes it is a condition because the services have a mutual relationship)

$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPREMIUM_NOPSTNCONF" `
 -DisabledPlans "EXCHANGE_S_ENTERPRISE", "THREAT_INTELLIGENCE", "EXCHANGE_ANALYTICS"

We can then apply that to a user

Set-MsolUserLicense -UserPrincipalName bouska@firma.cz -LicenseOptions $lic

If we want to enable all services again

$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPACK"
Set-MsolUserLicense -UserPrincipalName bouska@firma.cz -LicenseOptions $lic

Bulk operations - list of users

To perform the same settings for multiple users, we need to get their list. We can list users based on certain common parameters and apply a command. Or we can create a text file, either from some output or manually, where we can check its contents.

List of users by department

Get-MsolUser -All -Department "IT administration" | Select UserPrincipalName

List of users with an assigned license (Office 365 E3) synchronized from on-premises to the cloud

Get-MsolUser -Synchronized | Where-Object {$_.Licenses.AccountSku.SkuPartNumber -eq "ENTERPRISEPACK" -and $_.IsLicensed -eq $True} |
 Sort-Object UserPrincipalName | Select-Object UserPrincipalName

List of users with a mailbox in the cloud, synchronized from on-premises

Get-User | Where-Object {$_.RecipientTypeDetails -eq "UserMailbox" -and $_.IsDirSynced } | Sort-Object UserPrincipalName |
 Select-Object UserPrincipalName

List of users with a mailbox in the cloud, an assigned license (Office 365 E5 without Audio Conferencing), synchronized from on-premises

Get-MsolUser -Synchronized | Where-Object {$_.Licenses.AccountSku.SkuPartNumber -eq "ENTERPRISEPREMIUM_NOPSTNCONF" `
 -and $_.IsLicensed -eq $True -and (Get-User $_.UserPrincipalName).RecipientTypeDetails -eq "UserMailbox" } |
 Sort-Object UserPrincipalName | Select-Object UserPrincipalName

Bulk operations with licenses for users

If we save the list of users (their UserPrincipalName) to a text file accounts.txt, we can use it in various commands and apply the settings to all users in the list.

Only display the content of the file (line by line)

Get-Content "d:\accounts.txt" | foreach {$_}

Information about the recipient type (whether they have a mailbox)

Get-Content "d:\accounts.txt" | foreach {Get-User $_ | Select Name,*Recipient*}

Set the license object (remove a service) for users from the file

Get-Content "d:\accounts.txt" | foreach {Set-MsolUserLicense -UserPrincipalName $_ -LicenseOptions $lic}

List of users and their assigned licenses

Get-Content "d:\accounts.txt" | foreach {$_; (Get-MsolUser -UserPrincipalName $_).Licenses.Accountsku.Skupartnumber}

Set UsageLocation and assign a license (we could set in one command)

Get-Content "d:\accounts.txt" | foreach {Set-MsolUser -UserPrincipalName $_ -UsageLocation CZ}
Get-Content "d:\accounts.txt" | foreach {Set-MsolUserLicense -UserPrincipalName $_ -AddLicenses "firma:ENTERPRISEPACK"}

Remove a license

Get-Content "d:\accounts.txt" | foreach {Set-MsolUserLicense -UserPrincipalName $_ -RemoveLicenses "firma:STREAM"}

Fixing an account when a duplicate mailbox is removed from the cloud

This problem will be described in more detail in another article. If it happens that the user has a mailbox on the on-premises Exchange server and at the same time an (unused) mailbox was created on Exchange Online. To make everything work properly, we need to remove the cloud mailbox and connect the account to the internal mailbox.

We will prepare a license object where we remove the Exchange Online service from the given license

$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPREMIUM_NOPSTNCONF" `
 -DisabledPlans "EXCHANGE_S_ENTERPRISE", "THREAT_INTELLIGENCE", "EXCHANGE_ANALYTICS"

Apply it to the users from the file

Get-Content "d:\accounts.txt" | foreach {Set-MsolUserLicense -UserPrincipalName $_ -LicenseOptions $lic}

Remove the information about the previous mailbox from the users (without confirmation)

Get-Content "d:\accounts.txt" | foreach {Set-User $_ -PermanentlyClearPreviousMailboxInfo -Confirm:$false}

Restore the Exchange Online service to the users

$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPREMIUM_NOPSTNCONF"
Get-Content "d:\accounts.txt" | foreach { Set-MsolUserLicense -UserPrincipalName $_ -LicenseOptions $lic }

Between the individual steps, it is good to print information about the recipient type so that we perform the next step only when the changes are applied. Especially when removing the Exchange service, it takes quite a long time for the user to change from UserMailbox to MailUser. The entire process can look like this (we don't run it all at once).

Get-Content "d:\accounts.txt" | foreach { Get-User $_ | Select Name,*Recipient* }
$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPACK" -DisabledPlans "EXCHANGE_S_ENTERPRISE"
Get-Content "d:\accounts.txt" | foreach { Set-MsolUserLicense -UserPrincipalName $_ -LicenseOptions $lic }
Get-Content "d:\accounts.txt" | foreach { Get-User $_ | Select Name,*Recipient* }
Get-Content "d:\accounts.txt" | foreach { Set-User $_ -PermanentlyClearPreviousMailboxInfo -Confirm:$false }
Get-Content "d:\accounts.txt" | foreach { Get-User $_ | Select Name,*Recipient* }
$lic = New-MsolLicenseOptions -AccountSkuId "firma:ENTERPRISEPACK"
Get-Content "d:\accounts.txt" | foreach { Set-MsolUserLicense -UserPrincipalName $_ -LicenseOptions $lic }
Get-Content "d:\accounts.txt" | foreach { Get-User $_ | Select Name,*Recipient* }
Author:

Related articles:

Azure, Microsoft 365, Office 365, Cloud

Various popular topics regarding the public cloud. More focused on Microsoft services, i.e. IaaS, PaaS, SaaS Azure, Entra ID directory services (formerly Azure AD) and hosted Microsoft 365 / Office 365 services.

PowerShell

Articles related to Microsoft's PowerShell scripting language, which is used in all new versions of MS OS and applications.

If you want write something about this article use comments.

Comments

There are no comments yet.

Add comment

Insert tag: strong em link

Help:
  • maximum length of comment is 2000 characters
  • HTML tags are not allowed (they will be removed), you can use only the special tags listed above the input field
  • new line (ENTER) ends paragraph and start new one
  • when you respond to a comment, put the original comment number in squar brackets at the beginning of the paragraph (line)