# ##############################################
# Author: Doug Blanchard
# Description: This report pulls various information about the Messaging Environment and email the report to the operations team
# Tasks include: Backup Status, Mail Queues over 100 msgs, Free Disk Space under 30%, Errors/Warnings generated past 24 hours,
# Mailbox DB Report, Cluster Status Report
# Security: You may need to run [ Set-ExecutionPolicy Unrestricted ] prior to running this script
# Usage: no arguments needed
# Prerequisites: See PreRequisites section at bottom of script
# Version Control - 2010517_1300_djb
# ##############################################
$error.clear()
$warningpreference = "silentlycontinue"
# ########################################
# List all Functions to be Used in Script
# ########################################
# ~~~~~~~~~~~~~~~~~~~~~~~~
# Mailbox Size Summary Function
# ~~~~~~~~~~~~~~~~~~~~~~~~
Function MailboxFunc
{
$TotalMbx = Get-Mailbox -ResultSize Unlimited | Where {$_.Displayname -notlike "SystemMailbox*"} | Measure-Object
$Nolimit = Get-MailboxServer | Get-MailboxStatistics | Where {$_.StorageLimitStatus -eq "NoChecking"} | Measure-Object
$Overlimit = Get-MailboxServer | Get-MailboxStatistics | Where {$_.StorageLimitStatus -eq "MailboxDisabled"} | Measure-Object
$2_5GBMBX = Get-MailboxServer | Get-MailboxStatistics | Where {$_.TotalItemSize -ge 2GB -and $_.TotalItemSize -le 5GB} | Measure-Object
$5GBMBX = Get-MailboxServer | Get-MailboxStatistics | Where {$_.TotalItemSize -ge 5GB} | Measure-Object
$obj = New-Object PSObject
$obj | Add-Member NoteProperty -Name "Total # of
Mailboxes" -Value $TotalMbx.count
$obj | Add-Member NoteProperty -Name "# of Mbx
No Quota Set" -Value $Nolimit.count
$obj | Add-Member NoteProperty -Name "# of Mbx
Over Quota" -Value $Overlimit.count
$obj | Add-Member NoteProperty -Name "# of Mbx
Between 2GB-5GB" -Value $2_5GBMBX.count
$obj | Add-Member NoteProperty -Name "# of Mbx
Greater than 5GB" -Value $5GBMBX.count
$obj | ConvertTo-Html | Out-File C:\Temp\mbx.tmp
}
# End Mailbox Summary Function
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~
# Hub Transport Stats Function
# ~~~~~~~~~~~~~~~~~~~~~~~~
# Pulls # of messages sent, received, and NDR per hub transport server
# Based on data pulled from http://gsexdev.blogspot.com/2010/05/quck-smtp-bandwidth-usage-script-for.html
Function HubStatsFunc
{
$date = ((get-date).AddHours(-24).ToString('yyyy/MM/dd'))
$start = $date+ " 00:00:00"
$end = $date+ " 23:59:59"
$HubSrv = @()
$DomainHash = @{}
$msgIDArray = @{}
get-accepteddomain | ForEach-Object {
if ($_.DomainType -eq "Authoritative")
{$DomainHash.add($_.DomainName.SmtpDomain.ToString().ToLower(),1)}
}
$hub = get-transportserver | Select Name
foreach ($item in $hub)
{
Get-MessageTrackingLog -server $item.Name -ResultSize Unlimited -Start $start -End $end | ForEach-Object{
if ($_.EventID.ToString() -eq "SEND" -bor $_.EventID.ToString() -eq "RECEIVE")
{foreach($recp in $_.recipients)
{if($recp.ToString() -ne "")
{$unkey = $recp.ToString() + $_.Sender.ToString() + $_.MessageId.ToString()
if ($msgIDArray.ContainsKey($unkey) -eq $false){
$msgIDArray.Add($unkey,1)
$recparray = $recp.split("@")
$sndArray = $_.Sender.split("@")
if ($_.Sender -ne ""){
if ($DomainHash.ContainsKey($recparray[1])){
if ($DomainHash.ContainsKey($sndArray[1])){
$InternalNum = $InternalNum + 1
$InternalSize = $InternalSize + $_.TotalBytes/1024
}
else{
$ExternalRecNum = $ExternalRecNum + 1
$ExternalRecSize = $ExternalRecSize + $_.TotalBytes/1024
}
}
else{
if ($DomainHash.ContainsKey($sndArray[1])){
$ExternalSentNum = $ExternalSentNum + 1
$ExternalSentSize = $ExternalSentSize + $_.TotalBytes/1024
}
}
}
}
}
}
}
}
$GetDSN = Get-MessageTrackingLog -server $item.Name -EventID DSN -resultSize unlimited | Measure-Object
$obj = New-Object PSObject
$Obj | Add-Member NoteProperty -Name "Server" -Value $item.Name
$Obj | Add-Member NoteProperty -Name "# Msg Sent/Rcvd
Internal" -Value $InternalNum
$Obj | Add-Member NoteProperty -Name "# Msg Sent
Internet" -Value $ExternalSentNum
$Obj | Add-Member NoteProperty -Name "# Msg Rcvd
Internet" -Value $ExternalRecNum
$Obj | Add-Member NoteProperty -Name "Msg Sent/Rcvd (MB)
Internal" -Value ([math]::round($InternalSize/1024,0))
$Obj | Add-Member NoteProperty -Name "Msg Sent (MB)
Internet" -Value ([math]::round($ExternalSentSize/1024,0))
$Obj | Add-Member NoteProperty -Name "Msg Rcvd (MB)
Internet" -Value ([math]::round($ExternalRecSize/1024,0))
$Obj | Add-Member NoteProperty -Name "Total #
of DSN" -Value $GetDSN.count
$HubSrv += $Obj
}
$HubSrv | ConvertTo-Html | Out-File C:\Temp\hub.tmp
}
# End Hub Transport Stats Function
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Disk FreeSpace Status Function
# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
# Identifies those volumes (either physical or mount points) who have less than 20% free space available
Function FreeSpaceFunc
{
$diskout = @()
ForEach ($Srv in $online)
{
$disks = gwmi -class "win32_volume" -namespace "root/cimv2" -computername $srv | Select SystemName,Name,Capacity,FreeSpace | Sort Freespace
ForEach ($drv in $disks)
{
$size = "{0:n2}" -f ($drv.capacity / 1GB)
$free = "{0:n2}" -f ($drv.FreeSpace / 1GB)
$Pfree = "{0:P2}" -f ($free/$size)
$check = $Pfree -le 20
If ($check -eq "True")
{
$obj = New-Object PSObject
$obj | Add-Member Noteproperty "Server Name" -Value $drv.systemName
$obj | Add-Member Noteproperty "Drive Letter" -Value $drv.Name
$obj | Add-Member Noteproperty "Free Space(GB)" -Value ($drv.Freespace/1GB -as [int])
$obj | Add-Member Noteproperty "% Free" -Value (([double]$drv.freespace/[double]$drv.capacity)*100 -as [int])
$diskout += $obj
}
}
}
$disk1 = $diskout | ConvertTo-Html -Fragment
$threshhold = 15
$disk1 = $disk1 | ForEach-Object{If (($_.Split("<>")[-5]) -le $threshhold) {$_ -replace ("
No Drives were found to be under 20%
" | Out-File C:\Temp\disk.tmp} } # End Disk FreeSpace Status Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~ # Mailbox Store Function # ~~~~~~~~~~~~~~~~~~~~~~~~ # Pulls mailbox store information Function StoreFunc { $MBXSrv = get-mailboxserver $MBXOutput = @() foreach ($server in $MBXSrv) { $db = Get-MailboxDatabase -server $server -status | where {$_.Recovery -ne 'False'} foreach ($objItem in $db) { $edbpath = $objItem.edbfilepath $edbfile = get-wmiobject cim_datafile -computername $server -filter ('name=''' + $edbpath.pathname.replace("\","\\") + '''') $edbSize = [math]::Round([Decimal]( $edbfile.filesize / 1GB),2) $mailboxcount = Get-MailboxStatistics -database $objItem |measure-object $obj = New-Object PSObject $obj | Add-Member NoteProperty -Name "Server" -Value $objItem.Server $obj | Add-Member NoteProperty -Name "Database" -Value $objItem.Name $obj | Add-Member NoteProperty -Name "Size (GB)" -Value $edbSize $obj | Add-Member NoteProperty -Name "Mailbox Count" -Value $mailboxcount.count $obj | Add-Member NoteProperty -Name "Last Backup" -Value $objItem.LastFullBackup $obj | Add-Member NoteProperty -Name "Is Mounted?" -Value $objItem.Mounted $obj | Add-Member NoteProperty -Name "Drive" -Value $edbpath.DriveName $MBXOutput += $obj } } $MBXOutput | ConvertTo-Html | Out-File C:\Temp\store.tmp } # End Mailbox Store Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # Transport Queue Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # List those SMTP Queues that have more than 50 messages Function GetQueue { $getqueue = Get-TransportServer | get-queue -erroraction silentlycontinue | Where {$_.MessageCount -ge 50} | Select Identity,Status,MessageCount,LastError,LastRetryTime,NextRetryTime |Sort MessageCount If ($GetQueue -eq $Null) {"No backed up queues were found
" | Out-File C:\Temp\queue.tmp} Else {$GetQueue | Convertto-HTML | Out-File C:\Temp\queue.tmp} } # End Transport Queue Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~ # Event Log Function # ~~~~~~~~~~~~~~~~~~~~~~~~ # List Error Event information from Event Logs that were generated during past 24hours Function EventFunc { $time = [System.Management.ManagementDateTimeConverter]::ToDmtfDateTime((Get-Date).AddHours(-24)) get-content $Tmp | ForEach-Object { Get-WmiObject win32_NTLogEvent -computerName $_ -filter "EventType=1 and TimeGenerated>='$time'" } | Select-Object __SERVER, LogFile, Type, EventCode, SourceName, CategoryString -Unique | ConvertTo-Html | Out-File C:\Temp\event.tmp } # End Event Log Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ~~~~~~~~~~~~~~~~~~~~~~~~ # Send Email Function # ~~~~~~~~~~~~~~~~~~~~~~~~ # Sends the output file to the administrator Function SendEmailFunc { $body = get-content $outputF | ForEach-Object {$fullstring = ""} {$fullstring += $_} {$fullstring} $subj = "Daily Messaging Status Report - " +$(Get-Date -Uformat %D) send-mailmessage -from "Script@domain.local" -to "Administrator@mylab.local" -subject $subj -BodyAsHtml $body -attachment $OutputF -smtpServer localhost } # End Send Email Function # ~~~~~~~~~~~~~~~~~~~~~~~~~~~ # ############################# # Powershell Script Starts Here # ############################# # Create Directory, Tmp, & Output File # $dirname = "C:\Temp\$(Get-Date -format 'yyyyMMdd')" # New-Item $dirname -itemType directory | out-null $OutputF = "C:\Temp\DailyReport_$(Get-Date -format 'yyyyMMdd').html" New-Item $OutputF -itemType file | out-null $Tmp = "C:\temp\$(Get-Date -format 'yyyyMMdd').tmp" If(test-path $Tmp -pathtype leaf){remove-item -path $Tmp -force} ELSE {New-Item $Tmp -itemType file | out-null} # Get Server List $Svrname = get-content C:\Temp\Servers.txt # Check Each Server is Reachable foreach ($a in $Svrname) {$p = test-path "\\$a\c$" if ($p -eq "True"){$a | out-file $Tmp -append} } # Set new variable for reachable servers $online = get-content $Tmp # Create Array for HTML Output $output = @() $output += '