Exchange Server Large MailItem Script


UPDATE : 

1. Please take note we have increased the size limit to 150MB during on boarding the previous 25MB should no longer be an issue - see the announcement here: http://blogs.office.com/2015/01/12/whats-new-december-2014/

2 . I've handed this script over to someone else for maintenance and support. Please use the following link to get the latest version: https://gallery.technet.microsoft.com/PowerShell-Script-Office-54d367e

There has been a lot of requests from my customers for an easy way to find large mail items in mailboxes that are planned to be moved to Exchange Online.

As you are probably aware, items larger than 25MB are not moved to Exchange Online and this causes the move request to fail if LargeItemLimit is not specified and/or the items larger than 25MB isn’t removed from the mailbox (backed up to a PST).

You can read more about it here: http://support.microsoft.com/kb/2584294

It’s obviously not very feasible to start your move requests without knowing that you are going to hit these kind of problems, because you want those moves to be as smooth as possible. I’ll show you some tricks that I use to avoid starting the move request from scratch when this occurs, but that will be another article.

Initially, I wanted to start from scratch and write a PowerShell script based on Exchange Web Services, but luckily one of my colleagues (Dmitry Kazantsev) already had a great bunch of scripts based on EWS that he created. I have however made some extensive changes by consolidating all the scripts to functions in one single script and adding some additional horsepower to the script. It’s been working great for me.

The script uses Exchange Web Services to impersonate a user account and essentially gaining access to the mailbox to scan the items in each folder for the large item limit you specify. All the results are then dumped to a CSV file.

So how does this work?

First, download and install the Exchange Web Services 2.0 API here

Make sure you have Exchange Management Tools installed on the machine you will be running the script. If you are running the script on an Exchange Server you need to install the API on the server.

Now we need an account with impersonation rights to be able to read the mailboxes.

  • Create a service account in Active Directory - for this example I’ll use svc_ews@contoso.com

Now we need to assign impersonation permissions for this account.

For Exchange Server 2007 mailboxes:

  • Open Exchange 2007 Management Shell.
  • Assign impersonation permissions on the Exchange 2007 Client Access Servers (replace svc_ews@contoso.com with your service account created earlier):
Get-ExchangeServer|where {$_.Admindisplayversion.Major -lt 14 -and $_.IsClientAccessserver}| ForEach-Object {Add-ADPermission -Identity $_.distinguishedname -User svc_ews@contoso.com -extendedRight ms-Exch-EPI-Impersonation}
  • Assign impersonation permissions on the Exchange Server 2007 databases.
Get-MailboxDatabase | ForEach-Object {Add-ADPermission -Identity $_.DistinguishedName -User svc_ews@contoso.com -ExtendedRights ms-Exch-EPI-May-Impersonate}

For Exchange Server 2010/2013 mailboxes:

  • Permissions for Exchange Server 2010/2013 mailboxes (replace svc_ews@contoso.com with your service account created earlier):
New-ManagementRoleAssignment –Name:impersonationAssignmentName –Role:ApplicationImpersonation –User:svc_ews@contoso.com

Let’s cover the parameters that the script uses:

Mandatory parameters:

  • adminAccountName – Organization Management Administrator account
  • adminPassword - Administrator Password
  • serviceAccountDomain - EWS Service Account domain
  • serviceAccountName – EWS Service Account
  • servicePassword - Service Account Password
  • resultsFile – Results Export Filename
  • ItemSizeLimit - Item Size Limit

Parameters that are not mandatory:

  • ImportCSV  - List of mailboxes to import .
  • URI -  URI of EWS Endpoint.
  • archiveCheck - switch to only search archive folders.

If you want to target a subset of users you can use the ImportCSV parameter to specify a CSV file to read. The file needs a header called PrimarySMTPAddress and then the primary SMTP addresses of the mailboxes you want to target.

If you don’t specify the ImportCSV parameter the script will scan all mailboxes in the organization.

The URI parameter can also be specified if you want to use a specific EWS endpoint like https://webmail.contoso.com/ews/exchange.asmx.

If you do not specify the URI parameter the script will use Autodiscover for the correct Web Services URI for each mailbox.

And that’s it. Now you’re ready to rumble.

Copy the script to a folder of your choice and open Exchange Server 2010/2013 Management Shell.

To following is examples of the usage:

.\LargeItemChecks.ps1 -serviceAccountName svc_ews -serviceAccountDomain contoso.com -servicePassword P@5sword2 -resultsFile .\exportResultSet.csv -ItemSizeLimit 25
.\LargeItemChecks.ps1 -archiveCheck -serviceAccountName svc_ews -serviceAccountDomain contoso.com -servicePassword P@5sword2 -resultsFile .\exportResultSet.csv -ItemSizeLimit 25

It will run for a while depending on the size of your organization. The transcript log will also be created in the current directory.

The results file will look like this:

Until next time,

Michael Hall

Comments (39)

  1. Hi Todd,

    Things have been somewhat hectic in my life as of late, so I haven’t had time to look at the script. But thanks for providing me with the above feedback and fixes!! I will definitely update the script with the fixes. Will be working on it in my spare time, but will update this page once its done.

    Thanks,
    Michael

  2. Hi Zoltan, It’s your lucky day, I added archive support into the new version 1.2.7. If you specify the -archiveCheck switch it will search archive mailboxes only. This was only tested in my lab environment, so I hope it works in your environment. Michael

  3. Lance, would you mind communicating with me on the TechnicalRamblings mail addy. I’m not able to repro this, but I might have an idea why its happening, it just need someone to test the change I made 🙂
    Michael

  4. Hi Won Keat, You are correct, I’m busy investigating how MRS determines the size of an item to make sure we don’t get into a situation where we dont report on actuals that MRS would deem as large items. In the meantime if you are comfortable taking the chance I’d suggest changing the value to 1048576.

    Hi Maxime, Did you receive any exceptions that you can send me?

  5. Hey Tony,
    You could potentially use the output from the script as contentfilter properties in new-mailboxexportrequest cmdlet. I haven’t tried it myself yet, might be a good candidate for a follow up article.
    Michael

  6. Try forcing the EWS Endpoint by using the URI parameter. This way it wont utilize autodiscover to find the smtp address.

  7. Please find the latest version here
    https://gallery.technet.microsoft.com/PowerShell-Script-Office-54d367ea
    I’ve given this to someone else to manage going forward since I don’t have time to support the script going forward

  8. Hey Steve, I’ve had some other complaints around 401 Unauthorized. Unfortunately, I cannot repro it on my side. I have however updated the script to use a new credential mechanism for the EWS cred instantiation. Give it a shot and let me know. Michael

  9. Kyle says:

    Hi Michael, thanks for putting this together, will be much help once I get it going. When I run it I get "Exchange Server Management Tools not installed on this host". I have the management tools installed on the host I'm running the script from, I see the script does a check "$checkEMT12Installed = test-path -Path 'hklm:SOFTWAREMicrosoftExchangeServerv12AdminTools' " which is False, as that path does not exist in that registry location. Is there another location where I can check to confirm AdminTools are installed? I searched my registry and don't find this Key anywhere, but I have confirmed Exchange Admin Tools are installed. Thoughs?

    Exchange 2007 sp3 / Host is Windows 7.

    Thanks

    Kyle

  10. Kyle says:

    I was able to over come this by running the script on the hybrid exchange server. But interested in getting it running on my host machine. Regardless, this script is a huge help! Thanks again, Mike!

    Kyle

  11. Todd Erickson says:

    Hello Michael.  Thanks a million for this script.  If I can get it to work, I would like to send you a donation.

    I am also getting the "Exchange Server Management Tools not installed on this host". I have the management tools installed on the host I'm running the script from, I see the script does a check "$checkEMT12Installed = test-path -Path 'hklm:SOFTWAREMicrosoftExchangeServerv12AdminTools' " which is False, as that path does not exist in that registry location. Is there another location where I can check to confirm AdminTools are installed?

    My Exchange is 2007 running on Server 2003 x64.  I get this error if I try to run the scripts on the host or on an XP workstation with the Management tools installed.

    Thanks,

    -Todd

  12. Todd Erickson says:

    We got this working with a couple of rather minor edits.

    #1 None of the machines I tried this on had the registry entry for the Exchange Admin Tools (see my comment above) so the PowerShell failed.  I edited the PowerShell and changed this line to $checkEMT14Installed = 'true'  since I have Exchange 2007.

    #2 On very large mailboxes I would get "ERROR:Cannot Process" because it was timing out.  I added the following line to the Get-Item function to increase the time out:

    $Service.Timeout = 600000;

    I added this just before the following line:

    $findResults = $Service.FindItems($folder.Id, $itemView);

    Other Notes: I could not run this on my Exchange Server (I don't think .Net 1.1 is installed on it).  I was able to run it on an old 32-bit XP VM after installing .Net 1.1, the 32-bit Exchange Admin Tools, and  the Exchange Web Services API.

    Thanks a million Michael.

  13. tony says:

    Michael,

    I have a question how does this differ from exFolders. We have been migrating mailboxes into Office 365 and when I run the script it doesn’t return the same information that exFolders does. I am able to find the folder location that has a large item using exFolders but the script does not find anything. Any information would be appreciated.

    thanks,

  14. Steve T. says:

    Michael, I get Unauthorized errors. I was hoping that the impersonation role would work for Exchange2010. I didn’t get errors running the pre-script roll/permissions assignments. Transcript started, output file is Z:DevelPowershello365Get-MailboxInfo.wwu.eduItemSizeChecks_2014-01-30_03-52-25_PM.txt
    2014-01-30_03-52-25_PM : Loading Microsoft.Exchange.WebServices.dll 2014-01-30_03-52-25_PM : Reading Exchange Mailboxes 2014-01-30_03-52-25_PM : Total number of mailboxes: ‘1’ 2014-01-30_03-52-25_PM : Getting impersonated service instance for ‘Steve.xxxx@ContosoCom.edu’
    2014-01-30_03-52-25_PM : Enumerating folders 2014-01-30_03-52-25_PM : Exception calling "FindFolders" with "2" argument(s): "The request failed. The remote server returned an error: (401) Unauthorized."[0] 2014-01-30_03-52-25_PM : Check service account credentials
    2014-01-30_03-52-25_PM : Writing results to .exportResultSet.csv 2014-01-30_03-52-25_PM : Done Transcript stopped, output file is Z:DevelPowershello365Get-MailboxInfo.wwu.eduItemSizeChecks_2014-01-30_03-52-25_PM.txt

  15. Zoltan Erszenyi says:

    Does the script also search the archive mailbox, or the primary mailbox only?

  16. Zoltan Erszenyi says:

    To complement my previous post, I have a customer who has some 1000 archive mailboxes that he wants to move to O365 while keeping the primary mailbox on premise. Some moves fail due to large items. How do I find them without having to walk to the user
    and use their Outlook? Thanks.

  17. Zoltan Erszenyi says:

    Awesome news! Thanks Michael 🙂

  18. Zoltan Erszenyi says:

    Michael, I ran the script and overall it did an excellent job. It however failed twice with errors similar to the following, on the Drafts and Calendar folders in the archive mailbox:

    ======================================================================
    2014-02-25_02-44-22_PM : EWS found item it cannot process
    WARNING:
    2014-02-25_02-44-22_PM : Processing of the folder Drafts is incomplete
    Get-Item :
    2014-02-25_02-44-22_PM : Inner Exception: Exception calling “FindItems” with “2” argument(s): “An internal server error occurred. The operation failed.”
    At C:_ZELargeItemChecks_1_2_7.ps1:415 char:29
    + $largeItems = Get-Item < <<< -ItemSizeLimit $itemSizeLimit -Folders $folders -Service $service -Verbose;
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Item
    ======================================================================

    The errors have been handled gracefully, they got logged in the output CSV file too, and they did not prevent the script from carrying on. That’s a very good thing.

    Is it something you can address in the script or it’s a missing/buggy feature of EWS?

    Thanks,
    Zoltan

  19. Rikard Strand says:

    I’m trying to run this in a Exchange 2013 CU3 Environment. I’m getting a error on all mailboxes;
    Exception calling “FindFolders” with “2” argument(s): “The SMTP address han no mailbox associated with it.”[0]

    However if I enter the same SMTP address in OWA it resolves to a user.

    What should I look for to troubleshoot/solve this ?

    Regards,

    Rikard Strand

  20. Won Keat, Liew says:

    Hi Michael

    I have a question regarding the code
    [System.Int32] $size = $item.Size / 776192; #Investigate this number

    I remember $Item.Size return the value in bytes, hence shouldn’t the formula is $item.Size / 1048576 in order to convert the bytes to MB?

    Besides that, if I wish to export the message class for those mail items, ex. IPM.Note, IPM.Appointment etc, what properties I should add in? Is it $Item.ItemClass ?

    Thanks for your guidance.

    Regards,
    Won Keat, Liew

  21. Maxime COEUR says:

    Hi Michael,
    Thanks a lot for your script
    It run well on exchange 2010 servers, but for big mailbox, it only seems to parse the first 1000 folders of this mailbox, any idea?
    Best regards.

  22. Maxime COEUR says:

    Hi Michael,
    thanks for your quick reply, unfortunatly i didn’t get any exception but i found a work arround making a loop splitting each 1000 folder result 🙂
    Best regards

  23. Lance Wilson says:

    Hi Michael,

    I’m running into an issue when I try to run the script. I’m getting “Exception calling “FindFolders” with “2” arguments: the SMTP address has no mailbox associated …”

    I have set the URI entry, but that didn’t help. Exchange 2007 with 2013 SP1 Hyrbid server.

    Any ideas?

  24. Tony Escamilla says:

    Michael is there an easy way to incorporate this to give us a report and allow us to export the emails to PST.

  25. Don Young says:

    Michael,

    I’m having an issue in that I apparently have a user with something corrupt in their mailbox, and it goes into an endless error loop when it hits there. (But that’s not an issue with the script).

    So… I am trying to use an import.csv file. And the script either doesn’t handle it right, or I have butchered it somehow.

    I get this error for each line in the CSV file:

    2014-05-28_12-20-25_PM : Cannot bind argument to parameter ‘Status’ because it is null.[0]

    Any ideas?

    Thanks in advance,

    Don

  26. santosh says:

    This is Good , But I have got Trouble at output file. I am getting some symbols. I have added -encoding ASCII,, Now out put is proper

  27. santosh says:

    I am geeting following error for some mail box: Any help ?
    Processing of the folder Calendar is incomplete
    Get-Item :
    2014-06-17_02-27-26_PM : Inner Exception: Exception calling "FindItems" with "2" argument(s): "The property has an inva
    lid value."
    At C:LargeItemChecks_1_2_8LargeItemChecks_1_2_8-New.ps1:444 char:15
    + Get-Item <<<< -ItemSizeLimit $itemSizeLimit -Folders $folders -Service $service -Verbose;

    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Get-Item

    WARNING:

  28. Mageid M says:

    I had this error when I ran it on two servers 2007 and 2010 any idea why

    2014-07-22_01-52-24_PM : Enumerating folders

    2014-07-22_01-52-24_PM : Exception calling "FindFolders" with "2" argument(s): "The request failed. The remote server re
    turned an error: (401) Unauthorized."[0]

    2014-07-22_01-52-24_PM : Check service account credentials
    thanks

  29. Jeff Janner says:

    The tool doesn’t seem to be able to view "Private" items. I’ve had several mailboxes show up as having no items over the large limit, but when I went to move them, the move failed with too many large items. The returned list of items detected as large
    could not be seen by me when I mounted the mailbox as a full-access user. Any setting change needed to enable the script to "see" large private items?

  30. Jeff Janner says:

    Now that I look at a completion report again, it might not be a "Private" items issue after all, though I think that might still be there. However, there is a problem with moving items in the "Recoverable Items/Deletions" folder. Can the tool also detect
    these? For some reason this folder gets moved with the mailbox.

  31. Mike Prisco says:

    Great script. It worked on my company cas server. But I tried to run it on a customer servers and I get "Transcription cannot be started" "Use the Start Transcript command"

  32. Anonymous says:

    If you haven’t seen my mailbox migration tool yet, go and have a look at it here . It’s been

  33. mike says:

    I am randomly getting these errors in the middle of processing a folder
    I still get data but wonder if I am missing some

    Get-Item :
    2014-09-03_03-46-03_PM : Inner Exception: Exception calling "FindItems" with "2
    argument(s): "The request failed. The remote server returned an error: (401)
    unauthorized."
    t C:Documents and SettingsxxxxxxxDesktopLargeItemChecksLargeIte
    mChecks_1_4.ps1:452 char:29
    $largeItems = Get-Item <<<< -ItemSizeLimit $itemSizeLimit -Folde
    rs $folders -Service $service -Verbose;
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorExcep
    tion
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorExceptio
    n,Get-Item

  34. oscar says:

    Great Script, would it be possible to search for public folders as well?

  35. Suggestion performance wise says:

    Why not filter the result to only retrieve the items that are larger than the itemsizelimit? This will have a huge impact on the performace.

    $AQSString = "System.Size:$($ItemSizeLimit)mb..9999mb"
    $findResults = $Service.FindItems($folder.Id, $AQSString , $itemView);

    The AQS search string is onnly availible from ews 2010 and above.

    /johnny stenberg

  36. thomas says:

    Hope this helps someone, but I was having all kinds of issues until I installed powershell 3.0, things just didnt seem to work right under 2.0

  37. Hasan Reza says:

    Dears,
    from where can I download the script LargeItemChecks.ps1 , please help..

  38. David says:

    Running the script with the following options, and receiving the error below. I have specified the folder on the server I am running the script. I have also shared and given the service account full access to the folders. Can anyone help with this?

    .LargeItemChecks_2_2_0.ps1 -ServiceAccountDomain grsd.local -ServiceAccountName mailscript -ServicePassword Spassword1 -ItemSizeLimit 25 -ImportCSV .user.csv -MoveLargeItems -ExportLargeItems -LargeItemNotice

    Couldn’t find the Enterprise Organization container.
    + CategoryInfo : NotSpecified: (0:Int32) [Get-MailboxExportRequest], OrgContainerNotFoundException
    + FullyQualifiedErrorId : 52B56334,Microsoft.Exchange.Management.RecipientTasks.GetMailboxExportRequest

    Couldn’t find the Enterprise Organization container.
    + CategoryInfo : NotSpecified: (0:Int32) [New-MailboxExportRequest], OrgContainerNotFoundException
    + FullyQualifiedErrorId : 31182839,Microsoft.Exchange.Management.RecipientTasks.NewMailboxExportRequest

Skip to main content