One of the Exchange Server administration tasks I perform almost every day is creating mailbox size reports. There are a few different reasons that I create these reports, such as planning a mailbox migration project, responding to a storage capacity alert for a particular database, or providing a specific team of people with a report of their mailbox sizes.

Now it is pretty easy to get the sizes for Exchange mailboxes and to handle the formatting of the Exchange 2010 mailbox statistics so that they are easier to perform calculations on, but it gets a bit boring running those commands day after day.

Even worse, after running the commands to create a CSV report I still had to open that in Excel, remove the unwanted details, use Excel formulas to convert the values from bytes to megabytes, sort them into order, and so on. Again not difficult, just boring after doing it hundreds of times.

So I created a PowerShell script, Get-MailboxReport.ps1, to do all of the heavy lifting for me, and I’m sharing that script with you here.

This script is available on the TechNet Script Gallery or Github. Comments are welcome below. If you find a bug please consider raising it as an issue on Github.

Let’s take a look at how the script works. Here is a video to demonstrate:

I’ve included help information within the script itself so you can use Get-Help to discover how to run the script.

[PS] C:\Scripts\demo>Get-Help .\Get-MailboxReport.ps1


    Get-MailboxReport.ps1 - Mailbox report generation script.

    C:\Scripts\demo\Get-MailboxReport.ps1 [-database ] []

    C:\Scripts\demo\Get-MailboxReport.ps1 [-file ] []

    C:\Scripts\demo\Get-MailboxReport.ps1 [-server ] []

    C:\Scripts\demo\Get-MailboxReport.ps1 [-mailbox ] []

    C:\Scripts\demo\Get-MailboxReport.ps1 [-all] []

    Generates a report of useful information for
    the specified server, database, mailbox or list of mailboxes.
    Use only one parameter at a time depending on the scope of
    your mailbox report.

    For more script details, a video demo, or to give feedback please go to:

    To see the examples, type: "get-help C:\Scripts\demo\Get-MailboxReport.ps1 -examples".
    For more information, type: "get-help C:\Scripts\demo\Get-MailboxReport.ps1 -detailed".
    For technical information, type: "get-help C:\Scripts\demo\Get-MailboxReport.ps1 -full".

Depending on which parameter you use the output will vary.

  • If you use the -mailbox parameter to query a single mailbox, then the output will appear in the console window. I don’t really see the need to output a single mailbox’s details to a CSV file.
  • If you use any of the other parameters, -server, -database, -file, or -all, the output will be written to a CSV file in the same folder you’re running the script from.
  • You can use the optional -filename parameter to specify your own output file name

Once you’ve generated the CSV report you can open it with Excel and begin to analyze the data.

This script is available on the TechNet Script Gallery or Github. Comments are welcome below. If you find a bug please consider raising it as an issue on Github.

About the Author

Paul Cunningham

Paul is a former Microsoft MVP for Office Apps and Services. He works as a consultant, writer, and trainer specializing in Office 365 and Exchange Server. Paul no longer writes for


  1. Aaron

    This is a beautiful script!

  2. Charles

    I’m running the report (Exchange 2013) with the “-all” switch, but its not showing the total mailbox size, inbox size, etc. It does show the archive sizes as “n/a”. Was there a different switch to get the mailbox size included?

  3. Noe L

    good morning friends,

    I would like to make a report to extract fields from both AD and Exchange
    for example:
    Name Company Department Description Domain Email Address Job Title MAILBOX SIZE SPACE IN (MB) Office Street PHONE

    This is possible?

    1. Dennis

      You ever get a response on this?

  4. Kashif

    Hi Paul,
    Thanks for sharing the mailbox statistics script. I am having a bit different scope as i am searching a script that will send an email alert to helpdesk distribution group when a mailbox approaching its limit of prohibit send. can you please help to get it done.

    Kashif Saeed

  5. Fadhil Hamid

    Thank you. this lowed my learning curve in exchange

  6. Alex Nagy

    Does this work off the Scheduled Tasks? If I run it manually, it works fine. But from scheduled tasks it keeps saying: Could not find file ‘C:\SCRIPTS\Alex\MailboxReport-20200405-1637-evhlr9.csv’.

  7. Keith Luken

    I love this script. I would like to see it scan all AD accounts and get mailbox info whether is is on prem Exchange or O365 and just annotate each with relevant field comments if n/a.

  8. Kenneth

    Hi Paul

    Can this script be used for Exchange Online?
    If so, how can I do it?

    1. Kenneth

      Sorry, for repetition, something went wrong with my answer.

  9. Kenneth G. Vandbæk

    Hi Paul.

    Is it possible to use this with Exchange Online?
    If yes, how do to that?

  10. Kenneth G. Vandbæk

    Hi Paul.

    Is it possible to use this script against Exchange Online, if so, how do I do that.

  11. AniketG

    Hi Paul,

    I run this script into Exchange 2016 server, takes lot of time to execute it, any chances reduce it.

  12. Martin Soubre

    Hi, very thank for your script, it’s an awesome work, save me hours of work
    By the way, it work well on windows server 2016 with exchange 2016 CU11, maybe you can tag it on the technet

  13. Richard Pettigrew

    Thank You Very Much for saving me many hours of my time! Appreciate it. 🙂

  14. Krasimir Donchev

    Hi Paul,
    the script is OK, but please change the column delimiter with ~. Using , as delimiter is not a good idea when exporting to CSV file, where most of the envrionments use DisplayName like: Lastname, Firstname.


  15. Rakesh

    Hi Paul ,

    I am looking for Archive Quota and Archive Warning Quota also to be included, do you have any other script for that to be included as well?

  16. Joe

    great script

    is there anyway to modify it to collect active sync syncs per account so I can great a power bi report for that?

  17. Anup Pachkude

    Hi Paul,

    We need to create a script to scan all inbox rules that are created on the user’s email where they only “Delete” inbound emails.

    Thanks in advance.

  18. Nagaraj

    HI Paul,
    a very tricky question you please help me on below requirement.
    if i run any exchange powershell command the complete output should be captured in transcript, Example If i run start transcript and then new=mailboxexportrequest with mailbox name and path then command will execute and in transcript i could see only output as mailbox is in pending status but i would like to capture all back end process until mailbox exported to the given path. Is there a way to do it. Kindly help me on this.

  19. Joe

    Got a lot of syntax error. What is going wrong?

    At C:\Windows\Get-MailboxReport.ps1:148 char:190
    + … ures”>Features <span class="Bump-link-symbol float-right text-normal text-gray-l …
    + ~
    The '→
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
    quotation marks (“&”) to pass it as part of a string.
    At C:\Windows\Get-MailboxReport.ps1:161 char:243
    + … “>Case Studies <span class="Bump-link-symbol float-right text-normal text-gray-l …
    + ~
    The '→
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
    quotation marks (“&”) to pass it as part of a string.
    At C:\Windows\Get-MailboxReport.ps1:162 char:231
    + … rity”>Security <span class="Bump-link-symbol float-right text-normal text-gray-l …
    + ~
    The '<' operator is reserved for future use.

    1. Chris

      This is probably because you may have just saved the script directly and it’s downloaded as HTML, rather than a PowerShell script?

  20. Craig Miskimmons


    I’ve ran the latest version of the script and i don’t seem to get anything in the “Last Logon By” field. I get data for every other field. Any idea why this might be?

  21. Filipe Araujo

    I’ve tried several things, this is all I get:

    PS C:\temp> C:\TEMP\Get-MailboxReport.ps1 -Server -SendEmail -MailTo XXX -MailFrom XXX -MailServer XXX
    C:\TEMP\Get-MailboxReport.ps1 : Missing an argument for parameter ‘Server’. Specify a parameter of type ‘System.String’ and try again.
    At line:1 char:31
    + C:\TEMP\Get-MailboxReport.ps1 -Server -SendEmail -MailTo XXX…
    + ~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-MailboxReport.ps1], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,Get-MailboxReport.ps1


    PS C:\temp> .\Get-MailboxReport.ps1 -Server
    C:\temp\Get-MailboxReport.ps1 : Missing an argument for parameter ‘Server’. Specify a parameter of type ‘System.String’ and try again.
    At line:1 char:25
    + .\Get-MailboxReport.ps1 -Server
    + ~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-MailboxReport.ps1], ParameterBindingException
    + FullyQualifiedErrorId : MissingArgument,Get-MailboxReport.ps1

    1. Filipe Araujo

      I’m running Exchange 2010
      PS version 5

    2. Filipe Araujo

      What a silly error I’m sorry.
      I was able to run it once then it no longer wants to run, I get the below:

      Collecting report data
      The type initializer for ‘Microsoft.Exchange.Diagnostics.ExTraceConfiguration’ threw an exception.
      + CategoryInfo : OperationStopped: (XSERVERX:String) [], PSRemotingTransportException
      + FullyQualifiedErrorId : JobFailure
      + PSComputerName : XSERVERX

      No mailboxes were found matching that criteria.

  22. Munesh Singh

    Hi Paul,

    Hope you are doing well.

    I’m running the script on one of my server but its running and powershell just close automatically in few seconds after running that script.


    Best Regards
    Munesh Singh

  23. Lex

    Hi Paul,

    Great work! I also have issues with ExchangeServer2016, but here is my error:

    [PS] C:\>.\Get-MailboxReport.ps1 -All

    VERBOSE: Connecting to TR-EXCH.XXX.local.
    VERBOSE: Connected to TR-EXCH.XXX.local.
    Import-Module : The specified module ‘ActiveDirectory’ was not loaded because no valid module file was found in any
    module directory.
    At C:\Get-MailboxReport.ps1:211 char:1
    + Import-Module ActiveDirectory -ErrorAction STOP
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceUnavailable: (ActiveDirectory:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

  24. Patrick Poon

    How to make the script to support the Mailboxes in Exchange Online?

  25. Keith McConville

    Hi Paul,

    I am getting an error file generated (get-mailboxreport-error.log) every time I run the script from any location. The text in the file goes something like “Could not find file ‘C:\scripts\MailboxReport-20180606-1508-6HNLvO.csv’.” Any ideas?

    1. Keith McConville

      Ignore that. When I used the -mailbox parameter, it didn’t work. I should have read you article above where you stated:
      “If you use the -mailbox parameter to query a single mailbox, then the output will appear in the console window. I don’t really see the need to output a single mailbox’s details to a CSV file.”

      Fantastic script and output!!!

  26. Sergio C.

    Thank for for providing this awesome script. I used it all the time when we were on 2010 but does not work with our new Exchange 2016 server. Will you be updating the script to make this work or is there something I can change in the code to make it work with 2016?

  27. Chris C

    First I just wanted to say this is a fantastic script! Saved me a TON of time. I did have a quick question on it however, is it possible to change the output of size from mb to gb? Is it a simple matter of replacing?


  28. Wasim Parkar

    Hi Paul
    This script is exactly what I am looking for but I cant get it to work.
    I can get the Get-Help up but if i run the command with the -all parameter it does nothing. I just get a new powershell window. A file gets created but with 0bytes.
    Any ideas. The command I run is:
    .\Get-MailboxReport.ps1 -All > C:\Temp2\newdata.csv
    It just comes to a new PS line (as if waiting for a new command).

      1. Mounir

        i have the same issue. even i use \Get-MailboxReport.ps1 -All > C:\Temp
        or just \Get-MailboxReport.ps1 -All

        It just comes to a new PS line (as if waiting for a new command).

  29. Nasser Al Toubi

    Dear Paul,

    Thank you for the great script it’s a very helpful script, it was working fine with me until last month as it’s configured for monthly basis but I get an issue with it, it give me error “Get-MailboxReport.ps1 : Parameter set cannot be resolved using the specified named parameters” I solved this issue by modifying the param as below:

    function foof{





    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]
    [int]$Top = 10


    however I get another error “No mailboxes were found matching that criteria.”

    Run on Exchange 2013

    Please advice


    1. Avatar photo
      Paul Cunningham

      What command were you tying to run when you got the parameter set error?

  30. SCBPC

    This worked great when we had 2010. Any chance you will make this work with Exchange 2016?

  31. Admin

    Garbage. Just returns “Parameter set cannot be resolved….”

  32. Jimmy Wang

    is it possible I can use -match switch in my search ?

    Example, i’m look for ManagedFolderMailboxPolicy in match specific policy and output out to csv file. how do I insert “match” switch in the script ?

    if($database){ $mailboxes = @(Get-Mailbox -ResultSize Unlimited | ? {$_.ManagedFolderMailboxPolicy -match “Exchange2007-Unlimited) }

    1. Avatar photo
      Paul Cunningham

      Please don’t post the same question on multiple articles. Yes, modify the Get-Mailbox line to suit your purposes.

      1. Jimmy Wang

        Sorry for posting different places. though it was different blogs.

        what is correct line ? I think Im doing it wrong when I insert this line
        if($database){ $mailboxes = @(Get-Mailbox -ResultSize Unlimited | ? {$_.ManagedFolderMailboxPolicy -match “Exchange2007-Unlimited) }

        can you help me to identify what am I doing wrong ?

        1. Avatar photo
          Paul Cunningham

          You’re modifying the line that is run when the -Database parameter is used to query the mailboxes on a single database.


          There are multiple Get-Mailbox commands depending on which script parameter is used, so you will need to modify the command that is applicable to how you’re using the script.

  33. Shane King

    Anyone know how to get the emailing of the report to work with SSL port 465?

    1. Avatar photo
      Paul Cunningham

      Short answer: add a parameter to the script, call it something like MailPort or SMTPPort. Make it a default value of 465 if you want.

      Add to the email settings at around line 173, the extra setting for Port = $MailPort

  34. Muhammad Kamran Khan

    Hi Paul,

    can i get all mailbox calendar permission excluding default and anonymous, if can quickly help i will be great i have exchange 2013 with hybrid deployment.

    1. Avatar photo
      Paul Cunningham

      Yes you can get that with PowerShell, just not with this particular script.

  35. Jimmy Wang

    How to email with multiple recipients in one string instead ? some of the user is not in same distribution group and would like to including them. My work around, is to modify/add this parameter but I can’t add more than one user per string.

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

    [Parameter( Mandatory=$false)]

  36. Jimmy Wang

    when I run this script I get the version error. my windows powersehll is version 4 and exchange powershell is version 2.

    I took exact same script to run on different machine that is running Windows powershell version 2 and exchange powershell version 2 and it runs fine.

    Does this mean this script Get-MailboxReport.ps1 doesn’t support Windows powershell version 4 ?

    verson : The term ‘verson’ is not recognized as the name of a cmdlet, function, script file, or operable program.
    Check the spelling of the name, or if a path was included, verify that the path is correct and try again.
    At line:1 char:1
    + verson
    + ~~~~~~
    + CategoryInfo : ObjectNotFound: (verson:String) [], CommandNotFoundException

    PS C:\> $PSVersionTable.PSVersion

    Major Minor Build Revision
    —– —– —– ——–
    4 0 -1 -1

    1. Avatar photo
      Paul Cunningham

      “verson : The term ‘verson’ is not recognized as the name of a cmdlet, function, script file, or operable program.”

      Did you modify the script? If so, looks like you’ve misspelled “version”?

      1. Jimmy Wang

        Hi Paul, thanks for getting back.
        I downloaded the script again without changing anything. still running the same error.

        I didn’t mention, I’m running this in task scheduler. i have no problem running it from Exchange powershell, always can get the results back. with this
        .\Get-MailboxReport.ps1 -database databasename -SendEmail -MailFrom -MailTo -MailServer

        when I run it from task scheduler, the Window powershell pop up and error out with this error . from out my machine, it runs fine.

        it looks like it bomb out on Windows powershell

        trouble machine is running Windows powershell version 4.0
        working machine is running Windows powershell version 2.0

        Collecting mailbox list
        The type initializer for ‘Microsoft.Exchange.Diagnostics.ExTraceConfiguration’ threw an exception.
        + CategoryInfo : OperationStopped: ( [], PSRemotingTransportException
        + FullyQualifiedErrorId : JobFailure
        + PSComputerName :

        Collecting report data
        The type initializer for ‘Microsoft.Exchange.Diagnostics.ExTraceConfiguration’ threw an exception.
        + CategoryInfo : OperationStopped: ( [], PSRemotingTransportException
        + FullyQualifiedErrorId : JobFailure
        + PSComputerName :

        Problem signature:
        Problem Event Name: PowerShell
        NameOfExe: powershell.exe
        FileVersionOfSystemManagementAutomation: 6.3.9600.16406
        InnermostExceptionType: System.NullReferenceException
        OutermostExceptionType: System.TypeInitializationException
        DeepestPowerShellFrame: unknown
        DeepestFrame: oft.Exchange.Diagnostics.SystemTraceControl.Update
        ThreadName: unknown
        OS Version: 6.1.7601.
        Locale ID: 1033

        Read our privacy statement online:

        If the online privacy statement is not available, please read our privacy statement offline:

  37. Jon

    Is there a way to specify multiple servers when running the script?

    1. Avatar photo
      Paul Cunningham

      Not as is. I tend to just run it for the whole org and do my filtering in Excel later.

  38. Piter

    Hi Paul, can you help me?

    How could I control the growth of mailboxes? I want to do the operations in excel.


  39. tom smith

    Hi Paul,

    should this script also flag archive mailboxes on the databases?
    ive just run the script against an archive db and it doesn’t flag any users?

    works fine on the other databases

    1. Avatar photo
      Paul Cunningham

      Without really looking into it, I’d guess that the script is not handling that scenario properly. I’ve made a note in my GitHub issues register to take a closer look at some stage.

      As a workaround I’d suggest, if practical in your environment, just running a report of the entire org and filtering in Excel to get the view that you’re looking for.

  40. Paul Lee

    This script is amazing! I was wondering if there is a way to report on mailbox items that are less than 30 days old? In other words, total items and size for the most recent 30 days, discarding anything older than that.

    1. Avatar photo
      Paul Cunningham

      You’ll need Exchange Web Services for that level of detail. There’s good code samples out there for EWS scripts that report on mailbox item age.

  41. Shaik

    Hello paul,

    Could you please help me with the script where the quota emails triggers to admin when any users reach the quota limit.

  42. joshua

    I am running into the same error message “cannot process argument transformation … ”

    I am using Exchange 2010, so the advice about referring to storage groups is not meaningful.

    How can I fix this ?

    1. Avatar photo
      Paul Cunningham

      Are you using the Exchange management shell or a remote PS session? The script doesn’t work with a remote PS session.

      1. joshua

        I am using the Exchange Management Shell. The error and the version table are:

        Welcome to the Exchange Management Shell!

        [PS] C:Windowssystem32>.get-mailboxreport.ps1 -database m:databasexxxxxxxx.edb

        VERBOSE: Connecting to xxxxxx.xxxx.local
        VERBOSE: Connected to xxxxxx.xxxx.local.
        WARNING: Active Directory server settings remained unchanged.
        Collecting mailbox list
        Cannot process argument transformation on parameter ‘Database’. Cannot convert value “m:databasesharedemail-sg.edb” t
        o type “Microsoft.Exchange.Configuration.Tasks.DatabaseIdParameter”. Error: “‘m:databasesharedemail-sg.edb’ is not a
        valid value for the identity.
        Parameter name: Identity”
        + CategoryInfo : InvalidData: (:) [Get-Mailbox], ParameterBindin…mationException
        + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-Mailbox
        + PSComputerName : ny-paperboy.onssi.local

        Collecting report data
        No mailboxes were found matching that criteria.

        [PS] $psversiontable

        Name Value
        —- —–
        CLRVersion 2.0.50727.5485
        BuildVersion 6.1.7601.17514
        PSVersion 2.0
        WSManStackVersion 2.0
        PSCompatibleVersions {1.0, 2.0}
        PSRemotingProtocolVersion 2.1

        1. Avatar photo
          Paul Cunningham

          Use the name of the database, e.g. “Mailbox Database 1”, not the filename/path. The database name is whatever you see when you run Get-MailboxDatabase.

  43. Gav

    HI Paul,

    What happens if the script is run without switches?



  44. Peter Goldfarb

    Hi Paul,

    Great script! Just wanted to say thank you for creating such a useful piece of code.


  45. GAV

    Hi Paul,

    I’ve run the script and it works great but when I try to run it as scheduled task it’s not doing much. Have you ever run it as a scheduled task?



    1. Julio Villar

      If it works as a scheduled task, you must configure in the action option and enter the path with which program the script will be executed and in a comment argument enter a similar syntax.

      The script path may vary in this case, place the script in drive “C:” inside the “Script” folder

      -command “C:\Script\Get-MailboxReport.ps1 -All -SendEmail -MailTo -MailFrom -MailServer”

  46. Max P

    I just cant get this script to run on our exchange server 2010.
    Always getting error. Im just using it as explained in your video.
    No matter with what switch i use it just gives me back these lines

    At C:Users.DesktoppowershellGet-MailboxReport.ps1:116 char:13
    + <a href="/open-source" class="js-selected-navigation-item nav-item n …
    + ~
    The '<' operator is reserved for future use.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:118 char:13
    + <a href="/business" class="js-selected-navigation-item nav-item nav- …
    + ~
    The '<' operator is reserved for future use.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:120 char:13
    + <a href="/explore" class="js-selected-navigation-item nav-item nav-i …
    + ~
    The '<' operator is reserved for future use.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:122 char:11
    + ~
    The ‘
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks (“&”) to pass it as part of a string.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:2307 char:11
    + © 2016 <span title="0.07444s from github-fe155-cp1-prd.iad.github …
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double quotation marks ("&") to pass it as part of a string.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:2307 char:23
    + © 2016 <span title="0.07444s from github-fe155-cp1-prd.iad.github …
    + ~
    The '<' operator is reserved for future use.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:2307 char:29
    + © 2016 GitHub’ in expression or statement.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:2307 char:100
    + … “>GitHub, Inc.
    + ~
    Missing argument in parameter list.
    At C:Users.DesktoppowershellGet-MailboxReport.ps1:2326 char:14
    + You can’t perform that action at this time.
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    The string is missing the terminator: ‘.
    + CategoryInfo : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : RedirectionNotSupported

    Can someone help me ? What am i doing wrong?

    1. Avatar photo
      Paul Cunningham

      You’ve downloaded a bunch of HTML code from the page on GitHub, not just the script code itself.

  47. Madhav Pai

    Actually what need is all mailboxes including the one which migrated, discoonected, softdeleted, disabled.

  48. Juns

    Hello Paul,

    This script is amazing and does get all the details.

    How can we have the script run against a specific OU to retrieve the details of users belonging to a specific OU only.

    This would be really helpful for me. Thank you!


    1. Mik

      Hello Paul,

      I have exact the same question as Juns.

      Best regards,


  49. Alex

    Hello Paul,
    thank you very much for this script.

    When I try to run it, I get a “NullReference” Exception.

    The last line in the Powershell window is “Collecting mailbox list”.

    Its a 2012 Server with Exchange 2010 (14.3 123.4).

  50. A K M Mahbubul Hossen

    This is a nice script for day to day administration. But i am facing a problem. While i get the report i found Account Enabled and Account Expires column blank. Nothing is found for this two column. Please help me to solve the issue.

    I have below modules are installed in my exchange mailbox server from where i am executing the script.
    [PS] D:Program FilesMicrosoftExchange ServerV14scripts>get-module -listavailable

    ModuleType Name ExportedCommands
    ———- —- —————-
    Manifest ActiveDirectory {}
    Manifest ADRMS {}
    Manifest AppLocker {}
    Manifest BestPractices {}
    Manifest BitsTransfer {}
    Manifest FailoverClusters {}
    Manifest PSDiagnostics {}
    Manifest ServerManager {}
    Manifest TroubleshootingPack {}
    Manifest WebAdministration {}


  51. A K M Mahbubul Hossen

    This is a nice scripts for day to day administration. But i am facing a problem. While i get the report i found Account Enabled and Account Expires column blank. Nothing is found for this two column. Please help me to solve the issue.



  52. Elmer

    Muchas gracias Paul por compartir tan valiosos conocimientos.

  53. Peter Nagel

    Thanks for this work! I added some code to add two additional fields: SIP Address (containing the Skype for Business SIP Address of the user) and “All Email Addresses” which contains a comma seperated List of all email alias addresses a mailbox has. If you want to incorporate these changes please feel free to contact me to send the modified script to you 🙂



  55. Joe G.


    First, thanks for everything through the years, you have been a huge source of guidance.

    This script works great, I get the CSV I want in the drop folder, no problem.

    The -MailFrom seems to have issues. It doesn’t like my input value to some degree.

    I get a get-mailboxreport-error log of:
    “Cannot validate argument on parameter ‘From’. The argument is null or empty. Provide an argument that is not null or empty, and then try the command again.”
    I am trying to mail the results to multiple addresses as a scheduled task behind a BAT file as follows:
    C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -command “. ‘C:Program FilesMicrosoftExchange ServerV15binRemoteExchange.ps1’; Connect-ExchangeServer -auto;” “C:scriptsGet-MailboxReport.ps1 -All -SendEmail -MailTo;; -MailFrom -MailServer”

    Where all addresses are internal
    Where is an internal open relay (works for all other scripts, apps, telnet :25, etc.)
    Exchange is 2013CU11 4 multi-role member / 2 site DAG
    Running from 2012R2 server with all AD modules + Exchange 2013CU11 tools (modules)

    I haven’t modified the script, except for code signing it. (Required)

    Any ideas ?

    1. Joe G.


      Nevermind, 🙂

      I put a ‘pause’ in the BAT and could see that it did not like multiple addresses. I will have to create a distro group and send it there.


  56. Avatar photo
    Paul Cunningham


    There’s no “exumenabled” attribute of mailboxes. There is one called “UMEnabled” though.

  57. Doug Walker

    I am trying to add a umenabled field to this report. I have been able to add other fields, but having issues with this.
    I have tried adding $userObj | Add-Member NoteProperty -Name “Umenabled” -Value $mb.exumenable
    But the field I s blank. Also tried ummailbox with the same result
    Any ideas?
    Great script by the way

  58. Hugh Dunlop

    Hi Paul,

    Thanks for the script, however this month it will not run! When I go to run the script all I get is …

    C:ScriptsGet-MailboxReport.ps1 : Parameter set cannot be resolved using the specified named parameters.
    At line:1 char:1
    + .Get-MailboxReport.ps1 -server -file c:scripts250416.csv
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidArgument: (:) [Get-MailboxReport.ps1], ParameterBindingException
    + FullyQualifiedErrorId : AmbiguousParameterSet,Get-MailboxReport.ps1

    Any help would be welcomed.

  59. Joe

    My report takes over 3 days to run, i only have about 6000 mailboxes.
    Only one time i ran it, it ran in 4 hours.(magical time)

    Any ideas?



    1. Avatar photo
      Paul Cunningham

      Try running it against one database at a time to see which one might be slowing things down.

  60. Ron Kauffman


    I ran the report, and it worked great. You have item counts for the mailbox. But could you add item counts for the Inbox, Sent Items and Deleted Items folders?



  61. Rahul

    Hey Paul
    I getting error unable to relay email, after completion of script. And how to add two different database names i. e get-mailboxdatabase db-1 and db-9, and 3rd error is unable to split , while retrieving database drive space.

  62. RHV

    I am running the script from my laptop. I get all mailboxes with most of the data, but for all Size columns I get “n/a”.

    Issue warning Quata, Prohibit send, Account Expires, last logon are also blank.

    I have tried to run the scipts as Administrator, both in Power Shell and in ISE

    I don’t want to install the Exhange Management Console on my Exchange server so I am running it from my laptop on Windows 7.

    1. Avatar photo
      Paul Cunningham

      Your Exchange server would already have the Exchange management shell on it.

      Regardless, if you want to run it on your workstation, have you installed the Exchange management tools on it?

      1. RHV

        Yes, the Exchange management tools are installed.

        The script is also running and I get most of the info for all my users
        – just not the about about sizes and so on…

      2. RHV

        I found the problem….

        My user did not have enough rights. I logged on my computer with Domain administrator and then I got all relevant information.


  63. Daniel

    first off the script is awesome, thank you.
    i am trying to email the results to an outside email address. however i get unable to relay error. the script is running on the exchange server. i can send the email to an internal address with no problem. would you know what i need to change to allow it to relay to an external address? when i do a manual command to send an email to an external address i can use the -credential $credential command and it pops up a window for login, that works but i cant do that from a scheduled task. to add to the confusion i have been able to setup the script in a scheduled task on two exchange server and get the email but i have tried on three other servers and it will not relay. i have checked the send connectors on all the servers and none of them, including the ones that work, have an open relay for the exchange server’s IP address. they have relay for other devices but the exchange server’s IP is not in there, nor is 127…
    curious if you have any advice. thank you for the script, its very very helpful in keeping track of the ever exploding email boxes.

    1. Avatar photo
      Paul Cunningham

      If you’re trying to relay to an external address, then you either need to authenticate the SMTP session, or you need a relay connector that allows that IP to relay.

      But I don’t recommend adding an Exchange server’s IP to any relay connectors, that will most certainly break internal mail flow.

      Personally, I run these types of scheduled scripts from a separate management or monitoring server.

      Plus, you could try sending the report to a distribution group. That is an internal email address, so it should be accepted, and it can contain contacts for external addresses.

  64. Carlos

    Hi Paul,

    First, many thanks for another fantastic script!
    I’m running it in an Exchange 2013 CU7 (Server 2012 R2) environment. The script runs fine and dumps the csv format report in the directory. However, I do not get it emailed to me although the report data in the shell shows “Sending email report… Finished.”

    Please help – Thank you!

    1. Avatar photo
      Paul Cunningham

      Most likely means you are not specifying valid/working SMTP settings when you run the script.

      1. Carlos

        Please see below.
        I am running the script from a second script called ExecuteMailboxReport.ps1 so I can run it in a scheduled task:

        Get-ChildItem C:tempMailboxReport *.ps1 -Recurse | Unblock-File
        Set-ExecutionPolicy -Scope CurrentUser -ExecutionPolicy Unrestricted | .Get-MailboxReport.ps1 -All -SendEmail -MailFrom -MailServer -MailTo

        Do I specify the SMTP settings in this script like i did above, or rather in the original one (Get-MailboxReport.ps1)?
        Also, the email specified in the -MailTo switch belongs to a group. Does that make a difference or do I have to use the group members individual emails?

        Thank you!

        1. Carlos

          Kindly disregard my embarrassing previous mail – I was not using my head at all!
          I have now figured it out. I did not need a second script to run it in a scheduled task.
          Running the below command in the Arguments section of the scheduled task worked for me, plus I also got the report emailed:

          Powershell -executionpolicy bypass -file C:tempMailboxReportGet-MailboxReport.ps1 -All -SendEmail

          Again thank you very much Paul!!

  65. Tom

    I am running from my local Windows 7 machine with RSAT installed. I remotely connect PS to one of our mail servers. I am able to run other scripts with no issues. But when I run .get-mailboxreport.ps1 -database “database A” it immediately comes back to a prompt. There is no error. No file is created. I am not sure what I am doing wrong here, hopefully you can tell me how to correct it. -Thanks

  66. David UK

    Hi Paul,

    Thanks for taking the time to create such a useful and widely used script.

    However, each time I run the script it doesn’t output any information in the ADUser columns (Account Enabled and Account Expires). Everything else is as expected. Is it me doing something wrong or do I need to modify the script to work?


    1. Avatar photo
      Paul Cunningham

      That part relies on the Active Directory PowerShell module. From the same server or workstation that you’re running the script from, can you run AD cmdlets like Get-ADUser without error?

  67. Kirk

    I need to keep stats on mailboxes relative to their retention policy. I have a one year retention policy, excluding contacts, calendar, tasks and drafts. I want to report on any mailboxes that have data beyond the retention policy. Can just get the mailbox size of data over a year, that would include data in the excluded folders.

    I believe I can use EWS to do this but have not found how to exclude the specific folders.

  68. lior

    hi paul
    having issue when i run the script

    The ‘<' operator is reserved for future use.
    At C:Get-MailboxReport.ps1:112 char:13
    + <!– < <<< –>
    + CategoryInfo : ParserError: (<:OperatorToken) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

    any advise ?
    thank you

    1. Paul Cunningham

      That usually means you’ve downloaded a bunch of HTML from Github instead of just the PowerShell code. You might find it easier to use the TechNet Script Gallery link instead.

  69. Reda

    You must run PS :

    Import-Module ServerManager
    Add-WindowsFeature RSAT-AD-PowerShell

  70. Rajesh

    Hi Paul,

    Thanks for the great script.

    How can I check whether the mailbox is active or not for a list of email addresses in a text file using power shell ?


  71. Jared

    Hi Paul,

    Brilliant script and has worked perfectly.

    Just wondering if there was an easy way of adding the mailbox quota size as a heading on the top 10 email form?

  72. Paul

    Hi Paul,

    Thank you for this great script. Just wanted to know if it includes as well a way to detect if a userA had tried accessing a userB mailbox?
    Do you think that this is something that could be integrated by any chance?



  73. Anthony I.

    Thanks for providing this great tool. I wanted ask if there other parameters that could be used to pull stats for mailboxes within a child domain? We have a root domain that contains several child domains. Is there a way for your script to just search for users of single domain?

    Thank you.

    1. Avatar photo
      Paul Cunningham

      The script doesn’t include a parameter for that, but you could easily modify it to suit your needs. Just look for the line with the Get-Mailbox cmdlet and modify that to what you want.

      1. Cam

        Hi Paul,

        Do you have the exact command for this? I tried this –

        Get-Mailbox -resultsize unlimited | Select-Object displayname -expandproperty emailaddresses| Where-Object {$_.smtpaddress -like “*”} | -IgnoreDefaultScope

        But It comes back with no results, but when I run it independently, it shows the mailboxes I am looking for..

  74. Mike Williams

    Is there any way to add the retention policy applied in the output of this script and the mailbox features that are enabled?

  75. Antoni

    Hi Paul,

    We are running Ms. Exchange 2007, and running more user with big size attachment when sending email via outlook and seamonkey, and the user mailbox is always full.

    And we alwayas delete the user mailbox that get full, and re-create the user mailbox, and here we need help, how to reduce or remove the full mailbox without to remove the user mailbox ?

    Thank you.

    1. Avatar photo
      Paul Cunningham

      Deleting and recreating a mailbox just because the mailbox was “full” (which I assume you mean it has reached its mailbox quota) seems like overkill to me. The user could just delete some unwanted mail.

  76. Robert Evans

    Ok guys what am I missing here? I have Exchange 2013cu8 running on Server 2012r2. When I try to run the script I that the output displayed below. But if I run this on an Exchange 2013cu10 on Server 2012 not r2 it runs fine. Is this because of r2 or am I missing something. Thanks in advance.

    [PS] C:UsersbevansadminDesktop>.Get-MailboxReport.ps1 -all
    At C:UsersbevansadminDesktopGet-MailboxReport.ps1:100 char:12
    + <!– –><form accept-charset="UTF-8" action="/cunn …
    + ~
    The '<#
    + ~
    The ampersand (&) character is not allowed. The & operator is reserved for future use; wrap an ampersand in double
    quotation marks (“&”) to pass it as part of a string.
    At C:UsersbevansadminDesktopGet-MailboxReport.ps1:492 char:180
    + …
    + ~
    The ‘<' operator is reserved for future use.
    Not all parse errors were reported. Correct the reported errors and try again.
    + CategoryInfo : ParserError: (:) [], ParseException
    + FullyQualifiedErrorId : RedirectionNotSupported

    1. Avatar photo
      Paul Cunningham

      Sounds like you’ve downloaded a bunch of HTML and not just the script.

      1. Bob Evans

        No if I copy that same file to the 2012 server it runs fine but on the 2012r2 server it does not.

        1. Avatar photo
          Paul Cunningham

          I can’t see your file so I’ve no way to know for sure. But the error you’ve provided has strings like “form accept-charset=”UTF-8″” that don’t exist in the PowerShell script. Which makes it sound to me like you’ve gone to Github and done right-click -> download on the script’s file name.

          If you do that it downloads a bunch of HTML that isn’t part of the script (if you open it in an editor and see DOCTYPE HTML at the start then that will confirm my suspicion).

          So there’s not much else I can suggest without being able to see your system, other than going back to Github and making sure it’s downloaded properly, or download it from TechNet instead.

  77. F21

    Thank you for the excellent script!

    Would be even better, if contain additional column: Total Mailbox And Archive size together.

    Mb should be MB 😉

  78. Cedric


    Thanks for this script, a really good Job..

    Is it possible to start the script and select only user in my OU ?
    example : -OrganizationalUnit “ou=MyUsers,dc=Domain,dc=com” ?

    Thanks for your reponse…

  79. ek

    Hi Paul,

    I try to run the script, but output by below error message

    Import-Module : The ‘C:Windowssystem32WindowsPowerShellv1.0ModulesActiveDirectoryActiveDirectory.psd1’ module ca
    nnot be imported because its manifest contains one or more members that are not valid. The valid manifest members are (
    ‘ModuleToProcess’, ‘NestedModules’, ‘GUID’, ‘Author’, ‘CompanyName’, ‘Copyright’, ‘ModuleVersion’, ‘Description’, ‘Powe
    rShellVersion’, ‘PowerShellHostName’, ‘PowerShellHostVersion’, ‘CLRVersion’, ‘DotNetFrameworkVersion’, ‘ProcessorArchit
    ecture’, ‘RequiredModules’, ‘TypesToProcess’, ‘FormatsToProcess’, ‘ScriptsToProcess’, ‘PrivateData’, ‘RequiredAssemblie
    s’, ‘ModuleList’, ‘FileList’, ‘FunctionsToExport’, ‘VariablesToExport’, ‘AliasesToExport’, ‘CmdletsToExport’). Remove t
    he members that are not valid (‘HelpInfoUri’), then try to import the module again.
    At D:Get-MailboxReport.ps1:211 char:14
    + Import-Module <<<< ActiveDirectory -ErrorAction STOP
    + CategoryInfo : InvalidData: (C:Windowssyst…eDirectory.psd1:String) [Import-Module], InvalidOperatio
    + FullyQualifiedErrorId : Modules_InvalidManifestMember,Microsoft.PowerShell.Commands.ImportModuleCommand

    Can you please advise?

      1. wtm

        I get the same error when I run the scrip. Has anyone found a solution?

        Server 2012R2 with Exchange 2010

    1. Wayne

      This is because Windows 2012 runs Powershell 4.0 natively. When it tries to import the AD cmdlets, they are not compatible since the script is looking for 2.0. We had to run it from an Exchange shell on a Windows 7 workstation, not the server itself which was 2012.

  80. Marc Schnitman

    SOLVED! Had too many open connections at the console level. Knew it had to be something, stupid…

  81. Marc Schnitman

    I’m running directly on our on-premise Exchange 2010, which is a Server 2008 R2 OS.

    NOTE: I’ve changed sensitive information in the printout below, for obvious reasons.

    [PS] C:EXCHANGE 2010 SCRIPTS>.Get-MailboxReport.ps1 -all

    Security Warning
    Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your
    computer. Do you want to run C:EXCHANGE 2010 SCRIPTSGet-MailboxReport.ps1?
    [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”): r

    Welcome to the Exchange Management Shell!

    Full list of cmdlets: Get-Command
    Only Exchange cmdlets: Get-ExCommand
    Cmdlets that match a specific string: Help **
    Get general help: Help
    Get help for a cmdlet: Help or -?
    Show quick reference guide: QuickRef
    Exchange team blog: Get-ExBlog
    Show full output for a command: | Format-List

    Tip of the day #8:

    Command line SOS! Do you need help? Type:

    Help or -?

    You can choose what information to return when you view Help by using the Detailed, Full, and Examples switches:

    Help Get-Mailbox -Detailed

    VERBOSE: Connecting to MAIL.DOMAIN.COM
    VERBOSE: Connecting to MAIL.DOMAIN.COM
    VERBOSE: Connecting to MAIL.DOMAIN.COM
    Failed to connect to an Exchange server in the current site.
    Enter the server FQDN where you want to connect.: exchange
    VERBOSE: Connecting to exchange
    WARNING: Active Directory server settings remained unchanged.
    Collecting mailbox list
    Collecting report data

    DisplayName : USER
    Mailbox Type : UserMailbox
    Title : Project Consultant
    Department : COMPANY
    Office : Home Office
    Total Mailbox Size (Mb) : 4602
    Mailbox Size (Mb) : 4581
    Mailbox Recoverable Item Size (Mb) : 21
    Mailbox Items : 24542
    Inbox Folder Size (Mb) : 3396
    Sent Items Folder Size (Mb) : 1179
    Deleted Items Folder Size (Mb) : 1
    Total Archive Size (Mb) : n/a
    Archive Size (Mb) : n/a
    Archive Deleted Item Size (Mb) : n/a
    Archive Items : n/a
    Audit Enabled : False
    Email Address Policy Enabled : False
    Hidden From Address Lists : False
    Use Database Quota Defaults : True
    Issue Warning Quota : unlimited
    Prohibit Send Quota : unlimited
    Prohibit Send Receive Quota : unlimited
    Account Enabled :
    Account Expires :
    Last Mailbox Logon : 8/10/2015 1:58:20 PM
    Last Logon By : DOMAINuser
    Primary Mailbox Database : DOMAIN
    Primary Server/DAG : EXCHANGE
    Archive Mailbox Database :
    Archive Server/DAG :
    Primary Email Address :
    Organizational Unit : domain/Users

    This is all it outputs anytime I run that script, also it won’t output to a file. Beginning to suspect something wrong with PS? However, other Exchange PS commands do work.

    1. Avatar photo
      Paul Cunningham

      Maybe the script is getting blocked. It’s failing to connect to your Exchange server…. try simply copy/pasting the script contents into a new file and save that as a PS script and run that?

      1. Marc Schnitman

        I have done that too. Odd thing is that the first attempt fails, but second attempt succeeds. I had to “allow” the script as seen in the output. I have also tried copy/paste into a new file: A) directly from GitHub and B) from the actual download – same result regardless.

  82. Marc Schnitman

    For whatever reason, the script is only returning a report, on the screen, for one user. And it always reports that one, and only one user.

    Q1 = How do I get this to report for all users, I have used the “-all” option
    Q2 = How do I get it to either e-mail me the CSV or create a CSV to a provided path. I have used both the e-mail and filename options, neither work.

    1. Avatar photo
      Paul Cunningham

      Does tab auto-completion work for the parameters?

      For example if you type “Get-MailboxReport.ps1 -a” and then hit Tab does it auto-complete to -All?

      1. Marc Schnitman

        Yes, it does.

        1. Avatar photo
          Paul Cunningham

          So what is the exact command you’re running? And are you running it from an Exchange Management Shell or from a remoting session?

  83. Chris


    how could I get the mailbox creation date… the date the mailbox was created????

    1. Avatar photo
      Paul Cunningham

      Mailboxes have an attribute of “WhenCreated” that has that info.

      1. James Slack

        The field you are looking for is called “WhenMailboxCreated”.

        If you just need to know when all the mailboxes were created, you could do a simple command like get-mailbox | select Name,WhenMailboxCreated

        1. Chris

          Thanks James for your reply but this command does not support Company, Department Office fields.

      2. Chris

        Thanks Paul for your reply..

        What I need to do is Get-mailbox | Select-Object DisplayName, PrimarySmtpAddress, Company, Department, Office, WhenCreated | export-csv “c:outputfilename.csv”

        This command give me a blank in the “company, department & office” fields

        could you help pls

        1. Chris

          thanks Paul ur the man

  84. Pam


    Can you tell me how you schedule this powershell script in schdeule task to get the report in email on weekly basis. I’m specifically looking for what arguments i need to enter in the schedule task to get weekly email.

  85. Bill Bollinger

    I am trying to run the script on an Exchange server 2013 Windows Server2102 an continue to get Import-Module : The specified module ‘ActiveDirectory’ was not loaded because no valid module file was found in any
    module directory.
    At C:tempGet-MailboxReport.ps1:211 char:1
    + Import-Module ActiveDirectory -ErrorAction STOP
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : ResourceUnavailable: (ActiveDirectory:String) [Import-Module], FileNotFoundException
    + FullyQualifiedErrorId : Modules_ModuleNotFound,Microsoft.PowerShell.Commands.ImportModuleCommand

    Can you help me out. This usually means that this is the wrong version of the script file

      1. Erik

        “Install the ActiveDirectory module for PowerShell.”

        I raise you: “Mention this in the requirements for the script to run successfully” …

      2. RobS

        The Exchange servers in my organization don’t have the AD module installed presumably for a reason, so I cannot run the script at all. Bummer.

        1. Avatar photo
          Paul Cunningham

          You could install the Exchange management tools and the AD module on your workstation, or a management server, and run it from there.

  86. Neil

    Disregard my last Paul. All working great. Its Friday and im an idiot 🙁
    Thanks for your quick response.

  87. Neil

    No mods and im confident its not the script. Rather the way I am calling it.
    I was using quotes around the script name but not this time.
    I run this
    .Get-MailboxReport.ps1 -All

    And get this:
    Missing expression after unary operator ‘–‘
    At c:filepathGet-MailboxReport.ps1:184 char:10
    + — <<</<!–
    + CategoryInfo :ParserError: [], ParseException
    + FullyQualifiedErrorId : MissingExpressionAfterOperator

  88. Neil

    Thank you for your script Paul. Im having rouble running it though and am new to this.
    error is “You must provide a value expression on the right-hand side of the ‘-‘ operator. Which I am doing of course. Its referencing the -All or -Server parameter.
    Its Exch 2010 and im running from the server. I get the same error for each of the valid parameters.
    Any ideas please?
    Thank you

    1. Avatar photo
      Paul Cunningham

      What is the exact command you’re running?

      Have you modified the script at all?

  89. sam_in

    This script works perfect and getting report in the email if i use commands. I need to some help to configure this script in schedule task. Can you provide the steps to schedule this script in schedule task to get this report in the email in weekly or monthly period.

  90. James Slack

    Just to clarify my above comment.

    If we could have a script that would look at a mailbox and say that 15000 items that are 1.2GB in size are over 2 years old in the given mailbox, that would tell us everything we need.

  91. James Slack

    Hi Paul,

    I am trying to work out how you would write a script, which you can run against users to see how much email (item count and file size) they have over a certain age.

    The reason I would like this would be to work out which users to enable to Exchange 2013 Archiving first and justify what space we will recover.

    I’m not sure I have seen a cmd that would cover this though. My guess would be that this can only be done with something horribly complicated like EWS, but maybe you could suggest something I could use to write this that I am missing?

    Thanks as always

      1. James Slack

        Thanks Paul – I’ll take a look, that example is perfect.



  92. Essexboy

    Hi Paul, the script is running brilliantly when I manually trigger it via Powershell, however when I run the script from a Batch its popping up with the following message :

    Get-ActiveSyncDeviceStatistics : Operation is not valid due to the current stat
    e of the object.
    At C:ScriptsActiveSync ReportGet-EASDeviceReport.ps1:143 char:55
    + $EASDeviceStats = @(Get-ActiveSyncDeviceStatistics <<<< -Mailbox $Mailbo
    + CategoryInfo : NotSpecified: (:) [Get-ActiveSyncDeviceStatistic
    s], InvalidOperationException
    + FullyQualifiedErrorId : System.InvalidOperationException,Microsoft.Excha

    Are you able to assist? We are currently migrating from Ex2010 to Ex2013. Not sure if this causing the issue

  93. Avatar photo
    Paul Cunningham

    Alright, installed an Exchange 2010 server and found the bug. Anyone experiencing that issue should grab V1.04 from TechNet or Github. Let me know if there are still any issues.

  94. Todd L.

    I downloaded the new version and it will not run with any parameter. Gives message that file or all or not parameters.

    1. Avatar photo
      Paul Cunningham

      What is the exact command you’re trying to run? Which version of Exchange?

  95. Michael

    i have the same behaviour as Jason. run the script an nothing happens regardless of the paramter.
    script is not blocked and i am running Exchange 2010 .

  96. Jason

    When I run the script, regardless of what parameter I use, it does nothing but reloads the PS window. Am I missing something?

    1. Avatar photo
      Paul Cunningham

      Version of Exchange? Are the management tools installed? Checked your execution policy? Is the downloaded file itself blocked?

    2. Dan

      I’m also getting the same:

      Exchange 2010 SP2 UR7
      Running on one of the Exchange Boxes so the Management Tools are installed.
      Script Unblocked and execution policy set to Unrestricted

      Also tried with a remote PS session from my Windows 8.1 machine, this appears to run the command but then crashes the window when it looks like its about to retrieve the result.

  97. Razi

    Thanks for your reply Paul, Yes the script is written to require a parameter but I want to know if there is way to run it without parameter, Since you are a developer of the script I am requesting you to let me know how to run it without param as I am using it in my application which does not accepts any parameter and the design of my application is such a complex one which cannot be changed. You help will be highly appreciated.

  98. mark

    Grate Script Paul, could you add a tab for a retention policy if one is set and what it is?

  99. Sam_in

    Can you tell me where exactly i need to add email functionality to get the report in the email?

    1. Avatar photo
      Paul Cunningham

      V1.03 has been uploaded and includes email functionality. You can get it at the same links in the article above.

  100. Razi

    Hi Paul,

    The script gives error if I use it with out any parameter on the power shell command. It works fine if I use parameters.
    Can you please let me know , how to execute this script without a parameter, If I execute this without any parameter it should displays the same results as that of using “all” parameter. Thanks for creating such a great script.


    1. Avatar photo
      Paul Cunningham

      The script is written to require a parameter. Use -All if you want all mailboxes.

  101. Mark

    This is a brilliant script. Are you able to detail how to automate emailing this out as a scheduled task? I can see no Email To parameters within the script, I would love to get this sent to me automatically each week. Thanks!

    1. Avatar photo
      Paul Cunningham

      Seems like a useful feature. Watch this space, I should be able to add that in pretty soon.

  102. Razi

    Paul ,
    Great Script, Hats up for you.
    The script run great with in powershell window with all the parameters defined.
    Any idea how to execute this script from .Net C# with command line arguments like -all , -server etc. Any Help will greatly be appreciated

  103. Ramkumar

    Hi the script works perfectly alright
    However I would like to display server name / originating server name for a specific users
    What can be done

    1. Ramkumar

      Ahh actually I figured it out !!!

  104. Howard Emerich

    The out put has 2 columns, Total Mailbox Size (Mb) and Mailbox Size (Mb). What is the difference between them, other than the numbers that are reported? Is the first number including white space and the second the actual mailbox size?

  105. Hesta

    Hi Paul,

    How to use this script with selected database more 2 database ? let say I have DB_1 – DB_10 but we just need 2 database which generated on this script e.g DB_1 & DB_2.


    1. Avatar photo
      Paul Cunningham

      Right now the solution is to simply run the script twice, once per database.

  106. Eric

    Hi Paul,

    how can i execute your script if my database mailbox name is Mailbox Database 1159192321.
    Its possible? or i must rename the name first?


    1. Avatar photo
      Paul Cunningham

      If the database name has spaces in it then you’ll need to enclose the name in quotes.

      .Get-MailboxReport.ps1 -Database “Mailbox Database 1159192321”

      This is one reason that I tend to keep my database names short and without any spaces in them, eg DB01, DB02…

  107. Thomas

    Awesome Script! – Thank You so much for making life a little easier.

  108. Ludovic


    I’m French and so I use some others characters than you.
    I have to add : -encoding Unicode to get good letters.

    Thank you for this script.


  109. Anthony

    When I run the command on our 2008 server I keep getting Missing expression after unary operator ‘–‘. I confirmed powershell is 2.0 by running $host. Any ideas?

    1. Todd

      Make sure you are running the script while logged on to an Exchange server using the Exchange Management Shell.

      1. Anthony

        I am logged in to the exchange server and I also am using the Exchange Management Shell.

  110. James

    Hi Paul.

    Late to the party but when I run the script against any of our Exchange 2010 databases, I get:

    No mailboxes were found matching that criteria.

    I am not sure what I am doing wrong…

    1. Avatar photo
      Paul Cunningham

      What is the exact command you’re running?

      You can also try just running “Get-Mailbox -Database ” and see if that works, since that is all the script really does when you use the -Database option.

  111. Ghouse

    Hello Paul,

    I am poor at scripting. can you let me know how to send the output this script through email as attachment. Any help will be highly appreciated. Thanks

  112. Ghouse

    Hi Paul, this is an excellent script. Truely AWESOME. I need some help in sending the report through email. Please help!!!

  113. Carlo Wolter

    Hi Paul,
    thanks for the script… I was looking for a similar tool and this seems to fill my needs.
    But I have a tough time running it.
    EMS gives me twice a strange error message and dies gracefully… 🙁

    Environment: Windows Serrver 2008 R2 SP1 + Exchange 2010
    The error, translated back to English, is something like:
    Initializer type ‘Microsoft.Exchange.Diagnostics.ExTraceConfiguration’ generated an exception.
    + CategoryInfo : OperationStopped: (MYSERVERNAME.MYDOMAIN:String) [], PSRemotingTransportException
    + FullyQualifiedErrorId : JobFailure

    This error is printed on the console after:
    Collecting mailbox list
    and after
    Collecting report data

    I’m not a keep Exchange admin so I’m frozen at it…..

    Can you please give some advice ?


  114. ARX

    Hi Paul,

    I am looking for something that collects similar stats but for ActiveSync (Get-ActiveSyncDeiceStatistics) while combining some user AD fields such as their office location etc. Do you have anything in the works for something like that?

    Or can you suggest something?


  115. Jon

    Hi Paul,

    Thank you for this very useful script! Is there a way to add a column for Retention Policy? I tried adding it to the script manually, but apparently it isn’t a valid MailboxStatistics value.

    Thank you very much!

      1. Jon

        That explains it. That will be an easy fix. I appreciate your quick reply!

  116. Bernhard

    Hi Paul,
    this cript is very useful for us.
    I created a script like this – but i have a problem.
    I want to look in special mailboxes, which i find out in the script (Members of a special Group) for Mails older than 40 days,.
    Do you have an idea how i could rsolve this?

    Thank you

  117. Kelley

    I modified this script by adding a parameter for CustomAttribute1. This allows me to get a report for customer even though they have multiple databases.

    I’ve noticed that even though I start the script in exactly the same way for each customer, the column Deleted Items Folder Size (Mb) is not present in every report. It seems to be consistent. If it is not present in one customer’s report, it never is present there.

    Any ideas why this might happen?

  118. JoeS

    Hi Paul,

    Any idea why I would get “Starting a command on remote server failed with the following error message : The WinRM client sent a request to the remote WS-Management service and was notified that the request size exceeded the configured MaxEnvelopeSize quota.”

    This only happens on some users. When this happens, the csv file will be missing info related to Title, Department, Office, OU.


    1. Avatar photo
      Paul Cunningham

      When I’ve seen the issue myself it has only been when EMS connects to a particular CAS. After the CAS is restarted (eg for patching) the issue goes away. I’ve never really gotten to the bottom of it. A workaround is to connect your EMS to a different CAS.

  119. PeterPhi

    Thanks Paul.

    But if we run on Windows Powershell , it will be faster in Exchange Management Shell. I tested with windows 2008 r2

  120. Leng

    Hi Paul,

    are there any command to export all shared mailboxes with size?
    Seems like Get-mailbox -RecipientTypeDetails sharedmailbox -Resultsize unlimited with parameter totalitemsize is not valid.
    Get-MailboxStatistics doesnt support receipienttype/type (so i can filter user or sharedmailbox) either,
    Kinda stuck in between!

    1. Avatar photo
      Paul Cunningham

      Get-Mailbox doesn’t return TotalItemSize, but Get-MailboxStatistics does. So the answer is to pipe the output from Get-Mailbox into Get-MailboxStatistics.

      1. PeterPhi

        Hi Paul,

        When i run this script on windows 2012 powershell i have the problem, please help. ((with exchange management shell is ok),

        Cannot process argument transformation on parameter ‘Identity’. Cannot convert value “test01” to type
        “Microsoft.Exchange.Configuration.Tasks.UserIdParameter”. Error: “Cannot convert hashtable to an object of the
        following type: Microsoft.Exchange.Configuration.Tasks.UserIdParameter. Hashtable-to-Object conversion is not
        supported in restricted language mode or a Data section.”
        + CategoryInfo : InvalidData: (:) [Get-User], ParameterBindin…mationException
        + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-User
        + PSComputerName : ex13

        1. PeterPhi

          Hi Paul,

          Please help me.

          Thank you.

        2. Avatar photo
          Paul Cunningham

          I get the same error. All I can suggest right now is that you run it using the Exchange Management Shell, as that works fine.

  121. Dhillan

    Paul – thanks for this wonderful script. I have used it over the past 2 years now on a number of deployments that i have done and clients are really appreciative of this.

    I however have been trying to run the same script on an Exchange 2013 deployment, the script runs fine except that I do not get information on the StorageLimitStatus. My understanding that there has been changes made to the store and Exchange Server 2013 Information Store does not cache the values of mailbox quotas.

    I am not the best at powershell and have seen that there are ways to get around this but have not been successful. Is there a chance that you will update this script so that it would work on Exchange 2013?

    1. Avatar photo
      Paul Cunningham

      You’re right, that status is no longer reported in Exchange 2013. To get the answer you’d need to compare the mailbox size value to the quota (if any is set) on the mailbox (which can be set on the mailbox or the mailbox database).

  122. Allen

    I wonder if it is possible for this script to run for only the users with hidden mailboxes? I’ve tried altering the script and have had no success. I’m trying to find all of the hidden addresses with who has full and/or read permissions to the hidden addresses listed, but I could do the permissions part manually.

  123. Tim McCarty

    Paul – I made some additions / changes to your script – if you would like I would be happy to send it to you for your review / use.

    Thanks again for providing such a stellar script.

    In the interest of full disclosure – i will say that the changes I made do NOT improve the functionality (memory use, etc.) of the script – I mostly have it collecting more data – and added an option for quickly testing in new environments.

    -Thanks again, Tim

    1. Avatar photo
      Paul Cunningham

      I am always happy to hear that people are tailoring the script for their own needs 🙂

  124. Tim McCarty

    Paul – thanks for this – I am wondering about running this script in very large environments. I am presently working in an environment with over 80,000 mailboxes and the script is taking a very long time to run (in excess of 4 hours) and the working set (RAM) after 4 hours is 7 GB. I am also seeing this error in the console ” Processing data for a remote command failed with the following error message: Objects cannot be added to a closed buffer. Make sure the buffer is open for Add and Insert operations to succeed. For more information, see the about_Remote_Troubleshooting Help topic.
    + CategoryInfo : OperationStopped: (System.Manageme…pressionSyncJob:PSInvokeExpressionSyncJob) [], PSRe motingTransportException + FullyQualifiedErrorId : JobFailure”

    Anyway the point and my question – have you considered any improvements for the script when working with very large data sets and/or can you point me to any helpful resources for improving the script myself?

    Thank you for your time and attention!

    1. Avatar photo
      Paul Cunningham

      In a similarly sized environment (where I developed early versions of that script) I never ran it for the entire organization in one go because yes, it takes forever, and yes, it eats a huge amount of RAM.

      Instead I would run it using the -Server or -Database parameters to just get the specific info I needed.

      Perhaps there are more memory-efficient PowerShell techniques that could be used to handle very large scenarios like that but I haven’t looked into it.

  125. jay

    sorry – should have been clearer with what I was chasing above. i can get the user to where this is forwarding by putting in the following line:

    $userObj | Add-Member NoteProperty -Name “Forwarding Address” -Value $mb.ForwardingAddress

    but ideally I would like to have the actual email smtp address but I don’t know how to get it using the ForwardingSmtpAddress property (seems I need to get this from Get-Mailbox instead of Get-Mailboxstatistics??)

    Also, I can get all the smtp addresses by using:

    $emailaddresses = [string]::Join(“;”,($mb.EmailAddresses | Where-Object {$_.PrefixString -ceq “smtp”})

    which is fine but I’d ideally like to remove the smtp: part from the start of each email address. Maybe I’m just being picky on this one… Thanks.

    1. Avatar photo
      Paul Cunningham

      Seems like you’re on the right track and it is just string formatting challenges to solve now 🙂

  126. jay

    Hi Paul

    Thanks for the great script – works like a charm. Can you point me in the right direction to add two extra columns? I would like to add forwarding address & all other smtp addresses (maybe seperated by a colon or similar). I’ve managed to do this in my own script but it’s fairly primitve and ideally would like to intergrate into your script but I’m not sure how to go about this. Cheers

  127. Artie


    Thank you for this great script. I am trying to tweak the powershell to get it to show me the StorageLimitStatus but cannot seem to get it to work. I have added Storage LimitStatus to the $stats list (Line 154) and added a new row like the others (Line 179). The heading shows up on my CSV, but I get no data. The two lines as I have them in my code are as follows:

    154: $stats = $mb | Get-MailboxStatistics | Select-Object TotalItemSize,TotalDeletedItemSize,ItemCount,LastLogonTime,LastLoggedOnUserAccount,StorageLimitStatus

    179: $userObj | Add-Member NoteProperty -Name “Limit Status” -Value $mb.StorageLimitStatus

    Any help is greatly appreciated, and thank you again for this great script!

  128. Deepak

    Thanks for wonderful script. Worked like charm. Keep up good work Paul!

  129. Manjunatha

    Dear Paul, Excellent script 7 thank you for your effort, sharing it freely for public.

    I have a request – Is there a possibility to add a column to fetch email ID in the script?

    1. Avatar photo
      Paul Cunningham

      I could add that to a future version, but I really encourage people to feel free to customize the scripts to suit their own needs. It is a good way to learn PowerShell if you are not already experienced with it.

  130. James Arellano

    Hello Paul, this script is a great help…. question, is there any way to incorporate

    “Get-MailboxFolderStatistics –FolderScope Inbox,SentItems,DeletedItems”

    into this reporting script? ive tried but failed with piping.



    1. Avatar photo
      Paul Cunningham

      I’ve got a few improvements planned and those are on the list. Stay tuned.

  131. Dennis Hartmann


    phenomenal script! I did, however, run into a weird thing. When I filtered the spreadsheet to display the archives of users it only showed one, versus at least 15-20 people’s archive on my Exchange 2010 SP3 server, Any clue as to why this could display wrong data?

      1. Dennis Hartmann

        Thanks Paul,

        I simply ran the -all condition to get as much info out of our Exchange environment as possible. We have 4 DBs, 3 with quota on mailbox size and one dedicated as the “Archive DB” with no quota. in addition what your script provides, I’d like to see how my archive DB is growing in size. So far, we only have company executives Archive enabled, fearing the DB would grow out of proportion if it were enabled for all users.

        Again, thanks Paul!


        1. Avatar photo
          Paul Cunningham

          I see. What you’re getting then is regular mailboxes that are sitting on your archive DB.

          I’ve got a newer version of the script that does include archive mailbox stats in the results. I’ll tidy it up a bit and release an update soonish 🙂

  132. Peter Raychev

    This script very useful. Thank you Paul.

  133. Sachin Kumar Singh

    Hi Paul,

    Thanks a lot for this script.

    I need to use this script with -Server parameter, want to schedule this script to run on specific time and generated .CSV file should automatically sent to desired SMTP address. Your help to configure it.

  134. Jim Zaino

    I have a question the spreadsheet that is created with the -all parameter. I am being asked about the items column. What do the numbers in that column relate too.



  135. BLeonard

    Thanks for this script Paul. It works very well, and is a great foundation for learning more PS Exchange scripting techniques.

  136. Allen

    Paul, that was exactly the problem I was having. I was opening the Exchange Management Shell and then typing powershell to bring up the PS> prompt that I was seeing in the video. Running it strictly from the EMS works perfectly.
    Todd and Paul, thanks again for all your help. Great stuff and great script!

  137. Allen


    No difference. Here is an example of what I see in the EMS – the command seems to simply echo back but no CSV files or even errors or additional info is generated:
    PS C:scripts> “.get-mailboxdatabase -all”
    .get-mailboxdatabase -all
    PS C:scripts>

    1. Allen

      Typo – please excuse me. Here is the actual text from the screen ….

      PS C:scripts> “.get-mailboxreport -all”
      .get-mailboxreport -all
      PS C:scripts>


    2. Todd Nelson

      One thing that I see is very curious. The name of the script referred to in this thread is “Get-MailboxReport.ps1”. Therefore, the command being run should be “.get-mailboxreport -all”. So, I feel this is probably a typo.

      If it is still not running for you, I cannot think of anything else but to make certain the file is unblocked from running and that the report output is being sent to a folder that isn’t set to read-only.

      I am running Exchange 2010 SP3 hosted on WS2008R2SP1 with PowerShell 2.0.

      When I run the command, this is what I see…

      [PS] C:ToolsGet-MailboxReport>.Get-MailboxReport -all
      WARNING: Active Directory server settings remained unchanged.
      Collecting mailbox list
      Collecting report data
      WARNING: The user hasn’t logged on to mailbox ‘red.local/Users/DiscoverySearchMailbox {D919BA05-46A6-415f-80AD-7E09334BB852}’
      (‘5631bcc1-7f67-4600-9fcb-82e652b92d2f’), so there is no data to return. After the user logs on, this warning will no longer appear.
      Report written to MailboxReport-20130509-1346-1rFbV8.csv in current path.

      Directory: C:ToolsGet-MailboxReport

      Mode LastWriteTime Length Name
      —- ————- —— —-
      -a— 5/9/2013 1:46 PM 2594 MailboxReport-20130509-1346-1rFbV8.csv

      [PS] C:ToolsGet-MailboxReport>

    3. Todd Nelson

      Another thing I could recommend is to download the script again but to a new/different folder on your mailbox server and try to run again.

      1. Allen

        Thank you very much for all of your replies. Yes, there was a typo that you picked up. I’ve tried running:

        PS C:\> cd scripts
        PS C:scripts> .get-mailboxreport -all
        Collecting mailbox list
        Collecting report data
        No mailboxes were found matching that criteria.

        And tried running:

        PS C:scripts> “.get-mailboxreport -all”
        .get-mailboxreport -all

        And you see the results. Tried another download to another directory with the same results. Permissions are all fine. I am running Exchange 2010 SP1 rollup 8 on Windows Server 2008 R2 Datacenter with SP1 and powershell V1.

        Here’s what I see after a fresh download to the C:Tools directory (newly created directory with permissions rechecked):

        PS C:tools> get-executionpolicy
        PS C:tools> .get-mailboxreport -all

        Security warning
        Run only scripts that you trust. While scripts from the internet can be useful, this script can potentially harm your
        computer. Do you want to run C:toolsGet-MailboxReport.ps1?
        [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”): R
        Collecting mailbox list
        Collecting report data
        No mailboxes were found matching that criteria.

        Interesting. Different info on the screen this time though.

        Database names in the DAG are DAGDB1 and DAGDB2. Calling them in the -database variable doesn’t change anything either.

        1. Avatar photo
          Paul Cunningham

          You need to run it in the Exchange Management Shell or at least a PowerShell window where you’ve loaded the Exchange snapin.

          If you just open plain PowerShell and run it then you get no results, as you’re seeing.

          The next version of the script will account for that and give a more useful error if the snapin can’t be loaded.

  138. Allen

    I’ve been successful a few months back in manually running your excellent script but tried again today and nothing happens. No errors but no CSV files appear. Command line looks like this:
    PS C:scripts>”.get-mailboxreport -all” or “.get-mailboxreport” are accepted without any feedback.
    I am running this on the active mailbox server against a DAG in Exchange 2010. I must be missing something really simple! Advice?

    1. Todd Nelson


      Does the account you are running the script with a member of the “Organization Management” group? I don’t feel the account needs Enterprise Admins membership but may since the script seems to query AD.


      1. Allen

        My account is a domain admin and a member of the Exchange Organization Administrators. I can try adding myself to the Organization Management group to see if that makes any difference. Will update in a few. Thank you.

  139. Todd Nelson

    I LOVE THIS SCRIPT! I’ve been using it for a while and it helps me to identify “dead” mailboxes, their sizes, etc. However, I recently ran into an issue that I am unable to figure out.

    If I run the script against my lab environment (or most any other for that matter) with Exchange 2010 SP3, I receive information for all of the headers…

    “DisplayName”,”Title”,”Department”,”Office”,”Enabled”,”Expires”,”Last Mailbox Logon”,”Last Logon By”,”Item Size (KB)”,”Deleted Item Size (KB)”,”Items”,”Type”,”Server”,”Database”

    But, I ran into a situation where two of the headers do not show in the report. And these headers (and info) are quite important to determine our migration strategy. The two headers that do not show are…

    “Item Size (KB)”,”Deleted Item Size (KB)”

    I am running the same command and the same switches (using server name) but the results are different in this particular environment.

    Paul, any ideas why this might be occurring?


  140. Tim

    Can the script be modified to include the active directory distinguished name (ID and container) ?

    1. Avatar photo
      Paul Cunningham

      Sure. I would certainly encourage you to look at the code and modify the script to suit your own needs.

  141. Evan Barrett

    Hi Paul.

    First off, GREAT script!

    Is there a way to break down the stats by date range per mailbox? Example:
    Items 0-15 days, Size 0-15 days, Items 16-30 days, Size 16-30 days, etc.?

    1. Avatar photo
      Paul Cunningham

      I guess you could use EWS to analyse the mailbox contents but I imagine it would slow down the script enormously.

  142. Shane Bryan

    thanks Paul. what happened is i have a few scripts set to run automatically via task scheduler, i inadvertently deleted the task that run this one – which had all the parameters so it would run as intended.

    i was trying to run it manually, without those – sorry about that 🙂

    Cheers Shane.

  143. Justin

    This script is great, a real time saver. I do have one question. We have 2 MB servers that are in a DAG. When I run against one I only get about 1/4 of the mailboxes returned. I know they’re all on both as we flip back and forth on mount points when we need to to perform maintenance (and the DB sizes are the same on both). Any idea why only one would return full results and the other incomplete?


    1. Avatar photo
      Paul Cunningham

      The -Server parameter for the script isn’t really suited to DAGs. That is probably because when I first wrote it there were no DAGs in the environment I was working in.

      The ServerName on a mailbox that is hosted on a DAG is misleading. I believe it gets stamped with the server name that the database was active on at the time the mailbox was created, but doesn’t update as active databases switchover.

  144. gadmee

    How can i get the first name & email address of the users in the csv file?

  145. Scott

    Hi Paul,

    Great script and have been using it for a couple years.

    Over the past couple days I have been getting the following error;

    Parameter cannot be resolved using the specified named parameters. At line:1 char:24

    Any ideas?


    1. Avatar photo
      Paul Cunningham

      Have you modified the script or upgraded your version of PowerShell or something like that?

      Note also that some combinations of parameters can’t be used. Eg, you can’t use -Server and -Database together.

      1. Scott

        thanks for the quick reply.

        it ended up being UAC settings set too high.


        1. Shane Bryan

          I’m getting this same error now as well.

          No updates on the mail server. No PowerShell upgrades but when I try and run it, I get;

          [PS] C:psscripts>.Get-MailboxReport.ps1
          C:psscriptsGet-MailboxReport.ps1 : Parameter set cannot be resolved using the specified named parameters.
          At line:1 char:24
          + .Get-MailboxReport.ps1 <<<<
          + CategoryInfo : InvalidArgument: (:) [Get-MailboxReport.ps1], ParameterBindingException
          + FullyQualifiedErrorId : AmbiguousParameterSet,Get-MailboxReport.ps1

        2. Avatar photo
          Paul Cunningham

          You need to specify at least one parameter, -all, -server, -database, etc.

  146. Trevor

    Had some trouble getting this to work. When you typed Get-M it autocompleted the rest for you, It did not do this for me, I tried typing out the whole command but kept getting an error that it could not find the script. I had to type out


    with the . in front before it would run. spent about 10mins before I figured that out…… Sure was much easier when you could open exchange 2003 and it told you how big the mailboxes where in a GUI.

    Good article though, thanks for the help.

  147. Oleg Tarasov

    Hi Paul,

    I have modified your script to give information on online Archive if one is enabled. Insert my code in $userobj section:

    $userObj | Add-Member NoteProperty -Name “Database” -Value $mb.Database
    #========Online Archive code================
    if ($mb.ArchiveDatabase)
    $astats=$mb | Get-MailboxStatistics -Archive
    $userObj | Add-Member NoteProperty -Name “Archive Item Size (Mb)” -Value $astats.TotalItemSize.Value.ToMB()
    $userObj | Add-Member NoteProperty -Name “Archive Deleted Item Size (Mb)” -Value $astats.TotalDeletedItemSize.Value.ToMB()
    $userObj | Add-Member NoteProperty -Name “Archive Items” -Value $astats.ItemCount
    $userObj | Add-Member NoteProperty -Name “Archive Server” -Value $astats.ServerName
    $userObj | Add-Member NoteProperty -Name “Archive Database” -Value $astats.Database
    } else {
    $userObj | Add-Member NoteProperty -Name “Archive Item Size (Mb)” -Value “”
    $userObj | Add-Member NoteProperty -Name “Archive Deleted Item Size (Mb)” -Value “”
    $userObj | Add-Member NoteProperty -Name “Archive Items” -Value “”
    $userObj | Add-Member NoteProperty -Name “Archive Server” -Value “”
    $userObj | Add-Member NoteProperty -Name “Archive Database” -Value “”
    #=====Online Archive code ends==================

    Also to support non-latin characters in your report and to be able to open straight with MS Excel change your export command to
    #========New export code=================
    $report | Export-Csv -Path $reportfile -NoTypeInformation -delimiter “;” -encoding “utf8”
    #========New export code end=================

  148. Arras

    Great information on all your posts.
    I’m getting this error:
    WARNING: Error initializing default drive: ‘Unable to find a default server with Active Directory Web Services running.’.

  149. Another Paul

    Getting her late to the party but a very awesome script! Great dialog in the thread as well for situation-specific needs!


  150. John Panicci

    Love the script…Is it possible to add Online Archive MB as a column? I’d like to determine the size of each Archive MB as well.

    1. Avatar photo
      Paul Cunningham

      It is something I want to add in the next version, when I have time to do a few updates to it.

  151. steve


    Great script. I am trying to figure out how to get one more field added, all SMTP addresses (aliases) for all users. How can I accomplish this.

    I typically do the following:Get-Mailbox | Select DisplayName, Alias,PrimarySMTPAddress, @{Name=’EmailAddresses’;Expression={[string]::join(“;”, ($_.EmailAddresses))}}

    I am not sure how to integrate that here.

    Thanks for the help!

    1. Avatar photo
      Paul Cunningham

      At about line 185 add these lines:

      $emailaddresses = [string]::Join(“;”,($mb.EmailAddresses))
      $userObj | Add-Member NoteProperty -Name “SMTP Addresses” -Value $emailaddresses

  152. Kelley

    I have customers who have multiple databases for their mailbox. Is there a way to alter the -database paremeter to analyze all databases that begin with a specific set of characters?

    1. Kelley

      I think I’ve found a way to resolve my issue. I added these lines in the appropriate places in the script:

      [Parameter(ParameterSetName=’CustomAttribute1′)] [String]$CustomAttribute1,

      if($CustomAttribute1){ $mailboxes = @(Get-Mailbox -Resultsize Unlimited | where {$_.CustomAttribute1 -eq $CustomAttribute1} ) }

      This allows me to report on a subset of my users regardless of what database their mailbox is in. It does take a while to gather the matching users before processing but if I schedule this and other variations to run at night it should not put a crunch on the server. I already run nightly scripts to set the proper value for CustomAttribute1 for users.

      This is a really nice script that is well documented and I truly appreciate it.

  153. Ken

    Thank you much and great work as always. Anyone know a way to add the Sent Items to the report? TotalSentItemSize to the Select-Object line and $userObj | Add-Member NoteProperty -Name “Sent Item Size (Mb)” -Value $stats.TotalSentItemSize.Value.ToMB() to the PS object. The script runs fine but does not output the Sent Items value.



  154. maddison

    To setup a monthly mailbox report just create a cmd batch file with the following command line in it, then set it as a task on the exchange server to run each month:

    C:WindowsSystem32WindowsPowerShellv1.0powershell.exe -command “. ‘C:Program FilesMicrosoftExchange ServerV14binRemoteExchange.ps1’; Connect-ExchangeServer -auto | “C:scriptsGet-MailboxReportMin.ps1 -all

    All the Beast Matt

  155. Robert

    This is really handy. Thanks!

  156. gnikolic

    Hi Paul!
    Thanx for sharing a script. One question. Is there a solution to add another value for get-mailbox with prohibitsendquota option. It would be usefull to get that info with all this usefull info.


  157. Alex G.

    Great Script, i love it…..

    I am new in Powershell World.

    But how can change the Field Separator from “,” to “;”.

      1. Alex G.

        Thanks, it works perfectly…

  158. MyITGuy

    Hey Paul. Great script outside of a couple minor suggestions.

    If the script requires a specific version of PowerShell; include the following:

    #requires -version 2
    write-host “Can only run on v2.”

    Also, it may be a better choice to use, “Set-ExecutionPolicy RemoteSigned” instead of “Set-ExecutionPolicy Unrestricted”


  159. Igor

    The script is perfect the only thing that would make it even better for me is to include the following: IssueWarningQuota, ProhibitSendQuota, ProhibitSendReceiveQuota. Any chance you could do it?

  160. Rolando Rodriguez


    I’m trying to run the script, however my databases have users from 3 seperate child domains. The report runs through for the local domain where the Exchange servers are hosted, but throws errors about not being found on the Domain Controller. I have a similar issue when I have to do exports and actually define the DC for the other child domain to pull an export. Any way this can be addressed in the script?

    1. Avatar photo
      Paul Cunningham

      At about line 130 in the script is the series of Get-Mailbox commands for the various all/server/database scenarios. You can modify those lines to specify a DC if you need to.

      Interesting that you’re having that problem at all. The script is designed to ignore default scope and search the entire forest, so it should find any mailbox regardless of child domains.

      1. Rolando Rodriguez

        Once it ran against the whole Server, it DID pull me back the info for the mailbox size and item count, but it didn’t pull back the AD info for the mailbox except mailbox user name. At the end, it did what I really needed, so THANK YOU!

  161. Amir


    Many thanks, your video was greatly helpful in understanding teh script’s functionality

  162. peter

    Hei Paul,

    Is there a way to suppress the first row?
    Aka, only having in data in the file and not the property name on the first line.


  163. Thomas

    Hi Paul,

    I am new to exchange scripting, and have been tasked with writing a script that will display all user’s that have email forwarding enabled. I need to export the data to an excel spreadsheat, containing the user’s name, primary email add and where they are forwarding to. I would appreciate any help or advice,


  164. Adam W

    Is it possible to get this script to report on mailboxe sizes based on the Office the person(s) are located in?

    1. Avatar photo
      Paul Cunningham

      Anything is possible with PowerShell mate 😉

      I would encourage you to look at the script code. Look at how the parameters are defined. Look at how those parameters correspond with the Get-Mailbox commands. You should be able to quickly see how to add that functionality you want.

  165. Jesse


    Thanks for the great script. I modified the Total Item Size and Deleted Item Size ToGB() because of the size of the mailboxes I am dealing with. I was wondering how I could format the values to 2 decimal place ex 9.65 right now it is displayed as 9. I tried figuring this out on my own but I am a powershell noob.

    Thank you

      1. Roderick

        the formatting works perfect when you run a single command as instructed on the linked site, but I have not been able to incorporate it in the script … yet 🙂

  166. Ramesh

    Excellent One.

    how to get mailbox details which includes the Servername, databasename, username – ,maybe display name etc.

    I gave the command as follow.

    get-mailbox -database dbname -server servername. But getting ambigous error. Can you please help me out in this.

  167. Peter Davidse

    I have an issue with the saved report.
    The first characters of the file are not “normal” characters.
    When using the report in Linux the file is being identified as a assembler file, not a text file.
    How can i fix this in the report generated instead of writing a workaround in my scripting language on the linux machine?

    Cheers, Peter

    1. Avatar photo
      Paul Cunningham

      Maybe try playing around with the -Encoding options for Export-CSV

  168. PC

    how can you sort the office, department and Total item size in the script?

  169. JC

    Dont suppose you could give us a ZIP file of this script. We dont allow direct internet downloads of PS1 extentions.

  170. Ytsejamer1

    Just wanted to drop a note of thanks for this script. I’ve been cobbling together a couple different reports to get me (and my supervisors) what we need. That was excellent. Cheers!

  171. Peter Davidse

    I am in Norway and the DisplayName contains ØÆÅ characters that are not in the generated reports, there they are substituted by a questionmark.
    Do you have a fix for that?

    1. Avatar photo
      Paul Cunningham

      Hi Peter, someone else encountered the same problem and fixed it by adding the -encoding switch to the Export-CSV command towards the end of the script


      Export-Csv -encoding ‘unicode’

      1. Peter Davidse

        Thanks, that worked perfectly!

  172. Ben

    Nice script. But i have a question, could you advise on how i can generate a report that will include the “date” a mailbox is disbled. In otherwords, the disabled date for all disabled mailboxes.

    Thank in anticipation.

    1. Avatar photo
      Paul Cunningham

      Do you already know how to retrieve the disabled date for a mailbox, and just want to know how to incorporate that into the script? Or are you also asking how/if its possible to retrieve the disabled date itself?

  173. Alagar

    By executing the following command it is giving the full report,
    .Get-MailboxReport.ps1 -full -filename e:allmailbox.csv


  174. Alagar

    very nice Script, Works perfectly for me with limited count.

    I have 500 mailbox, but i am getting only 139.

    .Get-MailboxReport.ps1 -server Exmbx02 -filename e:allmailbox.csv

    Please advise to get the full mailbox report.


  175. Vivek Malik

    Hi Paul,
    How can i get output of EmployeeType and EmailAddresses in this script.


  176. david sia

    Paul when i run the script I get:

    WARNING: Error initializing default drive: ‘Unable to find a default server with Active Directory Web Services

    but then it looks like it runs…



  177. narasimha

    Can i run ..powershell command as the following requirements.
    1 ) DLG Creation
    2 ) RMB Creation
    3 ) moving mail box from one location to another location ( Database )
    4 ) how to view log if we applied succesfully p-shell commands

  178. Rafi

    Hi Paul,

    Thanks Exactly what i was looking for, Is it possible for you to add the option to email the report.


  179. peter

    Hi Paul,
    I ran your script, it worked fine, thank you. I summed the Mailbox and deleted items they added up to 112Gb, but my two edb files are 86Gb and 45Gb, any idea wat is using the extra 20Gb? Db maintenace runs nightly.

    1. Avatar photo
      Paul Cunningham

      Hi Peter,

      A few articles that may help you determine what is using the extra space.

      The AvailableNewMailboxSpace is the usual culprit though. Running this command will show you that stat for your databases:

      Get-MailboxDatabase -Status | ft name,databasesize,availablenewmailboxspace -auto

  180. IntroToLogic

    The script is awesome Sir and so are you of having written it!

  181. Brian

    Hi Paul,

    Great Stuff, is it possible to alter the script to display total mailbox size per user, currently it only displays, Item Size and deleted item size.


  182. Shane Bryan

    Thank you Paul, that did the trick.

    I now have 2 variables.

    $filetimestamp = Get-Date -UFormat %d%m%y
    $datatimestamp = Get-Date -f d

    $filetimestamp is appended to the csv file when it’s written.
    $datatimestamp is used in [$userObj | Add-Member NoteProperty -Name “Date” -Value $datatimestamp] and displays the date as “6/07/2012” inside the csv file

    Perfect! Thank you so much 🙂

      1. Shane Bryan

        Thanks again, I didn’t know about Get-Date -f d, so cheers for that 🙂

  183. Shane Bryan

    Possibly :p It was a while back now. Apologies if I’ve turned your beautiful script into some bastard child :-p

    1. Avatar photo
      Paul Cunningham

      Yeah I just don’t see it in the original. Modifications are fine, people should certainly feel free to tweak these scripts to suit their needs.

      So what is the goal of that extra property you’re trying to set? Is it so your SQL import knows which day the stats apply to?

      1. Shane Bryan

        Hi Paul, yep at present I manually edit the csv file and replace all the 020712 date data with 02/07/2012 manually.

        it doesn’t take long, but the more i can automate the better 🙂

      2. Avatar photo
        Paul Cunningham

        Try this:

        $a = Get-Date -f d

        $userObj | Add-Member NoteProperty -Name “Date” -Value $a

        You can use any variable name you want I’m just $a for the sake of example.

  184. Shane Bryan

    Hi Paul. I notice in the script that the variable $timestamp is used in 2 places?

    $timestamp = Get-Date -UFormat %dd%mm%yy
    $reportfile = “C:PSScriptsCopyMailboxReport-$timestamp.csv”

    this places the timestamp on the file name (which is invaluable)

    and also;

    $userObj | Add-Member NoteProperty -Name “Date” -Value $timestamp

    places the time stamp into the spreadsheet data itself, next to the user name, dept, mailbox size etc.

    in the csv file, the date is displayed as 060712 (when I run it today).

    is it possible, to have the date (in the data, not necessarily the file name – as it won’t like slashes) be in the 06/07/2012 format?

    that might require the creation of a second timestamp variable though just for the date inside the csv file?

    if i change the $timestamp variable to;

    $timestamp = Get-Date -UFormat %dd%mm%yy

    the date on the file, and in the data gets written as; 06d07m12y

    I don’t expect you to solve the worlds problems for us, but is there a link or something you can share that will educate me on how to achieve the date formatting I need?

    Cheers, Shane.

    1. Avatar photo
      Paul Cunningham

      Is this a modification you’ve made to the original?

      $userObj | Add-Member NoteProperty -Name “Date” -Value $timestamp


    Hi Paul,

    I want to be run powershell command for Send As permissions in exchange 2010 ….which command should be used normally I am giving manually in exchange 2010 console..can you post Send as permissions command and if you possible share all the basic commands etc..add permissions.. DLG Creation .. and RMB Creations

  186. Erik

    Excellent script, thanks for sharing!

    Works like a charm. One question though. How did you get excel to sort the csv file automatically?

    1. Avatar photo
      Paul Cunningham

      Not entirely sure what you mean. Excel has a Sort button, I usually just use that. Is that what you meant?

  187. Aziz

    Thanks for your help by providing this Scrip, However I have tried to us is from ( Exchange powershell and Windows Poershell ) and while trying to import it there is an error message :

    [PS] C:Scripts>import-module .Get-Mailboxreport.ps1
    Collecting mailbox list
    Collecting report data
    No mailboxes were found matching that criteria.


    1. Avatar photo
      Paul Cunningham

      Hi Aziz, this is a script to run, not a module to import. Please review the article above again, read the built-in help for the script, or watch the video. They all demonstrate how to run the script.

      1. Abdulaziz

        OOOh, YES, I have tested and it is working perfectly …. 🙂 Really Thanks

  188. Jon Schlatter

    Thank you, this script has been very helpful! I do have one question that on an issue I see when I use it.

    Each time I run it I see a number of errors saying the following. Please note the

    The operation could’nt be performed because object ” couldn’t be found on ”.
    + CategoryInfo :NotSpecified: (:) [Get-User], ManagementObjectNotFoundException
    +FullyQualifiedErrorID: : ,Microsoft.Exchange.Management.RecipentTasks.GetUser

    This happens to users that are in one specific domain (which I can query with no issues in AD Management). Would anyone have any ideas on what I can do to resolve this?

    1. Jon Schlatter

      Please disregard my previous post. I found the answer to my issue only moments later. I corrected the recipent scope and all is fine.

  189. David

    Hi Bryan, thank you for your answer.
    I do not have a sql database but only a intranet webs erver where to publish the html report.
    I saw the codee like this:

    $style = “BODY{font-family: Arial; font-size: 10pt;}”
    $style = $style + “TABLE{border: 1px solid black; border-collapse: collapse;}”
    $style = $style + “TH{border: 1px solid black; background: #dddddd; padding: 5px; }”
    $style = $style + “TD{border: 1px solid black; padding: 5px; }”
    $style = $style + “”
    $message.Body = Get-ExchangeServer | Select-Object Name,ServerRole | ConvertTo-Html -Head $style

    Where can i put this code in your script to have the csv to html report file?

    I tried to insert in the following part of your script code but but I did not get the html table file:

    $reportcount = $report.count

    if ($reportcount -eq 0)
    Write-Host -ForegroundColor Yellow “No mailboxes were found matching that criteria.”
    #Output single mailbox report to console, otherwise output to CSV file
    if ($mailbox)
    $report | Format-List
    $report | Export-Csv -Path $reportfile -NoTypeInformation ???–> in this part?
    Write-Host -ForegroundColor White “Report written to $reportfile in current path.”
    Get-Item $reportfile ?? or in this part?

    Thank you so much for you help.


  190. Shane Bryan

    David, do you have SQL reporting services available to you?

    We take the data from this script and it gets imported into a database for SQL reporting. It allows me to see weekly growth on mailboxes by department and user. I totally recommend that if you have the resources available to you. Perhaps that might be more useful than simply dumping it into a html file, using a database and reporting services will let you track growth, find the heaviest mail users – and if your company is so inclined, charge accordingly.

    Before I found this script we were going to spend a great deal of money on a reporting system that went through the Exchange server logs. This script coupled with SQL reporting has pretty negated that.

    Anyhoo, there IS a ConvertTO-HTML option you can use with PowerShell, this link may help.

    1. Ray

      Hi Shane,

      how is this done ? I am quite interested in doing this. Could you or any one else shed some more light on it ?


      1. Shane Bryan

        Hi Ray. I use the script that Paul kindly created with just a couple of slight modifications. My copy of it is here;

        One change was the folder where it dumps the csv file. The other change was appending the date to the filename of the csv file to create a history. I take no credit for this, from memory Paul helped me work that out also 🙂

        There is a scheduled task on our Exchange server that runs this script once a week. Another scheduled task then robocopies the csv file to a SQL server that’s running Reporting Services. We then convert the .csv file to a .xls file, cleaning some of the data up. This excel file is then fed into the reporting database and then displays in the report when that is run. I’d past an export of that, but there’s corporate information in it so here’s a snippet of it, with corporate info blurred out.

        The report can be filtered by date, department etc so the majority of the work here was in the quality of the report created by our appsdev person.

        It also drops down to show the users from each department and the size of their mailbox on those dates. It’s shows growth, but also shows when someones doing a mass delete in their mailbox (perhaps a pending resignation etc, so we make a note of this in case we have to restore it from tape at some point).

        So unfortunately my ability to help further is hindered by the fact that the majority of the awesomeness was done by our awesome report writer. They take the data dump from this file and turn it into something useful 🙂

    2. Ray

      Thanx a lot Shane.

      1. CRAZY IT guy

        Hi Shane,

        Can you please provide the code to import excel file to SQL reporting DB server

      2. Shane Bryan

        Hi CRAZY IT guy. It’s a standard INSERT

        First we edit the spreadsheet a bit by changing the date from 020712 to 02/07/2012 which is done manually, then our code to import it is;

        INSERT INTO [ExchangeReporting].[dbo].[MailboxReport]

        select *

        from [ExchangeReporting].[dbo].[MailboxReport-070512]

        Obviously things will change for your environment such as the database name etc, also the file name is changed for each import as well. I hope that helps.

  191. David

    Hi thank u a lot for your wonderfull script.
    I need to bublic it to may intranet site. How convert it in html formatted tablereport?

    Could u modify the script to add html export?

    I’m trying to modify it but I’m not able.

    Thank you very much.


  192. Animesh

    Have you ever considered using a txt or csv file as input? I am currently evaluating Petri’s script for the same and can’t specify an input file. After analyzing your script, I find my problem as it is. Can you suggest me a way where I can specify a TXT or CSV file as input for users?


    1. Avatar photo
      Paul Cunningham

      The script has a -file parameter for using a txt file as the list of users to generate the report for. The txt file should contain the list of mailbox users in a format that would work with Get-Mailbox, so that could be alias, email address, display name, etc.

  193. Lumir

    It seems that code
    #This is an aged mailbox, so we want some extra details about the account
    $user = Get-User $mb
    isn’t exact
    better is
    $user = Get-User $mb.Alias

    1. Avatar photo
      Paul Cunningham

      Seems to be working okay for me (although that comment about aged mailboxes doesn’t seem right, must have slipped in from another script).

  194. Bjarni Kristjansson

    This is brilliant, thanks
    e.s. I changed the export command to $report | Export-Csv -encoding ‘unicode’ -Path $reportfile -NoTypeInformation – because here in Iceland we have alot of strange Icelandic characters like æ á þ ð ó and so on!
    Nice work.
    best regards, Bjarni

  195. Shane

    Kalvin, as HotFix says, you will only be able to run this script either from with in the Exchange Management Shell version of the PowerShell console on an exchange server or from a computer that has the Exchange Administration tools installed onto it.

    You can use the following command to load the Exchange Management tools in a script though, if that helps or you have problems fiding the Exchange console.

    function Load_Exchange_Tools {
    if (-not (Get-pssnapin | ? {$ -like ‘Microsoft.Exchange.Management.PowerShell.e2010’})) {
    Add-PSSnapin Microsoft.Exchange.Management.PowerShell.e2010

    If you don’t have access to the tools, or your permissions don’t allow access to Exchange, you won’t be able to run scripts like this though.

    Rgds, Shane.

  196. HotFix

    @Kalvin – it looks like you are running that script from within a regular PowerShell console. You either need to load the Exchange snap-ins into that console, or instead run the Exchange Management Shell version of the PowerShell console (preferably IMHO). The Exchange Management Shell is installed on any computer you install the Exchange Administration tools on.
    Happy hunting!

    1. Kalvin

      I am actually running it remotely and I am not in Exchange admin group. I have been given readonly access. Does that suffice or I need to do more?

  197. Kalvin

    I am not familiar with Exchange. When I run the script I get these error:
    Can you help me find the missing links?
    PS C:Mailboxes> .Get-MailboxReport.ps1 -database ‘PWRExchangePWRE_MBX_2-2’
    Get-PSSnapin : No Windows PowerShell snap-ins matching the pattern ‘Microsoft.E
    xchange.Management.PowerShell.Admin’ were found. Check the pattern and then try
    the command again.
    At C:MailboxesGet-MailboxReport.ps1:89 char:27
    + $2007snapin = Get-PSSnapin <<<< -Name Microsoft.Exchange.Management.PowerShe
    + CategoryInfo : InvalidArgument: (Microsoft.Excha…owerShell.Ad
    min:String) [Get-PSSnapin], PSArgumentException
    + FullyQualifiedErrorId : NoPSSnapInsFound,Microsoft.PowerShell.Commands.G

    Get-PSSnapin : No Windows PowerShell snap-ins matching the pattern 'Microsoft.E
    xchange.Management.PowerShell.E2010' were found. Check the pattern and then try
    the command again.
    At C:MailboxesGet-MailboxReport.ps1:96 char:28
    + $2010snapin = Get-PSSnapin <<<< -Name Microsoft.Exchange.Management.Powe
    + CategoryInfo : InvalidArgument: (Microsoft.Excha…owerShell.E2
    010:String) [Get-PSSnapin], PSArgumentException
    + FullyQualifiedErrorId : NoPSSnapInsFound,Microsoft.PowerShell.Commands.G

    Import-Module : The specified module 'ActiveDirectory' was not loaded because n
    o valid module file was found in any module directory.
    At C:MailboxesGet-MailboxReport.ps1:124 char:14
    + Import-Module <<<< ActiveDirectory
    + CategoryInfo : ResourceUnavailable: (ActiveDirectory:String) [I

    Please Help!

  198. Alex Edwards

    I do not normally post comments on any website, but I just felt I had to this time!
    Thank you – you have made my job about a milliontimes easier with this script…and such a simple thing it is too when you delve into it.

    Why I had not thought of doing this sort of thing myself before I will never guess…but today, yes today Paul, you have made a new friend for life!

    Once again, thank you mate!

  199. Michael Boback

    Awesome script. Can you add functionality to show whether Exchange Archiving is enabled and the Total Size and Total Items in the archive? So far it seems the best way to check if archiving is enabled is to use Get-Mailbox | Select-Object ArchiveDatabase. Someone please correct me if I am wrong though. A value of null means archiving is disabled. I added some lines to the script and this worked.

    When I tried to use Get-MailboxStatistics -Archive | Select-Object TotalItemSize,ItemCount this seems to work, but if the mailbox doesn’t have archiving enabled it throws out an error. I’m new to powershell scripting so I don’t know the best way to add this to the script so it’s handled gracefully.


  200. ilantz

    Kickass script Paul! Thanks for sharing.

  201. Rajkumar

    Hi Paul,

    I have added one Ps1 file which is callinghaving one function. I’m able to run the function( ex: get-Mail….). All is well.
    Can you help me to know, how to remove the Ps1 file and the function Get-Mail… in my exchange server environment. I don’t want others to run this shell command, whenever i need the details, i ll run the script and get the data.
    Help me to remove the function and PS1 file in safe manner

      1. Rajkumar

        I followed this article to use get-databasestatistics function. I’m able to use this EMS shell command.

        I want to remove the new Get-Databasestatistics command from my exchange environment. If I remove the ps1 file from the scripts folder, will this shell command get removed? or do i need to un register the script in someway…? Kindly advice

        Thank you

      2. Avatar photo
        Paul Cunningham

        Yes, if you delete a script file you won’t be able to run that script any more.

    1. Chris Brown

      Why on earth would you want to remove that cmdlet? You know you can restrict who can run what cmdlet, right?

  202. Peter Watson

    Many thanks for this script, saved me many hours and lots of fingernails!

  203. Dan

    If you are getting the “No mailboxes were found matching that criteria.” message, make sure you are running the script in the Exchange Management Shell, this fixed it for me on Exchange 2007 and 2010.

  204. Tim

    This could be helpful. Is it possible to have the script run against just “room mailboxes” ?

    1. BR Thurr


      Go to line 75, and add this line underneath:
      [Parameter(ParameterSetName=’room’)] [switch]$room,
      Go to line 139, and add this underneath:
      if($room) { $mailboxes = @(Get-Mailbox $mailbox -RecipientTypeDetails RoomMailbox ) }

      Save it and run it with the -room parameter. I tested this and it works.

      1. Tim

        Thanks BR – put doesnt the switch (-mailbox, -database -server, etc) specify where to pull the mailbox information from? Therefore using ‘-room’ switch it would have to be followed by the actual room ? I am trying to pull all rooms from a database or server.

        Unless I am missing something. Thanks again !

    2. Avatar photo
      Paul Cunningham

      The mailbox type us already included in the report, so you could just run it without modifications and use Excel to filter the data afterwards.

      Another way would be to generate the list of room mailboxes into a text file and use the -file parameter when running the script.

      Or, yet another way, make a copy of the script and call it say “Get-RoomMailboxReport.ps1” and as BR suggests above change all the Get-Mailbox commands to add the “-RecipientTypeDetails RoomMailbox” parameter.

  205. ShaunH

    I have added to following values to show the Storage quotas as well

    $userObj | Add-Member NoteProperty -Name “IssueWarningQuota” -Value $mb.IssueWarningQuota.Value.ToMB()
    $userObj | Add-Member NoteProperty -Name “ProhibitSendQuota” -Value $mb.ProhibitSendQuota.Value.ToMB()
    $userObj | Add-Member NoteProperty -Name “ProhibitSendReceiveQuota” -Value $mb.ProhibitSendReceiveQuota.Value.ToMB()

    1. BR Thurr

      I have added these as well:

      $userObj | Add-Member NoteProperty -Name “Primary SMTP Address” -Value $mb.PrimarySMTPAddress
      $userObj | Add-Member NoteProperty -Name “Forwarding Address” -Value $mb.ForwardingAddress
      $userObj | Add-Member NoteProperty -Name “Hidden From Address Lists” -Value $mb.HiddenFromAddressListsEnabled

      Make sure that in your “Select=-Object” line (154 in the latest version), that you add these attributes into your select statement. For example:

      $stats = $mb | Get-MailboxStatistics | Select-Object TotalItemSize,TotalDeletedItemSize,ItemCount,LastLogonTime,LastLoggedOnUserAccount,HiddenFromAddressListsEnabled,ForwardingAddress,PrimarySMTPAddress

    2. BKK-Mac

      Hi ShaunH,

      I have added those lines to get storage quota and if I run the script against 1 mailbox, I can see those values but when I run against a database, those values are missing from the export CSV file.

      I have also added the values of BR Thurr and they are present in the CSV

      Any idea?


      1. Driguez


        did you get this solved eventually? I`m also having this issue with the script. Can only display it for one user but not for all in Mb.

        1. NK

          The issue is the Value.ToMB() setting as when it encounters a mailbox which has no value set this is returned as “Unlimited” which can’t be converted to MB and it causes it to fail.

          I got round that by setting up a conditional statement to test if the quota returns a value and attached to a variable and then calling that variable

          $ProhibitSendReceiveQuota = if($mb.ProhibitSendReceiveQuota.value){$mb.ProhibitSendReceiveQuota.value.ToMB()} else {“unlimited”}
          $ProhibitSendQuota = if($mb.ProhibitSendQuota.value) {$mb.ProhibitSendQuota.value.ToMB()} else {“unlimited”}
          $IssueWarningQuota = if($mb.IssueWarningQuota.value) {$mb.IssueWarningQuota.value.ToMB()} else {“unlimited”}

          $userObj | Add-Member NoteProperty -Name “MBIssueWarning” -Value $IssueWarningQuota
          $userObj | Add-Member NoteProperty -Name “MBProhibitSend” -Value $ProhibitSendQuota
          $userObj | Add-Member NoteProperty -Name “MBProhibitSendReceive” -Value $ProhibitSendReceiveQuota

  206. ShaunH

    Hi Paul
    How can we use this script and add the User Mailbox Quota in , so that it also shows in the csv file

  207. Carlos V

    It’s working now in the batch file, I just added the command to load Exchange Management Shell in the PS script.


  208. Zubeir

    Getting output below when running the scripts
    Collecting mailbox list
    Collecting report data
    No mailboxes were found matching that criteria.

  209. Carlos V

    Thank you for providing us this script, I run it fine from PS command but when I try to run it on a batch file it doesn’t fetch anything. Can you please help with the line to run it on a batch file?

    powershell.exe -noexit c:TempGet-MailboxReport.ps1 -all

    I get
    Collecting mailbox list
    Collecting report data
    No mailboxes were found matching that criteria.

  210. Simon Craner

    works great. What do i need to change the output file name to contain the server name it was run against?

    1. Avatar photo
      Paul Cunningham

      You can use the -filename parameter to specify your own file names.

  211. Shane Bryan

    thanks so much 🙂

  212. Shane Bryan

    Thanks for the great script Paul. I’ve removed a few of the objects I don’t need, and plan to schedule this to be exported to a SQL server so we can import the results into a database and report on mailbox growth per user.

    I’ve changed your script to remove the random number being added to the file name, but if you can give me some advice on how to alter the export location that would be fantastic as i’d like the file exported to a folder that will have everything in it xcopied to another location at set times.

    Eg: C:ExchangeReportExport

    Cheers from Aus, and thanks again Shane.

    1. Shane Bryan

      Oh worked it out…

      $reportfile = “C:PSScriptsCopyMailboxReport-$timestamp.csv”

      easy 🙂

      1. Avatar photo
        Paul Cunningham

        Yep, also I’ve added a -filename parameter to the latest version (1.1) just uploaded in the last few minutes if you wanted to grab that. It has a few other minor fixes as well.

  213. HotFix

    FYI I wrote a similar in concept script to generate Exchange 2010 mailbox billing reports in Excel directly. While it is a slightly different focus than what you are doing (in that it grabs all customer mailboxes or specific OUs, not databases or servers), perhaps you could recycle the Execl logic in my script to dump your data directly into Excel spreadsheet where you have already pre-formatted the attributes the way you want (which we also had to do) and save yourself a step or two:

    I hope it helps.

  214. Ahmed

    thz a lot fr the script, very useful

  215. Allen J

    Great script, but I am seeing something odd when I use the -server parameter. The number of mailbox objects listed in the EMC is 2498, but when I use the -server parameter it only processes about 1400 or so, not the full 2498. To get around that for now, I am using a generated user.txt file and using the -file parameter. Any ideas why the difference ?

    1. Avatar photo
      Paul Cunningham

      Are all the mailbox users in the same domain in AD, or different domains?

      1. AllenJ

        We only have one AD domain.

      2. AllenJ

        I recently tried the updated version and that seems to work just fine.
        Thanks again

  216. Tom G

    I had already tried it that way but I ran it again. See below. I get the same error. It doesn’t seem to matter how I run it. Can you help further? This is driving me nuts. I will watch the video as well.

    [PS] C:scripts>.Get-MailboxReport.ps1
    The term ‘.Get-MailboxReport.ps1’ is not recognized as the name of a cmdlet, function, script file,…….


    1. Avatar photo
      Paul Cunningham

      You’ve downloaded the Zip file and extracted the PS1 file to C:Scripts I take it?

  217. Tom G

    I guess I am a retard because I can’t get it to run. I keep getting the following error:

    [PS] C:Windowssystem32>c:scriptsget-Mailboxreport.ps1
    The term ‘c:scriptsget-Mailboxreport.ps1’ is not recognized as the name of a cmdlet, function, script file…..

    What am I doing wrong? I am not an expert with PowerShell but this shouldn’t be this hard. thanks

    1. Avatar photo
      Paul Cunningham

      Hi Tom,

      Navigate to the folder where you’ve saved the script file, then run it with:


      You’ll need to supply one of the parameters for which type of report you want to run. You can see the help info by running:

      Get-Help .Get-MailboxReport.ps1

      Or watch the video above for a demonstration.

      Hope that helps.

  218. Christa Wilson

    Nice report. I’d like to put it into a scheduled task for a weekly/monthly report that’s emailed to me. I’m wondering how to call upon the output file as it will change each time it’s ran.

    1. Avatar photo
      Paul Cunningham

      Hi Christa, probably two ways you could do that.

      1) Remove the file name randomization. So instead of

      $reportfile = “MailboxReport-$timestamp-$random.csv”

      have simply

      $reportfile = “MailboxReport.csv”

      2) The file name is stored as $reportfile, so if you’re adding email functionality to the script you can always reference the file name by that variable, no matter what the real name is.

    2. Avatar photo
      Paul Cunningham

      I’ve added a -filename optional parameter to the latest version (1.1) for those who wish to specify the file name instead of the randomly generated ones (actually I use -filename almost every time I run it now :))

  219. Kbart2000

    Hello Paul,

    Thanks again för sharing your script. Works great, I just have a question… How can I do to find the right character in the csv file .. I m having in my exchange swedish names with those: å,ä,ö.

    Is it a parameter to add ?

      1. Kbart2000

        When Im having a look at the csv file after I ran the script,
        If for example the name of the user is Åsa Bergström, the result in the csv file is ?sa Bergstr?m

        Its not the right character, I would like to get on my csv file the swedish characters like : the å the ä and the Ö instead of “?”

        Hope I m more clear now? 🙂

        1. David

          I know this is years old, but it came up high when I googled for the same problem…

          Add -encoding “unicode” when exporting to csv makes åäö show up

      2. Avatar photo
        Paul Cunningham

        Ah, I understand now. Not sure of the solution though, I’ll see if I can find something.

  220. turbomcp

    Thanks again paul for an amazing time saver(and also teaches me powershell)
    i only had one issue when i ran it through 2010 ps(dont know if it matters) using -file
    i got cannot move something about distinguage name cannot be used or must be used:) when using -ignorescope
    so i removed the ignorescope for the file part of the script and it ran like a charmer:)
    Thanks again
    Much appreciated

    1. Avatar photo
      Paul Cunningham

      Yep, little bug I need to work on there. If you have a multi-domain forest you’d just need to put your management shell session into viewentireforest $true mode to see all the mailboxes in the report.

      Or if you’re a single domain forest it doesn’t matter, script will work as you’ve modified it 🙂

  221. David Taig

    Hi Paul,

    Great report for Migrations. As I need the Alias to perform the migration, I have added this in the first column:

    $userObj | Add-Member NoteProperty -Name “Alias” -Value $mb.Alias

    I also added sort “Size (Mb)” -Desc

    I did run this on a combined DC and Exchange 2007 SP3 Server – Enabled and Expires is blank. OK on other Exchange 2007 SP3 Server, so seems issue having DC and Exchange 2007 together..

    1. Avatar photo
      Paul Cunningham

      Could you try commenting out the error suppression lines at the start of the script and see if it produces any errors on the combined DC/Exchange server?

  222. starchaser

    Fantastic! It worked. Great script.


  223. starchaser

    Well, I tested the -database parameter works with .GetMailboxReport.ps1 -database ‘ServerNameStorageGroupNameDataabaseName’

    However, .GetMailboxReport.ps1 -file does not work. I tried Display Name, Primary SMTP address, UPN but it doesn’t work. It creates a blank 9 byte csv file.

    1. Avatar photo
      Paul Cunningham

      Ah yep, see comment above. Try removing -ignoredefaultscope from the line:

      “if($file) { $mailboxes = @(Get-Content $file | Get-Mailbox -resultsize unlimited -IgnoreDefaultScope) }”

      I’ll add it to my bug list.

  224. starchaser

    I am trying to run this script using the -database or -file parameter and it’s generating a blank csv file. The csv file generated is of 0 bytes.

    1. Avatar photo
      Paul Cunningham

      That will happen if no mailbox info could be retrieved.

      For -database make sure you’re supplying a value that would work if you ran “Get-Mailbox -database “.

      For -file try removing the -ignoredefaultscope switch from the script line

      “if($file) { $mailboxes = @(Get-Content $file | Get-Mailbox -resultsize unlimited -IgnoreDefaultScope) }”

    2. Avatar photo
      Paul Cunningham

      I’ve added some script logic so that instead of creating a 0kb file it will instead show a warning that no mailboxes were found matching the criteria given.

  225. Jeff Strubberg


    Great script! I removed a few of the output fields (we only have one mail server and one mail database, so those fields weren’t meaningful for us). At the moment I am trying to sort the resulting csv file via the script to put the mailboxes in order largest to smallest. Could use some help getting this to work.

    Once I’ve got that figured out, this script is going to save me a ton of time. I’ve got it running as a schedlued task on my exchange server and emailing me the resulting csv on the first of every month.

    1. Avatar photo
      Paul Cunningham

      In the last Else block try adding a Sort-Object to the $report | Export-CSV line like this:

      $report | Sort-Object “Size (Mb)” -Desc | Export-Csv -Path $reportfile -NoTypeInformation

    2. Alagar

      how you scheduled this task, please provide the steps.


  226. Frank

    Never mind. Got it now. Still getting this message:

    Security Warning
    Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your
    computer. Do you want to run C:tempExchangePowerShellotherGet-MailboxReport.ps1?
    [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”): R

    I ran Set-ExecutionPolicy Unrestricted

    1. Avatar photo
      Paul Cunningham

      May also need to right-click the downloaded file, and in properties unblock it.

  227. Frank

    Getting this error message.

    [PS] C:tempExchangePowerShellother>.Get-MailboxReport.ps1 -database MBX1VPMbxDb-YNHH-002

    Security Warning
    Run only scripts that you trust. While scripts from the Internet can be useful, this script can potentially harm your
    computer. Do you want to run C:tempExchangePowerShellotherGet-MailboxReport.ps1?
    [D] Do not run [R] Run once [S] Suspend [?] Help (default is “D”): R
    Cannot process argument transformation on parameter ‘Database’. Cannot convert value “MBX1VPMbxDb-YNHH-002” to type “M
    icrosoft.Exchange.Configuration.Tasks.DatabaseIdParameter”. Error: “‘MBX1VPMbxDb-YNHH-002’ is not a valid value for th
    e identity.
    Parameter name: Identity”
    + CategoryInfo : InvalidData: (:) [Get-Mailbox], ParameterBindin…mationException
    + FullyQualifiedErrorId : ParameterArgumentTransformationError,Get-Mailbox

    1. Avatar photo
      Paul Cunningham

      Which version of Exchange?

      Try supplying the -database value as “serverstoragegroupdatabase” if you’re running Ex2007.

  228. Kerry

    Excellent script! Thanks for the work and the updates. I know that this will be used much by myself and the consultants I work with.

    Thanks again

  229. Josh

    Keep getting an error ….
    “Missing opening “(” after keyword ‘for’.
    At C:Scriptsget-mailboxreport.ps1:48 char:5
    + For m <<<< ore script details, a video demo, or to give feedback please go to:

    Am I missing something?
    Exch 2007

    1. Avatar photo
      Paul Cunningham

      Hi Josh, it is written for PowerShell v2.0. Try running:


      …to see which version you’ve got. If you’re on version1.0 you can try and edit the script to remove all that help info at the start, and see if that works, but I haven’t specifically tested it on v1.0 to check for any other issues.

  230. kevin


    I have an issue where the powershel is preventing my from runnin gthe script. ” the file is not digitally signed” is the complaint from the PS!!

    1. kevin

      scratch my last post. Its early in the morning here………………

    2. Avatar photo
      Paul Cunningham

      Hi Kevin, try changing your execution policy to unrestricted.

      Set-ExecutionPolicy Unrestricted

  231. Rinku


    good work paul, thanks for sharing,

  232. Chris

    Hi Paul,

    That script very useful, very well documented as well. I’ll try to improve it adding if the user has mailbox default storage limits.

    Thanks for sharing!

  233. Edward Walton

    question. is it possilbe to script a way to find all emails with attachments over 25meg.


    1. Avatar photo
      Paul Cunningham

      Not with this script, but perhaps with a script that utilizes Exchange Web Services.

      1. Edward

        thank Paul

        if you have time to point me in a direction of how to write that script…that would be great.

        this one is really good too.

      2. Avatar photo
        Paul Cunningham

        I haven’t done any EWS script development yet, so I don’t have anything to offer you right now. Although you’re not the first person to ask me for a script like that, so I think its time I started to get into it 🙂

        But in the meantime, to learn about using EWS the first place I’d go to is Glen Scales’ blog here:

  234. Avatar photo
    Paul Cunningham

    Script has had a major overhaul and re-release, so much so that I’m just going to call this new one V1.0 🙂

  235. Sorin

    Hi Paul,

    Can u make this script work with server parameter? So it can list all the mailboxes from the server at once.


    1. Avatar photo
      Paul Cunningham

      Sure thing. Actually I’m already working on that, will post an updated when I’ve got it finished.

      1. Sorin

        I’ve managed to do it by myself 🙂 and now works with server parameter.
        I modified your script and it works perfect.

        Many thanks Paul,

  236. Devang Patel

    This is Awsome. I tried it and works smoothly. Before using this scripte i used to get the results manually by just entering the commands every time.

    I have one query about the text file that we need to create for getting the results for particular users. which fileds should i enter in the text file.


    1. Avatar photo
      Paul Cunningham

      Display name, alias, or UPN should work. Take your pick. I usually just use display name.

      1. Yogish Acharya

        Hi Paul,

        I have one query on quota limit set as a default on those mailboxes where the actual mailbox quota limit value need to fetch from database. for example, If the MBProhibitSendReceive quota set on database is 1GB, mailboxes related to this database should show the report as 1GB ,in fact we are getting the report as unlimited. So i need a powershell command for the mailboxes, where it shows actual quota limit set on database along with other attributes of mailboxes. and one more thing on the same list, some mailboxes quota size not set as default value, it should fetch the exact value on same report. Hope you could understand my query. Please do the needful, would be a grateful to you. Thanks in advance

Leave a Reply