Retrieve all Exchange mailboxes by OU with PowerShell


A question came up on powershellcommunity.org:
”Hi guys,
I’ve been blindsided by the General Manager and need to get a list of all our Mailboxes, as well as the smtp addresses attached to them.
I need these to be pumped out per OU (we have a lot) so that I can do costings per OU.
So basically, I need to get a list of mailboxes (with all smtp addresses) per OU, exported to a csv file
I don’t mind running the same command multiple times, just changing the OU name. But not sure how to do this!
Can anyone help?”

As the original poster did not provide information on his Exchange version, I created a script for Exchange 2007 and one for Exchange 2010.

Exchange 2010 has the shiny new “Get-OrganizationalUnit” cmdlet, which works pretty much as implied.
With Exchange 2007, and no fancy AD cmdlets from Quest or Microsoft, you have to roll your own in an ADSI call

So, for Exchange 2007, I did this:

001
002
003
004
005
006
007
008
009
010
011
012
013
014
015
016
017
function Get-OU
{
$search = [System.DirectoryServices.DirectorySearcher]([adsi]“”)
$search.Filter = “(objectClass=organizationalUnit)”
$ounames = $search.Findall()
return $ounames
}
 $AllMailboxes = @()
 foreach ($ou in Get-OU)
 {
  $AllMailboxes += Get-Mailbox -OrganizationalUnit $ou.Properties.distinguishedname[0]`
-ResultSize Unlimited |Select-Object OrganizationalUnit,`
DisplayName,PrimarySmtpAddress, @{Name=“EmailAddresses”`
;Expression={$_.EmailAddresses |Where-Object `
{$_.PrefixString -eq “smtp”} | ForEach-Object {$_.SmtpAddress}}}
 }
 $AllMailboxes |Export-Csv c:\test.csv -NoTypeInformation

For Exchange 2010:

001
002
003
004
005
006
007
008
009
010
 $AllMailboxes = @()
 foreach ($ou in Get-OrganizationalUnit)
 {
  $AllMailboxes += Get-Mailbox -OrganizationalUnit $ou.DistinguishedName`
-ResultSize Unlimited |Select-Object OrganizationalUnit,`
DisplayName,PrimarySmtpAddress, @{Name=“EmailAddresses”`
;Expression={$_.EmailAddresses |Where-Object `
{$_.PrefixString -ceq “smtp”} | ForEach-Object {$_.SmtpAddress}}}
 }
 $AllMailboxes |Export-Csv c:\test.csv -NoTypeInformation
Advertisements
  1. #1 by Jim on October 17, 2010 - 17:06

    Just a note because many miss how these guys are designed amd defaulted:

    This:


    $search = [System.DirectoryServices.DirectorySearcher]([adsi]“”)
    $search.Filter = “(objectClass=organizationalUnit)”
    $ounames = $search.Findall()

    Can be done easier like this:


    $ounames =([adsisearcher]“objectClass=organizationalUnit").Findall()

    The type accellerator defaults to teh current domain and if only one string is persent it assumes that it is the filter string. We can paren this and use it to eliminate any temporary variables. Remembering how this works makes it very typable and eliminates the need for a function to be loaded in advance.

    Very nice suggestion on teh mainboxes by OU.

    • #2 by karlmitschke on October 18, 2010 - 13:55

      Thanks, Jim!

      I did not know of the [adsisearcher] type accelerator until now.

  2. #3 by Raymond Dales on December 31, 2010 - 08:41

    I tried running the script for Exchange 2007 to get the OUs and got the following error.
    Any ideas?

    At :line:12 char:2
    + -R <<<< esultSize Unlimited |Select-Object OrganizationalUnit,`

    Missing expression after unary operator '-'.
    At :line:12 char:2
    + -R <<<< esultSize Unlimited |Select-Object OrganizationalUnit,`

    • #4 by Karl Mitschke on December 31, 2010 - 18:58

      Hello;

      Lines 11, 12, 13, 14, and 15 are one long line.

  3. #5 by Ed Wilkinson on February 8, 2011 - 19:07

    Hi,

    Is it possible to add the Size of the mailbox for each user to this?

    Thanks
    Ed

    • #6 by Karl Mitschke on February 9, 2011 - 08:48

      Ed;

      This should work for 2007 (Replace lines 11.12.13.14.15)
      $AllMailboxes += Get-Mailbox -OrganizationalUnit $ou.Properties.distinguishedname[0] `
      -ResultSize Unlimited |Select-Object OrganizationalUnit, DisplayName,PrimarySmtpAddress, `
      @{Name=”EmailAddresses”Expression={$_.EmailAddresses `
      |Where-Object {$_.PrefixString -eq “smtp”} `
      | ForEach-Object {$_.SmtpAddress}}}},@{Name=”Total Size” ;Expression=`
      {(Get-MailboxStatistics $_.DistinguishedName |Select-Object TotalItemSize).TotalItemSize}}

      For 2010 (replace line 4,5,6,7,8)
      $AllMailboxes += Get-Mailbox -OrganizationalUnit $ou.DistinguishedName -ResultSize Unlimited `
      |Select-Object OrganizationalUnit,DisplayName,PrimarySmtpAddress, `
      @{Name=”EmailAddresses”;Expression={$_.EmailAddresses `
      |Where-Object {$_.PrefixString -ceq “smtp”} `
      | ForEach-Object {$_.SmtpAddress}}},@{Name=”Total Size” ;Expression=`
      {(Get-MailboxStatistics $_.DistinguishedName |Select-Object TotalItemSize).TotalItemSize}}
      }

  4. #7 by Rod on August 22, 2012 - 05:29

    Sorry but I don’t get it to work on 2010
    I just copy paste the code, saved it to a .ps1 file and executed it in EMS and get this

    Missing expression after unary operator ‘-‘.
    At D:\scripts\distinguishedname.ps1:5 char:2
    + – <<<< ResultSize Unlimited |Select-Object OrganizationalUnit,`
    + CategoryInfo : ParserError: (-:String) [], ParseException
    + FullyQualifiedErrorId : MissingExpressionAfterOperator

    What am I doing wrong?
    Thanks

    • #8 by Karl Mitschke on August 22, 2012 - 09:03

      There is an unfortunate space at the end of each line of the pasted code.
      If you remove the trailing space from each line, the code should work.

      Karl

      • #9 by Bob Wang on November 8, 2012 - 20:56

        Hi Karl,

        the script didn’t seem to be working with exchange 2010 sp2, wonder if any code need to be changed.

        thanks in advance,

        Bob

      • #10 by Karl Mitschke on November 19, 2012 - 11:15

        Try changing lines 4, 5,6,7,and 8 as follows:
        4) $AllMailboxes += Get-Mailbox -OrganizationalUnit $ou.DistinguishedName -ResultSize Unlimited |
        5) Select-Object OrganizationalUnit,
        6) DisplayName,PrimarySmtpAddress, @{Name=“EmailAddresses”
        7) ;Expression={$_.EmailAddresses |Where-Object `
        8) {$_.PrefixString -ceq “smtp”} | ForEach-Object {$_.SmtpAddress}}}

        Or, make it one line (remove the ` characters)

        Karl

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: