Behold the power of Get-MailboxFolderStatistics

Not too long ago, I received a ticket from a user who was having quota issues and could not account for what was using up their Exchange quota. With a simple Exchange Management Shell one-liner, I was able to provide a list of every folder in that user’s mailbox, the number of items in each folder, and size of the folder contents:









[PS] E:\working\scripts>Get-MailboxFolderStatistics jane.user | sort-object item
sinfolder -descending | ft Name, FolderPath, ItemsInFolder, FolderSize -auto

Name                     FolderPath     ItemsInFolder FolderSize
----                     ----------     ------------- ----------
Inbox                    /Inbox                    33 103574B
Calendar                 /Calendar                 25 64012B
Deleted Items            /Deleted Items             7 9101B
Sent Items               /Sent Items                6 7690B
Notes                    /Notes                     0 0B
Outbox                   /Outbox                    0 0B
Tasks                    /Tasks                     0 0B
RSS Feeds                /RSS Feeds                 0 0B
Contacts                 /Contacts                  0 0B
Top of Information Store /                          0 0B
Drafts                   /Drafts                    0 0B
Junk E-Mail              /Junk E-Mail               0 0B
Journal                  /Journal                   0 0B

But wait, there’s more. As mentioned in my previous article, I’ve encountered issues with folders which have leading or trailing whitespace in their name. Sure enough, I was able to crank out a simple one-liner to list all  folders possessing this defect:

[PS] E:\working\scripts>get-mailbox -resultsize unlimited | Get-MailboxFolderSta
tistics | where {($_.Name -like "* ") -or ($_.Name -like " *")} | fl Name,Identi
ty,FolderPath
[PS] E:\working\scripts>get-mailbox -resultsize unlimited | Get-MailboxFolderSta tistics | where {($_.Name -like "* ") -or ($_.Name -like " *")} | fl Name,Identi ty,FolderPath

Addition in PowerShell

In general, PowerShell is able to detect when a mathematical operation is being performed and convert strings on the fly to permit this:

PS C:\> $x = 10 + “20”
PS C:\> $x
30

However, there are cases where this does not always work as expected:

PS C:\> $x = “1000”
PS C:\> $y = $x + 500
PS C:\> $y
1000500

As you can see, instead of converting the value of $x to an integer and performing the expected addition, it simply treated the entire command as a string concatenation operation. Note, however, that subtraction works just fine:

PS C:\> $z = $x – 500
PS C:\> $z
500

Knowing this, combined with the fact that subtracting the negative of a value is the same as adding the value, we have a workaround:

PS C:\> $y = $x – (-500)
PS C:\> $y
1500

A more straightforward solution, however, is to force PowerShell to treat our variable as an integer:

PS C:\> $y = [int]$x + 500
PS C:\> $y
1500

Using EMS to enumerate the e-mail addresses of Distribution Group members

The magic mojo for listing the SMTP addresses of all members of a Distribution Group is as follows:

Get-DistributionGroupMember “My Distribution Group Name” | ForEach {$_.PrimarySMTPAddress.ToSTring()}

Invocation of the ToString() method is necessary since the PrimarySMTPAddress property contains objects with separate properties for the address length, the portion of the address before the @, the domain, and a Boolean specifying whether or not the address is valid.

Using the EWS Managed API via PowerShell

As part of the rollout of the Exchange 2010 beta, Microsoft has released a beta API library for working with Exchange Web Services which can also be used in conjunction with an Exchange 2007 server. As with any .NET library, this can be invoked from PowerShell. There is an example here of retrieving the number of unread messages in the Inbox, as well as some attributes from the last message received. Unfortunately, the API documentation doesn’t give PowerShell examples, so figuring out how to invoke the calls requires a bit of trial and error. Here is a script I cobbled together which simply sends an email message:
Continue reading

Fun With Custom PSObjects

I was recently asked to generate a report on mailbox usage by a specific subset of AEMS users.  The tricky part is that the various pieces of info that I need are returned by two distinct Exchange Management Shell commands.  In order to merge properties from two different returned objects, I found it expedient to tack the values from those properties into a new PSObject:

#initializing an array to hold the constructed PSObjects
[array]$users = $null          

#  iterate through all members of myGroup
Get-DistributionGroupMember “myGroup” | ForEach-Object {    
# some info needed from Get-Mailbox
$mb=get-mailbox  $_.samaccountname    
# some from Get-MailboxStatistics
$mbstats = get-mailboxstatistics $_.samaccountname   

# create PSObject into which we will merge results
$user = New-Object PSObject   

# Now we add the desired properties into the PSObject
$user | Add-Member NoteProperty Name $mb.DisplayName
$user | Add-Member NoteProperty Usage $mbstats.TotalItemSize.Value.ToMB() 
$user | Add-Member NoteProperty Quota $mb.ProhibitSendQuota
$user | Add-Member NoteProperty Account $mb.SamAccountName 

# skipping users for whom no data is returned because they’ve never logged in
if ($mb.DisplayName -ne $NULL){$users += $user}

}

# Now, export the report as a CSV file:
$users | export-csv -path .\myGroup-Users.csv

PowerShell Training

The folks at Microsoft have made it pretty clear that they regard PowerShell (the scripting language formerly known as “monad”) as the future for managing their server products. Exchange 2007 was just the first wave, with the latest versions of SharePoint and SQL quickly following suite.  When Windows Server 2008 R2 is released, it will be accompanied by PowerShell v2.0, which will include a whole new batch of AD management cmdlets (including one for un-deleting AD objects – yeah!), as well as a PSDrive provider which will allow the Active Directory to be accessed from PowerShell as if it were a filesystem.

Last week, I and several of my collegues had the good fortune to attend a PowerShell training class.  Although I’ve been using PowerShell now for over a year to manage Exchange 2007, the class did provide a good opportunity to bone up on the fundamentals, and even helped me clear up some misconceptions that I had about how certain commands work. (ForEach and ForEach-Object are different commands?  That explains a lot….)

For anyone interested in learning more about PowerShell, here are some good resources: