Michael's technical ramblings....

Interesting things I've found throughout my technical journey.

Exchange Server Large MailItem Script

Exchange Server Large MailItem Script

  • Comments 27
  • Likes

UPDATED : Released 1.4

1. Fixed an issue where corrupted items causes an infinite loop

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:

Grab the script here

Let me know if you have any issues with the script - technicalramblings@outlook.com or comment below.

Until next time,

Michael Hall

Comments
  • 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:\SOFTWARE\Microsoft\ExchangeServer\v12\AdminTools' " 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

  • 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

  • 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:\SOFTWARE\Microsoft\ExchangeServer\v12\AdminTools' " 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

  • 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.

  • 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

  • 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,

  • 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:\Devel\Powershell\o365\Get-MailboxInfo.wwu.edu\ItemSizeChecks_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:\Devel\Powershell\o365\Get-MailboxInfo.wwu.edu\ItemSizeChecks_2014-01-30_03-52-25_PM.txt

  • 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

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

  • 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.

  • 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

  • Awesome news! Thanks Michael :-)

  • 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:\_ZE\LargeItemChecks_1_2_7.ps1:415 char:29
    + $largeItems = Get-Item < -itemsizelimit="" $itemsizelimit="" -folders="" $folders="" -service="" $service="">
    + 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

  • 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

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

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment