# ############################################## # 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 ("" + ($_.Split("<>")[-5]) + ""),("" + ($_.Split("<>")[-5]) + "")} Else {$_}} $disk1 | Out-File C:\Temp\disk.tmp $gc = get-content C:\temp\disk.tmp | Measure-Object -Line If ($gc.Lines -le 4) {"

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 += 'Daily Status Report' $output += '' $output += Get-Date # Call Mailbox Stats Function write-host "Gathering Mailbox stats..." $output += '

Mailbox Size Stats

' $output += 'The following information is a summary of the # of mailboxes that are...' MailboxFunc $output += get-content C:\Temp\mbx.tmp $output += "


" # Call Hub Stats Function write-host "Gathering Message stats..." $output += '

Message Stats

' $output += 'Report of how many messages were sent and received thru Hub Transport servers yesterday ' HubStatsFunc $output += get-content C:\Temp\hub.tmp $output += "


" # Call FreeSpace Function write-host "Checking disk freespace..." $output += '

Disk Report Alerts

' $output += 'The following disk have less than 25% of free space available:' FreeSpaceFunc $output += get-content C:\Temp\disk.tmp $output += "


" # Call Mailbox Store Function write-host "Gathering Database stats..." $output += '

Database Store Information

' $output += 'Provides a summary of current mailbox database stores' StoreFunc $output += get-content C:\Temp\store.tmp $output += "


" # Call Transport Queue Function write-host "Checking SMTP queues..." $output += '

SMTP Queues

' $output += 'Show list of SMTP Queues containing more than 50 messages' GetQueue $output += get-content C:\Temp\queue.tmp $output += "


" # Call Event Log Function write-host "Collecting Event Log data..." $output += '

Event Log Data

' $output += 'Show error events generated during past 24 hours' EventFunc $output += get-content C:\Temp\event.tmp $output += "


" # Finish and call output file $output += '' $output | Out-File $OutputF -Force # ii $OutputF # Send email to Exchange Team write-host "Sending the email..." SendEmailFunc # Clean Up get-childitem c:\temp -include *.tmp -recurse | foreach ($_) {remove-item $_.fullname} # ############################################################################# # PREREQUISITES FOR SCRIPT!!!!! # 1. Line 245: Determine location to store this script and update Output file path # 2. Line 253: Create a txt file that contains a list of servers that you want to pull event log and disk information from # 3. Line 230: Update the Email Address information of who you want to send this information to # 4. Line 230: Update the SMTP server that you want to relay this message through # 5. Line 133: Modify Disk Free Space Threshold, if applicable (default is 20%) # 6. Line 198: Modify SMTP Queue Threshold, if applicable (default is 50) # 7. C:\Temp drive is used to store tmp files. If this is not sufficient, do find/replace for C:\temp