Azure Runbook – Licensing Alert

I created this script for a client that wanted to know when they had no available licenses for any SKU.  I’m sure they will add this to the portal soon (?)

The goal is simple – if my consumed no. of licenses = available licenses for any given SKU, send an email to me and my CSP so I can replenish before it becomes a problem.  Easily modified to alert at any number of remaining available licenses. e.g. to alert when there are 5 available licenses change ($_.ConsumedUnits -eq $_.ActiveUnits) to ($_.ConsumedUnits -eq $_.ActiveUnits-5).

The script is written to run as an Azure PowerShell Runbook, which allows use of a credential stored in the automation account, as well as using output to have some nice text show up in the portal logs.  I’m assuming you have set this stuff up already (if you haven’t, google it and get it sorted =). I’ll do a post soon on how to do it but it is not too difficult.

Azure blocks outbound connections on port 25, so no going there!  But aha, they do allow secure port 587.  So I use a ‘soon to be’ deprecated command called send-mailmessage to send the email using a free SendGrid account (no cost for 100 emails per month) which is plenty enough for this solution.

Disclaimer ## as I was testing the script, I noticed Azure now has a ‘SendGrid solution’ where you can sign up to SendGrid free from within the Azure portal – awesome!  Shame I missed it… if I update to using that method I will update this post =).  My understanding is that you could sign up for that, then use it by calling a ‘playbook’ from the automation script.

Here is the script (replace $smtppswd with your sendgrid API key SG.xxxxxx, replace $runbookcredentialname with your runbook cred name, replace $mailfrom and $mailto).  Also, since there may be 0 available licenses or 1000 freely available licenses, by default I’m only considering available license values >1 <500.  Change to suit your needs!

If you have any problems or made the script cooler (like sending the info in an HTML table) please add a comment below! 🙂

# use TLS 1.2
[Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

# check for any licenses out of stock and send a notification - Simon Burbery - August 2021

# create credential for sending email via SendGrid
$smtpuser = 'apikey'
$smtppswd = ConvertTo-SecureString -String 'SG.xxxxxxx' -AsPlainText -Force
$CredSMTP = New-Object -TypeName System.Management.Automation.PSCredential -ArgumentList $SMTPuser, $SMTPpswd

# set variables
$runbookcredentialname = 'svc_runbookaccount'
$mailfrom = 'Azure License Notifcation <>'
$mailto = @("<>", "<>")
$mailsubject = 'Warning - out of licenses!'
$mailbody = 'Availability of one or more of your license SKUs has reached zero:'
$mailserver = ''
$mailport = '587'
$mailcredential = $CredSMTP

# get credential for msol connection
Try { 
    $CredAzure = Get-AutomationPSCredential -Name $runbookcredentialname
        Catch {
            Write-Error "Failed to get credential!"
Write-Output "Get automation credential - Success"

# connect msol
Try {
    Connect-MsolService -Credential $CredAzure
        Catch {    
            Write-Error "Failed to connect to MSOnline - check credential!"
Write-Output "Connect to MSOL - Success"

# license check
$skucheck = Get-MsolAccountSku  | Where-Object { ($_.ActiveUnits -gt 0) -and ($_.ActiveUnits -lt 500) -and ($_.ConsumedUnits -eq $_.ActiveUnits) }

# email body format
$mailbodyfinal = $mailbody,$skucheck | Out-String -Width 500

# send notification
If ( $skucheck -ne $null ) {
    $MailParameters = @{
        From = $mailfrom
        To = $mailto
        Subject = $mailsubject
        Body = $mailbodyfinal
        SmtpServer = $mailserver
        Port = $mailport
        Credential = $CredSMTP
        UseSsl = $true
        Send-MailMessage @MailParameters
            If  ($? -ne $true) { 
    Write-Error "Failed to send email notification!" 
                Else {
                Write-Output "Send email notification - Success"
    Else {
        Write-Output "No licensing issues detected"

# end


4 thoughts on “Azure Runbook – Licensing Alert”

  1. Is there an updated version to use MS Graph ? I cant seem to find the msol modules anymore in Azure Automation.
    Also, how do you go about using service principals? I didt understand how to use the credentials stored in Az Automation. For test i wanted to use my own admin credentials, but as they require MFA, it doesnt seem to work from the runbook.

    1. Hi Morbus, I’m pretty sure the AzureAD module is still there and would have replacement cmds for the license alert script, but I haven’t looked into that at this stage. I will now though! FYI, I started playing with the Graph modules recently… what a nightmare! I haven’t managed to get them working on my personal machine yet, due to seemingly unresolvable version conflicts. I’m switching to VS Code as well as I seem to have more trouble in ISE lately; probably because it is on the way out. AFAIK the Graph modules are still not at a stage where they can replace the MSOLService and AzureAD modules; hopefully that means AzureAD won’t be taken away anytime soon.

      Regarding Service Principals, I’m currently writing a post on how to use the Automation Account Managed Identity to access Exchange Online, so sign up to receive new posts! A bit of hoop-jumping required but once it’s up & running you won’t look back, they are awesome and very reliable. You can use a stored credential but as it’s just a username and password the account must be excluded from any MFA prompt. If you have to use this method, make the password very complex and then use a Conditional Access policy to restrict the account to the geo-region the Runbook will execute from. At least then you have secured the account as much as possible since it is excluded from MFA.

      Cheers, Simon

  2. hi,

    Thank you for a very good work.
    this is the error i got. I entered the credential information I created under automation as runbookcredname.
    is this true

    Get automation credential – Success
    Authentication Error: Bad username or password.
    Connect to MSOL – Success
    You must call the Connect-MsolService cmdlet before calling any other cmdlets.
    No licensing issues detected

    1. Hi emr, okay you’ve pointed out that the error check is not working for the error you received so I’ll fix that – thanks! I also need to update the script to use the AzureAD cmdlets as they will deprecate msonline at some stage.
      I’ll also add an image showing my automation account credential set up. It just has a name and then the user and password saved, so based on the error it seems like the credential may not have been entered correctly, or does not have permission to connect… please try deleting the automation credential and recreating. Then double check you can connect manually using that credential using connect-msonline in a normal PowerShell window on your machine. Thanks for commenting! – Simon.

Leave a Comment

Your email address will not be published. Required fields are marked *

Scroll to Top