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.
- View Microsoft 365 account license and service details with PowerShell
- Assign Microsoft 365 licenses to user accounts with PowerShell
- Disable access to Microsoft 365 services with PowerShell
- Manage user access to Teams
- Assign Teams add-on licenses to users
- Removing the License for an Office 365 Feature with PowerShell
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 E3ENTERPRISEPREMIUM_NOPSTNCONF- Office 365 E5 without Audio ConferencingO365_BUSINESS_PREMIUM- Microsoft 365 Business StandardO365_BUSINESS_ESSENTIALS- Microsoft 365 Business BasicSPE_E3- Microsoft 365 E3SPE_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 TeamsEXCHANGE_S_STANDARD- Exchange Online Plan 1EXCHANGE_S_ENTERPRISE- Exchange Online Plan 2MCOSTANDARD- Skype for Business OnlineOFFICESUBSCRIPTION- Microsoft 365 Apps for enterpriseINTUNE_A- Microsoft IntuneINTUNE_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* }
There are no comments yet.