Please help with big Mailbox report out to HTML and Email

by toybits at 2013-02-21 06:32:26

Hi all,

This is a long one so sorry and thanks for looking.

I need to provide a daily report of mailboxes over 550Mb (we have 24000 mailboxes) sorted largest to smallest. I’ve written the code below to do this. The html output and the email works fine. However only when I run it against one database. I used the body1 variable with a view to being able to add more body elements later. Not sure if this is the best way to do this?

I did that for testing purposes because it takes far less time (only 250 odd mailboxes per database). But when I run it against all 144 databases, it dies with the following error.

Sending data to a remote command failed with the following error message:

Deserialized objects exceed the memory quota.

For more information, see the about_Remote_Troubleshooting Help topic.
+ CategoryInfo : OperationStopped: (System.Manageme…pressionSyncJob:PSInvokeExpressionSyncJob) , PSRe
motingTransportException
+ FullyQualifiedErrorId : JobFailure

Invoke-Command : Cannot write input as there are no more running pipelines
At C:\Users\a-scomcgrath\AppData\Roaming\Microsoft\Exchange\RemotePowerShell\ <CAS Server Name in here > 1:14037 char:29
+ $scriptCmd = { & <<<< $script:InvokeCommand <br> + CategoryInfo : InvalidOperation: (:) [Invoke-Command], PSInvalidOperationException<br> + FullyQualifiedErrorId : NoMoreInputWrite,Microsoft.PowerShell.Commands.InvokeCommandCommand<br><br><br><br>I have two questions (See script below).<br><br>1. Anyone better than me with PowerShell, which is probably most of you, any comments would be very appreciated on how I could have done it better.<br>2. Could be a by-product of the first question, but anyone know why I'm getting the error? I'm guessing it's something to do with the order I'm instantiating the variables.<br>3. Any results that are over their quota, I'd like to colour red. Any ideas how to do that.<br><br>As a P.S. but don't want to overstay my welcome ;) but anyone know how to get it to ignore empty (i.e. new Mailboxes) so it doesn't warn that someone needs to log on to the mailbox before the Get-MailboxStatistics cmdlet will work. Not that necessary just might be handy to know. <br><br>Thanks in advance for your help.<br><br>#################################################################<br>#Mailbox Report #<br>#Author - Scott McGrath #<br>#2012 #<br>#Generates a Mailbox Report mailbox Report #<br>#################################################################<br><br>#Variables<br>$mailboxDatabases = Get-MailboxDatabase UK-MBX* #If I change this to a database, instead of a wild card for all DB's it works fine.<br>$mailboxes = $mailboxDatabases | Get-Mailbox -ResultSize Unlimited<br>$mbtoobig = $mailboxes | Get-MailboxStatistics | Where{$_.TotalItemSize -gt 550Mb} | Sort-Object TotalItemSize -Descending<br><br>$bodyObj=@()<br><br> $mailbox = $mbtoobig | Get-Mailbox<br> $mailbox | foreach-object{<br> $DisplayName=$_.DisplayName<br> $SmtpAddress=$_.PrimarySmtpAddress<br> $Office=$_.Office<br> $IssueWarningQuota=$_.IssueWarningQuota.Value.ToMB()<br> $ProhibitSendQuota=$_.ProhibitSendQuota.Value.ToMB()<br> $TotalMailboxsize=(get-mailboxstatistics –identity $DisplayName ).TotalITemSize.Value.ToMB()<br> $StorageLimitStatus=(get-mailboxstatistics –identity $DisplayName ).StorageLimitStatus<br> $LastLogonTime=(get-mailboxstatistics -identity $DisplayName ).LastLogonTime<br> $Telephone = (Get-User -Identity $_.Name).Phone<br> <br>$body1 = new-object System.Object<br>$body1 | Add-Member -membertype NoteProperty -name &quot;Display Name&quot; -value $DisplayName<br>$body1 | Add-Member -membertype NoteProperty -name &quot;Email Address&quot; -value $SmtpAddress<br>$body1 | Add-Member -MemberType NoteProperty -Name &quot;Phone&quot; -Value $Telephone<br>$body1 | Add-Member -membertype NoteProperty -name &quot;Office Location&quot; -value $Office<br>$body1 | Add-Member -membertype NoteProperty -name &quot;IssueWarning&quot; -value $IssueWarningQuota<br>$body1 | Add-Member -membertype NoteProperty -name &quot;ProhibitSend&quot; -value $ProhibitSendQuota<br>$body1 | Add-Member -membertype NoteProperty -name &quot;Mailbox Size&quot; -value $TotalMailboxSize<br>$body1 | Add-Member -membertype NoteProperty -name &quot;Limit Status&quot; -value $StorageLimitStatus<br>$body1 | Add-Member -membertype NoteProperty -name &quot;LastLogonTime&quot; -value $LastLogonTime<br><br>$bodyObj += $body1<br>}<br><br>$html = $bodyObj | ConvertTo-Html
-Title "Exchange Mailbox Size Report"<br> -Head &quot;&lt;style&gt; body {background-color: #1B3277; font-family: Arial ; font-size: 9 } h1 {font-famly:Arial ; font-size : 14 ; color:#9ACD66 ; padding: 7px ; margin: 5px} table {background-color: white ; margin: 5px; display: inline-block; padding: 5px; border: 1px solid black} tr:nth-child(odd){background-color: lightgray}&lt;/style&gt;&quot;
-Body "<h1>Large mailbox report</h1>"

$html | Out-File c:\Temp\ExchangeReport.html

$emailBody = $html | Out-String

$recipients = "scomcgrath@mydomain.co.uk"

Send-MailMessage -To $recipients -From "scomcgrath@mydomain.co.uk" -SmtpServer my.smtpserver.com -Subject "Exchange Report" -BodyAsHtml:$true -Body $emailBody
by Slashj at 2013-02-21 08:03:58
Hi,

i didnt read it completly due to not having that much time, but i guess that this might help you.

Ive seen this line "$mailboxDatabases = Get-MailboxDatabase UK-MBX* #If I change this to a database, instead of a wild card for all DB’s it works fine."

My question is, if it is working with one database only and not with the wildcard, why dont u take all database names into 1 variable and then run this script for each database name in the variable.

To be clear i mean this:

get-content "listofdatabases.txt" | %{
$mailboxdatabases = get-mailboxdatabase $($) # So now you only get 1 Database at the time instead of all directly
Run the rest of your script
}

As said, i didn read your whole script so i might be wrong here, but if your problem occured only cause you took all databases at once, then this should help i guess.

BR
by nate-n8 at 2013-02-23 21:41:32
You can run Get-MailboxStatistics against DB’s instead of each mailbox (i believe your doing double the work and this should be quicker). You should get the same results. So instead of opening the script with the first 3 variables, use only this:

$mbtoobig = Get-MailboxDatabase -id * | Get-MailboxStatistics | Where{$
.TotalItemSize -gt 550Mb} | Sort-Object TotalItemSize -Descending

if you get warning cause they havent logged in, use: Get-MailboxStatistics -WarningAction SilentlyContinue
by Takuu at 2013-02-25 06:41:50
It looks like those two above posts should be able to resolve your problems. Any luck there?