Skip to main content

Summarize MailStore growth and whitespace by Storage Group and growth exception reporting

This script takes a slightly different approach on some of the mailstore size and whitespace scripts that I've posted and a few others you may have seen posted around the traps. The great thing about scripting in the time of the WFC is that its free no budget required and the only limitation to what you can do is probably 1. your imagination 2. your skills. Given the WFC you should have much more time now to improve both (well at least the second). One of the new pressures that some admins maybe feeling in said WFC and the push towards virtulization is that the ratio of Servers to Admin is increasing so companies can at least from some perspective say they are cutting cost and raising efficacy of their IT teams.

So what does this have to do with this script well... because its a new year its a good chance to review and rethink traditional approaches. Pretty much any size reporting script you will see will look at giving you the current size of various components of your mailboxes/mailstore possible whitespace and retained items. This is where most scripters/developers stop, some may record this information in a database which is a great idea because you can then start to look at some growth trends. When you have a larger number of Servers, Stores and possibly Organizations if your a service provider just looking at recorded size information while usefull when its gets to large quantities it can be very hard for people to spot any anomalies or areas of interest that may need further investigation. Its also may lead to the discounting of such information by your more junior engineers if you can't provide a more valuable representation of the data your collecting with your scripts. The other users of this information your recording maybe your more senior managers who mostly like nice shiny reports but size reports that don't reflect the nature of change of the underlying system means its missing the point. If your size reports where written a few years ago and have had no changes since then you should get your finger out and your thinking cap on.

My approach to rewriting scripts from the traditional approach is first to make your script record historical data. The two options for doing this is firstly use a database which is a great idea because you can then use higher level reporting tools and SQL. The other option for recording historical information is using history files which is a good option where a database isn't practical which is the case for a lot of environments it also makes your scripting self contained and write once run everywhere so this is the approach I favour. To reduce information overload you should look at summarising data where you can. With this script I've summarised the size/whitespace data by Storage Group. This means if you have a large number of Storage groups spreed across a large number of servers you can a more manageable report. To do the data summerization I've use Custom objects and nested hashtables and a little bit of Math. The result of each run are written to a history file in a history directory which is used then to do exception and growth reporting.

Exception and growth reporting sounds hard but not really basically first there is some code that reads in the all the history file names that are in the history directory and then determines which file will represent the data from 1day 7days and 30days. Its then reads in each of these files into nested hashtable and index's it by combining the ServerName and StorageGroup. Then when the script runs through and builds the normal size report at the same time the current size is checked against the previous sizes and compaired against Threshold varibles. If any of the thresholds are breeched the an entry is added the the thresholds exception table.

Okay so to put all this togther into something thats usefull the script uses the Get-mailboxServer cmdlet to feed the servername of each of the mailbox servers within a Exchange Org into a function that then goes out and queries the size of the Mailbox and Public Folder Stores and then tries to use WMI to query the event logs this process is explained in a previous post. The results are combined into a HTML body of email and then the result is sent via SMTP to a mailbox (of a person who hopefully get some use from it). What gets emailed is firstly a table of all the Storage Group sizes summaries with WhiteSpace information. Then any exceptions are added after this first table. Before running the script you should set the following thresholds all sizes are in MB

$StoreSizeThreshold1day = 100
$StoreSizeThreshold7day = 300
$StoreSizeThreshold30day = 1000

$WhiteSpaceThreshold1day = 100
$WhiteSpaceThreshold7day = 300
$WhiteSpaceThreshold30day = 1000

$SMTPservername = "smtpservername"
$Toaddress = "your@ydomain.com"
$fromAddress = "Report@ydomain.com"

The script will store the history file in the c:\sizehistory directory based on this line

$HistoryDir = "c:\sizehistory"

I've put a download of this script here the script itself looks like

$StoreSizeThreshold1day = 100
$StoreSizeThreshold7day = 300
$StoreSizeThreshold30day = 1000

$WhiteSpaceThreshold1day = 100
$WhiteSpaceThreshold7day = 300
$WhiteSpaceThreshold30day = 1000

$SMTPservername = "192.168.1.45"
$Toaddress = "your@ydomain.com"
$fromAddress = "Report@ydomain.com"

function GetWSforServer($snServerName){

$SgcombCollection = @()
"Querying Server : " + $snServerName

$StoreFileSizes = @{ }
$StoreWhitespace = @{ }
$StoreRetainItemSize = @{ }
$StoreDeletedMailboxSize = @{ }
$sgTotalHash = @{ }
$hcHourCount = @{ }
$root = [ADSI]'LDAP://RootDSE'
$cfConfigRootpath = "LDAP://" + $root.ConfigurationNamingContext.tostring()
$configRoot = [ADSI]$cfConfigRootpath
$searcher = new-object System.DirectoryServices.DirectorySearcher($configRoot)
$searcher.Filter = '(&(objectCategory=msExchExchangeServer)(cn=' + $snServerName + '))'
$searchres = $searcher.FindOne()
$snServerEntry = New-Object System.DirectoryServices.directoryentry
$snServerEntry = $searchres.GetDirectoryEntry()




$adsiServer = [ADSI]('LDAP://' + $snServerEntry.DistinguishedName)
$dfsearcher = new-object System.DirectoryServices.DirectorySearcher($adsiServer)
$dfsearcher.Filter = "(objectCategory=msExchPrivateMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$sgStorageGroup = $msMailStore.psbase.Parent
if ($sgStorageGroup.msExchESEParamBaseName -ne "R00"){
$edbfile = [WMI]("\\" + $snServerName + "\root\cimv2:CIM_DataFile.Name='" + $msMailStore.msExchEDBFile + "'")
$StoreFileSize = [math]::round($edbfile.filesize/1048576,0)
$exStoreName = ($sgStorageGroup.Name.ToString() + "\" + $msMailStore.Name.ToString())
$StoreFileSizes.Add($exStoreName,$StoreFileSize)
}
}
"Finshed Mailstores"
$dfsearcher.Filter = "(objectCategory=msExchPublicMDB)"
$srSearchResults = $dfsearcher.FindAll()
foreach ($srSearchResult in $srSearchResults){
$msMailStore = $srSearchResult.GetDirectoryEntry()
$sgStorageGroup = $msMailStore.psbase.Parent
if ($sgStorageGroup.msExchESEParamBaseName -ne "R00"){
$edbfile = [WMI]("\\" + $snServerName + "\root\cimv2:CIM_DataFile.Name='" + $msMailStore.msExchEDBFile + "'")
$StoreFileSize = [math]::round($edbfile.filesize/1048576,0)
$exStoreName = ($sgStorageGroup.Name.ToString() + "\" + $msMailStore.Name.ToString())
$StoreFileSizes.Add($exStoreName,$StoreFileSize)
}
}
"Finshed Public Folder Stores"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1221' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$esEndString = $mbnamearray[2].indexof("megabytes ")-6
if ($StoreWhitespace.Containskey($mbnamearray[1]) -eq $false){
$StoreWhitespace.Add($mbnamearray[1],$mbnamearray[2].Substring(5,$esEndString))
}
}
"Finished WhiteSpace"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '1207' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$enditem = $mbnamearray[2].Substring($mbnamearray[2].indexof("End:"))
$esize = $enditem.SubString($enditem.indexof("items")+7,$enditem.indexof(" Kbytes")-($enditem.indexof("items")+7))
if ($StoreRetainItemSize.Containskey($mbnamearray[1]) -eq $false){
$StoreRetainItemSize.Add($mbnamearray[1],[math]::round(($esize/1024),0))
}

}
"Finshed Retained Items"
$WmidtQueryDT = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime([DateTime]::UtcNow.AddDays(-3))
Get-WmiObject -computer $snServerName -query ("Select * from Win32_NTLogEvent Where Logfile='Application' and Eventcode = '9535' and TimeWritten >='" + $WmidtQueryDT + "'") | sort $_.TimeWritten -Descending |
foreach-object{
$mbnamearray = $_.message.split("`"")
$retMbs = $mbnamearray[2].Substring($mbnamearray[2].indexof("have been removed."))
$retMbsSize = $retMbs.Substring(($retMbs.indexof("(")+1),$retMbs.indexof(")")-($retMbs.indexof("(")+1)).Replace(" KB","")
if ($StoreDeletedMailboxSize.Containskey($mbnamearray[1]) -eq $false){
$StoreDeletedMailboxSize.Add($mbnamearray[1],[math]::round(($retMbsSize/1024),0))
}

}
$StoreFileSizes.GetEnumerator() | sort name -descending | foreach-object {
$snames = $_.key.split("\")
if ($sgTotalHash.containsKey($snames[0])){
if ($StoreDeletedMailboxSize.containskey($_.key)){
$sgTotalHash[$snames[0]].MailboxStores = [int]$sgTotalHash[$snames[0]].MailboxStores + 1
$sgTotalHash[$snames[0]].MSSize = [int]$sgTotalHash[$snames[0]].MSSize + [int]$_.Value
$sgTotalHash[$snames[0]].MSWhiteSpace = [int]$sgTotalHash[$snames[0]].MSWhiteSpace + [int]$StoreWhitespace[$_.key].ToString()
$sgTotalHash[$snames[0]].MSRetainedItems = [int]$sgTotalHash[$snames[0]].RetainedItems + [int]$StoreRetainItemSize[$_.key].ToString()
$sgTotalHash[$snames[0]].RetainedMB = [int]$sgTotalHash[$snames[0]].RetainedMB + [int]$StoreDeletedMailboxSize[$_.key].ToString()

}
else{
$sgTotalHash[$snames[0]].PublicFolderStores = [int]$sgTotalHash[$snames[0]].MailboxStores + 1
$sgTotalHash[$snames[0]].PFSize = [int]$sgTotalHash[$snames[0]].MSSize + [int]$_.Value
$sgTotalHash[$snames[0]].PFWhiteSpace = [int]$sgTotalHash[$snames[0]].MSWhiteSpace + [int]$StoreWhitespace[$_.key].ToString()
$sgTotalHash[$snames[0]].PFRetainedItems = [int]$sgTotalHash[$snames[0]].RetainedItems + [int]$StoreRetainItemSize[$_.key].ToString()

}

}
else{
$sgtotalObject = "" | select ServerName,Name,MailboxStores,PublicFolderStores,MSSize,PFSize,MSWhiteSpace,PFWhiteSpace,MSRetainedItems,PFRetainedItems,RetainedMB
$sgtotalObject.ServerName = $snServerName
$sgtotalObject.Name = $snames[0]
if ($StoreDeletedMailboxSize.containskey($_.key)){
$sgtotalObject.MailboxStores = 1
$sgtotalObject.PublicFolderStores = 0
$sgtotalObject.MSSize = $_.Value.ToString()
$sgtotalObject.PFSize = 0
$sgtotalObject.MSWhiteSpace = $StoreWhitespace[$_.key].ToString()
$sgtotalObject.PFWhiteSpace = 0
$sgtotalObject.MSRetainedItems = $StoreRetainItemSize[$_.key].ToString()
$sgtotalObject.PFRetainedItems = 0
$sgtotalObject.RetainedMB = $StoreDeletedMailboxSize[$_.key].ToString()
}
else {
$sgtotalObject.MailboxStores = 0
$sgtotalObject.PublicFolderStores = 1
$sgtotalObject.MSSize = 0
$sgtotalObject.PFSize = $_.Value.ToString()
$sgtotalObject.MSWhiteSpace = 0
$sgtotalObject.PFWhiteSpace = $StoreWhitespace[$_.key].ToString()
$sgtotalObject.MSRetainedItems = 0
$sgtotalObject.PFRetainedItems = $StoreRetainItemSize[$_.key].ToString()
$sgtotalObject.RetainedMB = 0
}

$sgTotalHash.Add($snames[0],$sgtotalObject)
}

}



foreach ($row in $sgTotalHash.Values){
$global:rpReport = $global:rpReport + " <tr>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $snServerName + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.Name.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MailboxStores.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PublicFolderStores.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSSize.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFSize.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSWhiteSpace.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFWhiteSpace.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.MSRetainedItems.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.PFRetainedItems.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "<td>" + $row.RetainedMB.ToString() + "</td>" + "`r`n"
$global:rpReport = $global:rpReport + "</tr>" + "`r`n"
$global:ExcombCollection += $row
if ($onedaystats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold1day){
writeThresholdExecption "One Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $onedaystats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold1day){
writeThresholdExecption "One Day PublicStore Size" $snServerName $row.Name.ToString() $row.PFSize $onedaystats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold1day){
writeThresholdExecption "One Day Mail Store WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $onedaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$onedaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold1day){
writeThresholdExecption "One Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $onedaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}

}
if ($onedaystats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold7day){
writeThresholdExecption "Seven Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold7day){
writeThresholdExecption "Seven Day Public Store Size" $snServerName $row.Name.ToString() $row.PFSize $sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold7day){
writeThresholdExecption "Seven Day Mail Store WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $sevendaystats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold7day){
writeThresholdExecption "Seven Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $sevendaystats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}
}
if ($onemonthsstats.Containskey(($snServerName + "\" + $row.Name.ToString()))){
$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize
if(([INT]$row.MSSize - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize) -gt $StoreSizeThreshold30day){
writeThresholdExecption "Thirty Day MailStore Size" $snServerName $row.Name.ToString() $row.MSSize $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSSize.ToString()
}
if(([INT]$row.PFSize - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFSize) -gt $StoreSizeThreshold30day){
writeThresholdExecption "Thirty Day Public Store Size" $snServerName $row.Name.ToString() $row.PFSize $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFSize.ToString()
}
if(([INT]$row.MSWhiteSpace - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace) -gt $WhiteSpaceThreshold30day){
writeThresholdExecption "Thirty Day MailStore WhiteSpace" $snServerName $row.Name.ToString() $row.MSWhiteSpace $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].MSWhiteSpace.ToString()
}
if(([INT]$row.PFWhiteSpace - [INT]$onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace) -gt $WhiteSpaceThreshold30day){
writeThresholdExecption "Thirty Day Public Store WhiteSpace" $snServerName $row.Name.ToString() $row.PFWhiteSpace $onemonthsstats[($snServerName + "\" + $row.Name.ToString())].PFWhiteSpace.ToString()
}
}
}


}

function writeThresholdExecption([String]$threshold,[String]$tsServerName,[String]$tsSGName,[String]$tscValue,[String]$tspValue) {
$global:expReport = $global:expReport + " <tr>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $threshold + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tsServerName + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tsSGName + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tscValue + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + $tspValue + "</td>" +"`r`n"
$global:expReport = $global:expReport + "<td>" + ([INT]$tscValue - [INT]$tspValue) + "</td>" +"`r`n"
$global:expReport = $global:expReport + "</tr>" + "`r`n"

}



$HistoryDir = "c:\sizehistory"

if (!(Test-Path -path $HistoryDir))
{
New-Item $HistoryDir -type directory
}
$global:rpReport = ""
$global:expReport = ""
$global:rpReport = $global:rpReport + "<table><tr bgcolor=`"#95aedc`">" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>ServerName</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:15%;`" ><b>SG Name</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:5%;`" ><b>MS #</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:5%;`" ><b>PFS #</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MS Size</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PF Size</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MSWSpace</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PFWpace</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>MSRetItems</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>PFRetItems</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "<td align=`"center`" style=`"width:10%;`" ><b>RetMB</b></td>" +"`r`n"
$global:rpReport = $global:rpReport + "</tr>" + "`r`n"
$global:expReport = $global:expReport + "<table><tr bgcolor=`"#95aedc`">" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>Threshold</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>ServerName</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:15%;`" ><b>SGName</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Current Value</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Previous Value</b></td>" +"`r`n"
$global:expReport = $global:expReport + "<td align=`"center`" style=`"width:10%;`" ><b>Growth</b></td>" +"`r`n"
$global:expReport = $global:expReport + "</tr>" + "`r`n"
$global:ExcombCollection = @()
$datetime = get-date
$arArrayList = New-Object System.Collections.ArrayList
dir $script:HistoryDir\*.csv | foreach-object{
$fname = $_.name
$nmArray = $_.name.split("-")
[VOID]$arArrayList.Add($nmArray[0])
}
$arArrayList.Sort()
$spoint = $arArrayList[$arArrayList.Count-1]
$oneday = $spoint
$sevenday = $spoint
$onemonth = $spoint
$oneyear = $spoint
foreach ($file in $arArrayList){
if ($file -gt ($datetime.Adddays(-2).ToString("yyyyMMdd")) -band $file -lt $oneday) {$oneday = $file}
if ($file -gt ($datetime.Adddays(-7).ToString("yyyyMMdd")) -band $file -lt $sevenday) {$sevenday = $file}
if ($file -gt ($datetime.Adddays(-31).ToString("yyyyMMdd")) -band $file -lt $onemonth) {$onemonth = $file}
}

$onedaystats = @{ }
$sevendaystats = @{ }
$onemonthsstats = @{ }
$oneyearstats = @{ }

Import-Csv ("$script:HistoryDir\" + $oneday + "-wspacerun.csv") | %{
$onedaystats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}
Import-Csv ("$script:HistoryDir\" + $sevenday + "-wspacerun.csv") | %{
$sevendaystats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}
Import-Csv ("$script:HistoryDir\" + $onemonth + "-wspacerun.csv") | %{
$onemonthsstats.add(($_.ServerName.ToString() + "\" + $_.Name.ToString()),$_)
}


Get-MailboxServer | foreach-object{
GetWSforServer($_.Name.ToString())
}
$datetime = get-date
$fname = $script:HistoryDir + "\"
$fname = $fname + $datetime.ToString("yyyyMMdd") + "-wspacerun.csv"
$global:ExcombCollection | export-csv –encoding "unicode" -noTypeInformation $fname
$global:rpReport = $global:rpReport + "</table>" + " <BR><BR><H1>Threshold Exceeds</H1><BR> "
$global:rpReport = $global:rpReport + $global:expReport
$global:rpReport = $global:rpReport + "</table>" + " <BR><BR> "

$SmtpClient = new-object system.net.mail.smtpClient
$SmtpClient.host = $SMTPservername
$MailMessage = new-object System.Net.Mail.MailMessage
$MailMessage.To.Add($ToAddress)
$MailMessage.From = $FromAddress
$MailMessage.Subject = "Storage Group Reports"
$MailMessage.IsBodyHtml = $TRUE
$MailMessage.body = $global:rpReport
$SMTPClient.Send($MailMessage)
write-host "Mail Sent"

Popular posts from this blog

Testing and Sending email via SMTP using Opportunistic TLS and oAuth in Office365 with PowerShell

As well as EWS and Remote PowerShell (RPS) other mail protocols POP3, IMAP and SMTP have had OAuth authentication enabled in Exchange Online (Official announcement here ). A while ago I created  this script that used Opportunistic TLS to perform a Telnet style test against a SMTP server using SMTP AUTH. Now that oAuth authentication has been enabled in office365 I've updated this script to be able to use oAuth instead of SMTP Auth to test against Office365. I've also included a function to actually send a Message. Token Acquisition  To Send a Mail using oAuth you first need to get an Access token from Azure AD there are plenty of ways of doing this in PowerShell. You could use a library like MSAL or ADAL (just google your favoured method) or use a library less approach which I've included with this script . Whatever way you do this you need to make sure that your application registration  https://docs.microsoft.com/en-us/azure/active-directory/develop/quickstart-register-

How to test SMTP using Opportunistic TLS with Powershell and grab the public certificate a SMTP server is using

Most email services these day employ Opportunistic TLS when trying to send Messages which means that wherever possible the Messages will be encrypted rather then the plain text legacy of SMTP.  This method was defined in RFC 3207 "SMTP Service Extension for Secure SMTP over Transport Layer Security" and  there's a quite a good explanation of Opportunistic TLS on Wikipedia  https://en.wikipedia.org/wiki/Opportunistic_TLS .  This is used for both Server to Server (eg MTA to MTA) and Client to server (Eg a Message client like Outlook which acts as a MSA) the later being generally Authenticated. Basically it allows you to have a normal plain text SMTP conversation that is then upgraded to TLS using the STARTTLS verb. Not all servers will support this verb so if its not supported then a message is just sent as Plain text. TLS relies on PKI certificates and the administrative issue s that come around certificate management like expired certificates which is why I wrote th

The MailboxConcurrency limit and using Batching in the Microsoft Graph API

If your getting an error such as Application is over its MailboxConcurrency limit while using the Microsoft Graph API this post may help you understand why. Background   The Mailbox  concurrency limit when your using the Graph API is 4 as per https://docs.microsoft.com/en-us/graph/throttling#outlook-service-limits . This is evaluated for each app ID and mailbox combination so this means you can have different apps running under the same credentials and the poor behavior of one won't cause the other to be throttled. If you compared that to EWS you could have up to 27 concurrent connections but they are shared across all apps on a first come first served basis. Batching Batching in the Graph API is a way of combining multiple requests into a single HTTP request. Batching in the Exchange Mail API's EWS and MAPI has been around for a long time and its common, for email Apps to process large numbers of smaller items for a variety of reasons.  Batching in the Graph is limited to a m
All sample scripts and source code is provided by for illustrative purposes only. All examples are untested in different environments and therefore, I cannot guarantee or imply reliability, serviceability, or function of these programs.

All code contained herein is provided to you "AS IS" without any warranties of any kind. The implied warranties of non-infringement, merchantability and fitness for a particular purpose are expressly disclaimed.