The scripts send an email notification if the number of unused licenses for the specified enabled Microsoft 365 license plans falls below a specific limit. To execute either of the scripts, create a Scheduled Task configured for the Domain-DNS object type.
Check all registered tenants
Parameters:
- $limit - Specifies the minimum number of unused licenses. The script will send an email if the number of available licenses is below this limit.
- $skus - Specifies the SKU Part Numbers of the licenses to check. If set to NULL, the script will check all the enabled licenses.
- $to - Specifies email addresses of the email notification recipient(s).
- $subject - Specifies the email notification subject.
- $reportHeader - Specifies the email notification header.
- $htmlTableCoulmns - Specifies column headers for the table that contains details on the number of Microsoft 365 (Office 365) licenses.
- $reportFooter - Specifies the email notification footer.
To get the SKU Part Number of a license plan in Adaxes:
- In Adaxes Administration Console, expand the service node that represents your Adaxes service.
- Navigate to Configuration\Cloud Services and select Microsoft 365.
- Double-click the Microsoft 365 (Office 365) tenant to which the license belongs.
- Click the necessary license plan. The SKU Part Number is displayed below the Display Name field.
PowerShell
$limit = 5 # TODO: modify me
$skus = @("ENTERPRISEPREMIUM", "ENTERPRISEPACK") # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "List of Microsoft 365 plans that have $limit or less licenses available" # TODO: modify me
$reportHeader = "<h2>List of Microsoft 365 plans that have $limit or less licenses available</h2>"
$htmlTableColumns = "
<table border='1'>
<tr>
<th>License Plan</th>
<th>Total Licenses</th>
<th>Unused Licenses</th>
</tr>
" # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me
# Find all tenants
$microsoft365TenantsPath = $Context.GetWellKnownContainerPath("CloudServicesO365")
$searcher = $Context.BindToObject($microsoft365TenantsPath)
$searcher.SearchFilter = "(objectClass=adm-O365Tenant)"
$searcher.SearchScope = "ADS_SCOPE_SUBTREE"
$searcher.PageSize = 500
try
{
$searchResultIterator = $searcher.ExecuteSearch()
$searchResults = $searchResultIterator.FetchAll()
$report = $NULL
foreach ($searchResult in $searchResults)
{
# Bind to the tenant
$tenant = $Context.BindToObject($searchResult.AdsPath)
# Check licenses
$htmlTable = $NULL
foreach ($sku in $tenant.Skus)
{
if (($skus -ne $NULL) -and ($skus -notcontains $sku.SkuPartNumber))
{
continue
}
$difference = $sku.TotalUnits - $sku.ConsumedUnits
if ($difference -gt $limit)
{
continue
}
if ($htmlTable -eq $NULL)
{
$htmlTable += "<h3>$($tenant.TenantName)</h3>$htmlTableColumns"
}
$htmlTable += "<tr><td>$($sku.DefaultDisplayName)</td><td>$($sku.TotalUnits)</td><td>$difference</td></tr>"
}
if ($htmlTable -eq $NULL)
{
continue
}
$htmlTable += "</table>"
$report += $htmlTable
}
if ($report -eq $NULL)
{
return # There are no licenses in any tenant that are below the limit
}
# Build report
$html = $reportHeader + $report + $reportFooter
# Send mail
$Context.SendMail($to, $subject, $NULL, $html)
}
finally
{
# Release resources
$searchResultIterator.Dispose()
}
Check only the specified tenant
Parameters:
- $limit - Specifies the minimum number of unused licenses. The script will send an email if the number of available licenses is below this limit.
- $skus - Specifies the SKU Part Numbers of the licenses to check. If set to NULL, the script will check all the enabled licenses.
- $tenantName - Specifies the name of the Microsoft 365 tenant to check licenses in. The variable should contain the tenant name as it is specified in Adaxes.
- $to - Specifies email addresses of the email notification recipient(s).
- $subject - Specifies the email notification subject.
- $reportHeader - Specifies the email notification header.
- $htmlTableCoulmns - Specifies column headers for the table that contains details on the number of Microsoft 365 (Office 365) licenses.
- $reportFooter - Specifies the email notification footer.
To get the SKU Part Number of a license plan in Adaxes:
- In Adaxes Administration Console, expand the service node that represents your Adaxes service.
- Navigate to Configuration\Cloud Services and select Microsoft 365.
- Double-click the Microsoft 365 (Office 365) tenant to which the license belongs.
- Click the necessary license plan. The SKU Part Number is displayed below the Display Name field.
PowerShell
$limit = 5 # TODO: modify me
$skus = @("ENTERPRISEPREMIUM", "ENTERPRISEPACK") # TODO: modify me
$tenantName = "My tenant" # TODO: modify me
# E-mail settings
$to = "recipient@domain.com" # TODO: modify me
$subject = "List of Microsoft 365 plans that have $limit or less licenses available" # TODO: modify me
$reportHeader = "<h2>List of Microsoft 365 plans that have $limit or less licenses available</h2>"
$htmlTableColumns = "
<table border='1'>
<tr>
<th>License Plan</th>
<th>Total Licenses</th>
<th>Unused Licenses</th>
</tr>
" # TODO: modify me
$reportFooter = "<hr /><p><i>Please do not reply to this e-mail, it has been sent to you for notification purposes only.</i></p>" # TODO: modify me
# Bind to the Microsoft 365 tenant
$microsoft365TenantsPath = $Context.GetWellKnownContainerPath("CloudServicesO365")
$container = $Context.BindToObject($microsoft365TenantsPath)
$tenant = $container.GetObject("adm-O365Tenant", "CN=$tenantName")
# Check licenses
$htmlTable = $NULL
foreach ($sku in $tenant.Skus)
{
if (($skus -ne $NULL) -and ($skus -notcontains $sku.SkuPartNumber))
{
continue
}
$difference = $sku.TotalUnits - $sku.ConsumedUnits
if ($difference -gt $limit)
{
continue
}
if ($htmlTable -eq $NULL)
{
$htmlTable += "<h3>$($tenant.TenantName)</h3>$htmlTableColumns"
}
$htmlTable += "<tr><td>$($sku.DefaultDisplayName)</td><td>$($sku.TotalUnits)</td><td>$difference</td></tr>"
}
if ($htmlTable -eq $NULL)
{
return # There are no licenses in the tenant that are below the limit
}
# Build report
$htmlTable += "</table>"
$html = $reportHeader + $htmlTable + $reportFooter
# Send mail
$Context.SendMail($to, $subject, $NULL, $html)
O365_BUSINESS_ESSENTIALS
Office 365 Business
Hello Dave,
Yes, it is possible. We have updated the script with the possibility to specify SKU Part Numbers of the licenses to check.
Hello,
Could you, please, send us (support[at]adaxes.com) the script you are using with all the modifications and a screenshot of the full error message you are getting?
Hello,
We were not able to reproduce the issue and the script works just fine. Could you, please, send us (support[at]adaxes.com) the script you are using with all the modifications and a screenshot of the full error message you are getting?
Also, please, specify how exactly the script is executed. A screenshot of the Scheduled Task that runs the script would be very helpful.
We don't want a email at all unless it falls below on something.
Sorry for the confusion, but we are not sure what exactly you mean. The current script sends an email notification only if at least one of the specified Microsoft 365 licenses falls below the limit. If none of the licenses fall below the limit no email notification is send. If the email is still sent, please, make sure that you are using the exact above script without any modifications.
Yes, it is possible. Just specify all the addresses in the $to variable:
$to = "recipient@domain.com, recipient2@domain.com"
Unfortunately, there is no such possibility in the current script. However, it is possible to modify the script to meet your needs. Please, describe the desired behavior in all the possible details with live examples.
$limit = 10
$skus = @("EXCHANGESTANDARD","MCOMEETADV","SPE_E3","IDENTITY_THREAT_PROTECTION","MCOEV","POWER_BI_PRO")
$limit = 5
$skus = @("EXCHANGEENTERPRISE","POWER_BI_PRO","PROJECTPROFESSIONAL")
$limit = 3
$skus = @("VISIOCLIENT","MEETING_ROOM","PROJECT_P1")
Thank you for clarifying. What about the email recipients? Should they be the same for all licenses?
Also, please, specify how Microsoft 365 licenses should be identified in the email notifications. Should that be the licenses SKU Part Numbers or their display names as specified in the tenant settings?
Any additional details will be much appreciated.
For our case only one recipient is needed; however, I can see how this could be really useful to be able to specify recipients to specific limits.
For identification purposes, the display names of each SKU are good enough. If there's a way to also include the SKU part number along with the display name then I think this would be perfect.
We also do manage a separate instance of Adaxes and MS tenant. I figured this will simply have to be managed separately with a script on that Adaxes admin console? Or is there a possibility to apply all of the above to multiple tenants from the same script? No big deal if this is not possible, but less management is always better :)
> For our case only one recipient is needed; however, I can see how this could be really useful to be able to specify recipients to specific limits.
We will update the script so that it is possible to specify a separate recipient for each license.
> We also do manage a separate instance of Adaxes and MS tenant.
If you have separate instances (not sharing common configuration) of Adaxes service you will need to configure the script execution separately on each of them.
> Or is there a possibility to apply all of the above to multiple tenants from the same script?
The script check licenses in all the Microsoft 365 tenants registered for the Adaxes service the script is executed by. If you need information about tenants included into the email, please, provide a sample email notification.
Is there a way to only report on the specific tenant rather than all the tenants?
Yes, it is possible. We added the corresponding script (Check only the specified tenant) to the article.
Looks like it's pointing to '"CloudServicesO365". What is that value exactly?
Thanks!
The value is correct. For troubleshooting purposes, please, send us (support@adaxes.com) a full screenshot of the error you are facing.
I do not seem to have the domain-dns object type available when selecting the object type, where can I find it?
Could you, please, specify what version of Adaxes you are currently using? For information on how to check it, have a look at the following help article: https://www.adaxes.com/help/CheckServiceVersion.
Thank you for specifying. The Domain-DNS object type is not present in Adaxes 2023 that you are using. You need to select the Domain object type. The rest remains the same.
$to = "recipient@domain.com" # TODO: modify me
[Product version=3.16.21408.0]
In your version of Adaxes, the following approach for multiple recipients should be used: