SOLVED

Email IT department a report of a specific mailbox reaching 90% storage quota

Bronze Contributor

Hello everyone,

 

I'm looking for a script that can send a warning email to the IT department when a user's mailbox reaches 90% capacity.

I intend to schedule this script to run through a runbook.

I've come across a script that runs, but it doesn't seem to trigger any action; I don't receive any emails or notifications. It's evident that I'm missing something or doing something incorrectly. Any suggestions or ideas would be greatly appreciated.

 

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox statistics for the specified mailbox
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if mailbox size exceeds the warning quota
if ($mailboxStats.TotalItemSize -gt 0 -and $mailboxStats.ProhibitSendQuota -gt 0) {
$totalMailboxSize = $mailboxStats.TotalItemSize / 1GB
$mailboxWarningQuota = $mailboxStats.ProhibitSendQuota / 1GB

if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
# Send an email notification
$emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."
Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "Smtp.office365.com"
}
}

 

 

17 Replies

Hi @AB21805 ,

I've reviewed the code you provided and noticed a problem with the data types used. I understand that the values returned for TotalItemSize and ProhibitSendQuota are not simple numbers, but complex objects that contain data capacity (ByteQuantifiedSize type). This would make direct comparisons between them problematic.

I'd like to propose a modification to the script that solves this problem by properly converting these values into a comparable format. I'll post the revised code in the comments below.

Below is the modified code

 

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox statistics for the specified mailbox
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if mailbox size exceeds the warning quota
if ($mailboxStats.TotalItemSize -gt 0 -and $mailboxStats.ProhibitSendQuota -gt 0) {
    $totalMailboxSize = $mailboxStats.TotalItemSize.Value.ToBytes() / 1GB  
    $mailboxWarningQuota = $mailboxStats.ProhibitSendQuota.Value.ToBytes() / 1GB  

    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."
        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "Smtp.office365.com"
    }
}

 

 


Before modification

$totalMailboxSize = $mailboxStats.TotalItemSize / 1GB
$mailboxWarningQuota = $mailboxStats.ProhibitSendQuota / 1GB

 

After modification

$totalMailboxSize = $mailboxStats.TotalItemSize.Value.ToBytes() / 1GB
$mailboxWarningQuota = $mailboxStats.ProhibitSendQuota.Value.ToBytes() / 1GB

 

Thank you

 

Best regards,

Minseok Song

Hi !@Minseok_Song 

 

Thanks for this now I am getting error? 

 

Screenshot 2024-04-18 at 10.52.22.png

 

Is this because the limit has now been reached yet? 

 

@AB21805  I've checked my proposed code and found some places where it might cause additional type issues, I'll re-propose the code below with those fixes, thanks.

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox statistics for the specified mailbox
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if mailbox size exceeds the warning quota
if ($mailboxStats.TotalItemSize.Value.ToBytes() -gt 0 -and $mailboxStats.ProhibitSendQuota.Value.ToBytes() -gt 0) {
    $totalMailboxSize = $mailboxStats.TotalItemSize.Value.ToBytes() / 1GB  
    $mailboxWarningQuota = $mailboxStats.ProhibitSendQuota.Value.ToBytes() / 1GB  

    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."
        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "Smtp.office365.com"
    }
}

 

 

@AB21805  I took a look at the latest documentation and made some changes to the code to match the v3 exo version. In the end, the main cause of the problem was that the TotalItemSize and the ProhibitSendQuota type were not returned in byte form. If you encounter this error in the future, please be aware of it and change the code accordingly. Thank you very much.

 

 

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox statistics for the specified mailbox
$mailboxStats = Get-EXOMailboxStatistics -Identity $mailboxIdentity

# Check if mailbox size exceeds the warning quota
if ($mailboxStats.TotalItemSize.ToBytes() -gt 0 -and $mailboxStats.ProhibitSendQuota.ToBytes() -gt 0) {
    $totalMailboxSize = $mailboxStats.TotalItemSize.ToBytes() / 1GB  
    $mailboxWarningQuota = $mailboxStats.ProhibitSendQuota.ToBytes() / 1GB  

    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."
        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "Smtp.office365.com"
    }
}

 

 

 

Code changes

 

Get-MailboxStatistics -> Get-EXOMailboxStatistics

 

TotalItemSize.Value.ToBytes() -> TotalItemSize.ToBytes()
ProhibitSendQuota.Value.ToBytes() -> ProhibitSendQuota.ToBytes()

 

 

Hi, Slightly different error this time!

Method invocation failed because [Microsoft.Exchange.Management.RestApiClient.Unlimited`1[[Microsoft.Exchange.Management.RestApiClient.ByteQuantifiedSize,
Microsoft.Exchange.Management.RestApiClient, Version=15.0.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35]]] does not contain a method named 'ToBytes'.
At line:11 char:5
+ if ($mailboxStats.TotalItemSize.ToBytes() -gt 0 -and $mailboxStats.Pr ...
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidOperation: (:) [], RuntimeException
+ FullyQualifiedErrorId : MethodNotFound


Is this working for you?
I'm using a different version of PowerShell, so I can't give you the exact code for your version.
To change the data types of TotalItemSize and ProhibitSendQuota, you will need to refer to the documentation for the objects that contain these properties or related materials.
If you need help, you can refer to the official documentation for your version of PowerShell or ask someone else for help again.
Thank you.
Hi can you confirm what version you are using so I can then try with that?

Hi @AB21805 , I don't think you need to lower the version because of this issue. Let me test the code again in my EXO V3 environment and get back to you with a cleaned up answer. I looked it up and it seems to work fine if you convert the TotalItemSize to a string and then double it.

best response confirmed by AB21805 (Bronze Contributor)
Solution

Hi @AB21805, I tested it on EXO V3 and here is the revised code. I found some other errors besides the existing type error, so I fixed the code in general.

I'll give you the full modified code first and explain it. The modified code works fine in my local environment.

 

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox configuration and statistics for the specified mailbox
$mailboxConfig = Get-Mailbox -Identity $mailboxIdentity
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if TotalItemSize and ProhibitSendQuota are not null and extract the sizes
if ($mailboxStats.TotalItemSize -and $mailboxConfig.ProhibitSendQuota) {
    $totalSizeBytes = $mailboxStats.TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]
    $prohibitQuotaBytes = $mailboxConfig.ProhibitSendQuota.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]

    # Convert sizes from bytes to gigabytes
    $totalMailboxSize = $totalSizeBytes / 1GB
    $mailboxWarningQuota = $prohibitQuotaBytes / 1GB

    # Check if the mailbox size exceeds 90% of the warning quota
    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential (Get-Credential)
    }
} else {
    Write-Host "The required values(TotalItemSize or ProhibitSendQuota) are not available."
}

 

 

To test if the mail sending function was working, I temporarily modified the condition to if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.0)).

solved.png

 

 

@AB21805I'll outline the code changes below and detail the specific problems I encountered and solved.

 

1. Type Error

Firstly, there was a type error in the original code, which I have corrected as follows:

 

Original code

 

$mailboxStats.TotalItemSize
$mailboxStats.ProhibitSendQuota

 

 

Modified code

 

$totalSizeBytes = $mailboxStats.TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]
$prohibitQuotaBytes = $mailboxConfig.ProhibitSendQuota.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]

 

 

2. method error

 

There was a problem where ProhibitSendQuota was called on the wrong object, which I have fixed in the modified code below. This may have been one of the reasons why the code did not work correctly the first time you ran it.

 

Original code

 

$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

$mailboxStats.TotalItemSize
$mailboxStats.ProhibitSendQuota

 

 

Modified code

 

$mailboxConfig = Get-Mailbox -Identity $mailboxIdentity
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

$mailboxStats.TotalItemSize
$mailboxConfig.ProhibitSendQuota

 

 

3. Credential error

I encountered an authentication-related error when sending mail, so I made some adjustments to the port number and updated the code accordingly.

 

Original code

 

Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "Smtp.office365.com"

 

 

Modified code

 

Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential (Get-Credential)

 

 

Finally, I made some changes to the logic. While testing the code, I noticed errors when variables like  ProhibitSendQuota came in as null, so I adjusted the code to handle such cases more gracefully.

Thank you so much! The script works! Do I need to change much to log in with a managed identify (system assigned) within a runbook for exchange online - ( the identiy already has permission) and module installed.  

I keep getting this!

System.Management.Automation.ParameterBindingException: Cannot process command because of one or more missing mandatory parameters: Credential.
at System.Management.Automation.CmdletParameterBinderController.PromptForMissingMandatoryParameters(Collection`1 fieldDescriptionList, Collection`1 missingMandatoryParameters)
at System.Management.Automation.CmdletParameterBinderController.HandleUnboundMandatoryParameters(Int32 validParameterSetCount, Boolean processMissingMandatory, Boolean promptForMandatory, Boolean isPipelineInputExpected, Collection`1& missingMandatoryParameters)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)
at System.Management.Automation.CommandProcessor.BindCommandLineParameters()
at System.Management.Automation.CommandProcessor.Prepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.CommandProcessorBase.DoPrepare(IDictionary psDefaultParameterValues)
at System.Management.Automation.Internal.PipelineProcessor.Start(Boolean incomingStream)
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
--- End of stack trace from previous location where exception was thrown ---
at System.Runtime.ExceptionServices.ExceptionDispatchInfo.Throw()
at System.Management.Automation.Internal.PipelineProcessor.SynchronousExecuteEnumerate(Object input)
at System.Management.Automation.PipelineOps.InvokePipeline(Object input, Boolean ignoreInput, CommandParameterInternal[][] pipeElements, CommandBaseAst[] pipeElementAsts, CommandRedirection[][] commandRedirections, FunctionContext funcContext)
at System.Management.Automation.Interpreter.ActionCallInstruction`6.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)
at System.Management.Automation.Interpreter.EnterTryCatchFinallyInstruction.Run(InterpretedFrame frame)

@AB21805  If you want to connect to Exchange Online using a managed identity in Azure Automation, you must specify the -UseManagedIdentity flag, which works without the additional Credential parameter.

 

Original code

Connect-ExchangeOnline

 

Modified code

Connect-ExchangeOnline -UseManagedIdentity -Verbose

 

And if you're using Azure Automation, my understanding is that you need to use Azure Automation to get the credentials, and you can do that by modifying the code that sends the email like this.

 

Original code

# Send an email notification
$emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential (Get-Credential)

 

 

Modified code

# Automation Account Credential
$credential = Get-AutomationPSCredential -Name 'SMTPCredential'

# Send an email notification
$emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential $smtpCredential

 

 

I've provided the code below for you to try out. Since I'm not currently able to test this code myself, it may require some adjustments, especially in the credential methods, to meet your specific needs.

 

# Connect to Exchange Online using Managed Identity
Connect-ExchangeOnline -UseManagedIdentity -Verbose

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox configuration and statistics for the specified mailbox
$mailboxConfig = Get-Mailbox -Identity $mailboxIdentity
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if TotalItemSize and ProhibitSendQuota are not null and extract the sizes
if ($mailboxStats.TotalItemSize -and $mailboxConfig.ProhibitSendQuota) {
    $totalSizeBytes = $mailboxStats.TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]
    $prohibitQuotaBytes = $mailboxConfig.ProhibitSendQuota.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]

    # Convert sizes from bytes to gigabytes
    $totalMailboxSize = $totalSizeBytes / 1GB
    $mailboxWarningQuota = $prohibitQuotaBytes / 1GB

    # Check if the mailbox size exceeds 90% of the warning quota
    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {

        # Retrieve SMTP credentials from Azure Automation Credential
        $smtpCredential = Get-AutomationPSCredential -Name 'SMTPCredential'

        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential $smtpCredential
    }
} else {
    Write-Host "The required values(TotalItemSize or ProhibitSendQuota) are not available."
}

 

 

 

Hi,

I am getting this now

System.Management.Automation.ParameterBindingException: A parameter cannot be found that matches parameter name 'UseManagedIdentity'.
at System.Management.Automation.CmdletParameterBinderController.VerifyArgumentsProcessed(ParameterBindingException originalBindingException)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParametersNoValidation(Collection`1 arguments)
at System.Management.Automation.CmdletParameterBinderController.BindCommandLineParameters(Collection`1 arguments)

When I use this / test:

Screenshot 2024-04-19 at 13.39.32.png

 

Screenshot 2024-04-19 at 13.37.54.png

@Minseok_Song So It seems to communicate with exchange. 

 

i did try adding the first screenshot part: 

 

$organization = "mydomain.co.uk"
Connect-ExchangeOnline -ManagedIdentity -Organization $organization
 
But same error I posted first 
 

@Minseok_Song Also looks like there is an error come this part 

 

# Check if TotalItemSize and ProhibitSendQuota are not null and extract the sizes
if ($mailboxStats.TotalItemSize -and $mailboxConfig.ProhibitSendQuota) {
$totalSizeBytes = $mailboxStats.TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]
$prohibitQuotaBytes = $mailboxConfig.ProhibitSendQuota.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]

# Convert sizes from bytes to gigabytes
$totalMailboxSize = $totalSizeBytes / 1GB
$mailboxWarningQuota = $prohibitQuotaBytes / 1GB

# Check if the mailbox size exceeds 90% of the warning quota
if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.0)) {
# Send an email notification
$emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential (Get-Credential)
}
} else {
Write-Host "The required values(TotalItemSize or ProhibitSendQuota) are not available."
}
 
As when I run

 

$organization = "mydomain.co.uk"
Connect-ExchangeOnline -ManagedIdentity -Organization $organization
# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox configuration and statistics for the specified mailbox
$mailboxConfig = Get-Mailbox -Identity $mailboxIdentity
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity
 
I get no error. 
1 best response

Accepted Solutions
best response confirmed by AB21805 (Bronze Contributor)
Solution

Hi @AB21805, I tested it on EXO V3 and here is the revised code. I found some other errors besides the existing type error, so I fixed the code in general.

I'll give you the full modified code first and explain it. The modified code works fine in my local environment.

 

 

# Connect to Exchange Online
Connect-ExchangeOnline

# Specify the user's mailbox identity
$mailboxIdentity = "email address removed for privacy reasons"

# Get mailbox configuration and statistics for the specified mailbox
$mailboxConfig = Get-Mailbox -Identity $mailboxIdentity
$mailboxStats = Get-MailboxStatistics -Identity $mailboxIdentity

# Check if TotalItemSize and ProhibitSendQuota are not null and extract the sizes
if ($mailboxStats.TotalItemSize -and $mailboxConfig.ProhibitSendQuota) {
    $totalSizeBytes = $mailboxStats.TotalItemSize.Value.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]
    $prohibitQuotaBytes = $mailboxConfig.ProhibitSendQuota.ToString().Split("(")[1].Split(" ")[0].Replace(",", "") -as [double]

    # Convert sizes from bytes to gigabytes
    $totalMailboxSize = $totalSizeBytes / 1GB
    $mailboxWarningQuota = $prohibitQuotaBytes / 1GB

    # Check if the mailbox size exceeds 90% of the warning quota
    if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.9)) {
        # Send an email notification
        $emailBody = "The mailbox $($mailboxIdentity) has reached $($totalMailboxSize) GB, which exceeds 90% of the warning quota."

        Send-MailMessage -To "email address removed for privacy reasons" -From "email address removed for privacy reasons" -Subject "Mailbox Size Warning" -Body $emailBody -SmtpServer "smtp.office365.com" -Port 587 -UseSsl -Credential (Get-Credential)
    }
} else {
    Write-Host "The required values(TotalItemSize or ProhibitSendQuota) are not available."
}

 

 

To test if the mail sending function was working, I temporarily modified the condition to if ($totalMailboxSize -ge ($mailboxWarningQuota * 0.0)).

solved.png

 

 

View solution in original post