Removing Duplicate Items from a Mailbox

powershellLatest version: 2.41, April 18th, 2023

For those involved with Exchange migration projects or managing Exchange environments, at some point you probably have experienced the situation where people ended up with duplicate items in their mailbox. Duplicate items can be caused by many things, but most common are:

  • Synchronization tools or plug-in. Entries from the mailbox are treated as new entries and as a consequence are added to the mailbox when synchronizing information back to the mailbox, creating duplicates. In the past, I’ve seen this happening with Nokia PC Suite and Google Apps Sync for example;
  • Importing existing data. Accidental import from – for example – a PST file to a mailbox  can lead to duplicate entries.

image

When looking for a solution, you’ll probably encounter MSKB299349, “How to remove duplicate imported items in Outlook”. This article describes a manual procedure to remove duplicates entries from your calendar, contacts, inbox or other folders. Not a very helpful and labor intensive.

When continuing your search, you’ll find lots (I mean lots!) of tools and Outlook add-ins, like Vaita’s DIR or MAPILab’s Duplicate Remover. Not all this software is free (some even require payment per duplicate removal of appointments, contacts or e-mail) and some might not even work (MAPI-based tools may not work against Exchange 2013).

When you finally have selected a tool, in most cases they require installation of a piece of software and someone to perform the removal process using the tool or Outlook with add-in. When you’re an Apple shop you’ll require different tools, unless you’re running a Windows desktop somewhere (I’ll just pretend I didn’t hear you saying ‘Why don’t you install the tool on the Exchange server’).

Wouldn’t it be nice if you’d have a PowerShell script you can conveniently run from any workstation (or server) with PowerShell installed, removing those duplicate items from a user’s mailbox remotely? If the answer is yes, the Remove-DuplicateItems.ps1 script may be something for you.

Requirements
Using the Remove-DuplicateItems.p1 script requires Exchange Web Services (EWS) Managed API and for OAuth authentication the Microsoft Authentication Library (MSAL) libraries. You can install these packages from NuGet, or place their DLL’s in the same folder as the script. For an example of how to install EWS.Managed.Api from NuGet, see this article; for MSAL follow the same process but with the package titled ‘Microsoft.Identity.Client’.

Also take notice that since you’ll be processing user mailboxes, you’ll need to have full mailbox access or impersonation permissions when using Basic Authentication; the latter is preferred. For details on how to configure impersonation for Exchange On-Premises or Office 365, see this blog post. Using a registered app with OAuth is always through Impersonation.

Usage
The script Remove-DuplicateItems.ps1 uses the following syntax:

Remove-DuplicateItems.ps1 [[-Identity] ] [[-Type] ] [-Retain ] [-Server ] [-Impersonation] [-DeleteMode ] [-Credentials ] [-Mode ] [-MailboxOnly] [-ArchiveOnly] [-IncludeFolders <String[]>] [-ExcludeFolders <String[]>] [-PriorityFolders <String[]>] [-NoSize] [-CleanupMode] [-NoProgressBar] [-Force] [-WhatIf] [-Confirm] [-Secret] [-CertificateThumbprint] [-CertificateFile] [-CertificatePassword] [-TenantId] [-ClientId] [-TrustAll] [-ExchangeSchema <String>] [-NoSCP]

A quick walk-through on the parameters and switches:

  • Identity is the e-mail address or name of the mailbox to process. If name is used, it is matched against cn/SAMAccountname/email address of local AD.
  • Type determines what folders are checked for duplicates. Valid options are Mail, Calendar, Contacts, Tasks, Notes or All (Default).
  • Retain determines which item to retain by comparing last modification times. Valid options are Newest (default) or Oldest.
  • Server is the name of the Client Access Server to access for Exchange Web Services. When omitted, the script will attempt to use Autodiscover.
  • When the Impersonation switch is specified, impersonation will be used for mailbox access, otherwise the current user context will be used.
  • DeleteMode specifies how to remove messages. Possible values are HardDelete (permanently deleted), SoftDelete (use dumpster, default) or MoveToDeletedItems (move to Deleted Items folder).
  • Mode determines how items are matched. Options are Quick, which uses PidTagSearchKey and is the default mode, or Full which uses a predefined set of attributes to match items, depending on the item class:
ItemClass Criteria
Contacts File As, First Name, Last Name, Company Name, Business Phone, Mobile Phone, Home Phone, Size
Distribution List FileAs, Number of Members, Size
Calendar Subject, Location, Start & End Date, Size
Task Subject, Start Date, Due Date, Status, Size
Note Contents, Color, Size
Mail Subject, Internet Message ID, DateTimeSent, DateTimeReceived, Sender, Size
Other Subject, DateTimeReceived
  • MailboxOnly specifies you only want to process the primary mailbox of specified users. You als need to use this parameter  when running against mailboxes on Exchange Server 2007.
  • ArchiveOnly specifies you only want to process personal archives of specified users.
  • IncludeFolders specifies one or more names of folder(s) to include, e.g. ‘Projects’. You can use wildcards around or at the end to include folders containing or starting with this string, e.g. ‘Projects*’ or ‘*Project*’. To match folders and subfolders, add a trailing \*, e.g. Projects\*. This will include folders named Projects and all subfolders. To match from the top of the structure, prepend using ‘\’. Matching is case-insensitive.
  • ExcludeFolders specifies one or more folder(s) to exclude. Usage of wildcards and well-known folders identical to IncludeFolders.
    Note that ExcludeFolders criteria overrule IncludeFolders when matching folders.
  • CleanupMode specifies to cleanup duplicates per folder (Folder, default), the whole mailbox (Mailbox), or multiple mailboxes (MultiMailbox, identities specified using Identity). The first unique item encountered will be retained. For Mailbox-level cleanup, PriorityFolders can be used to give priority to retaining items in specified folders before those found in other folders.
  • PriorityFolders specifies which folders have priority over other folders, identifying items in these folders first when using MailboxWide mode. Usage of wildcards and well-known folders is identical to IncludeFolders.
  • NoSize tells script to not use size to match items in Full mode.
  • NoProgressBar prevents displaying a progress bar as folders and items are being processed.
  • Report reports individual items detected as duplicate. Can be used together with WhatIf to perform pre-analysis.
  • TrustAll can be used to accept all certificates, e.g. self-signed certificates or when accessing Exchange using endpoint with a different certificate.
  • ExchangeSchema can be used to specify the Exchange schema to use when connecting to Exchange server or Exchange Online. Defaults to Exchange2013_SP1 or Exchange2016 when -Server is specified and is ‘outlook.office365.com’ (Exchange Online endpoint).
  • NoSCP to skip SCP lookups in Active Directory for Autodiscover.

For authentication, the following parameters are available:

  • Credentials specifies credentials to use for Basic Authentication.
  • TenantId specifies the identity of the Tenant (OAuth)
  • ClientId specifies the Id of the registered application (OAuth).
  • CertificateThumbprint specifies the thumbprint of the certificate from personal store to use for authentication (OAuth).
  • CertificateFile specifies the external certificate file (pfx) to use for authentication (OAuth). This certificate needs to contain a private key; the registered application needs to contain the certificate’s public key.
  • CertificatePassword optionally specifies the password to use with the certificate file (OAuth).
  • Secret specifies the secret to use with the application (OAuth).

Few notes:

  • When MoveToDeletedItems is specified, the Deleted Items folder will be skipped;
  • When Type is omitted or set to All, all folders are scanned, including folders like Conversation History, RSS Feeds, etc.;
  • When Quick mode is used and PidTagSearchKey is missing or inaccessible, search will fall back to Full mode;
  • For more info on PidTagSearchKey, see http://msdn.microsoft.com/en-us/library/cc815908.aspx. Note that PidTagSearchKey will have duplicate values for copied objects.
  • You need to specify MailboxOnly when running against mailboxes on Exchange Server 2007 as the Exchange 2010 personal archive options in EWSare not support in Exchange 2007 mode.

Well-Known Folders
For IncludeFolders, ExcludeFolders and PriorityFolders, you can also use well-known folders using this format: #WellKnownFolderName#, e.g. #Inbox#. Supported are #Calendar#, #Contacts#, #Inbox#, #Notes#, #SentItems#, #Tasks#, #JunkEmail# and #DeletedItems#. The script uses the currently configured Well-Known Folder of the mailbox to be processed.

Patterns
Here are some examples of using pattern matching in IncludeFolders, ExcludeFolders or PriorityFolders, based on the following tree structure:

+ TopFolderA
  + FolderA
    + SubFolderA
    + SubFolderB
  + FolderB
+ TopFolderB

The following filters will match folders from the above structure:

Filter Matches
FolderA \TopFolderA\FolderA, \TopFolderB\FolderA
Folder* \TopFolderA\FolderA, \TopFolderA\FolderB, \TopFolderA\FolderA\SubFolderA, \TopFolderA\FolderA\SubFolderB
FolderA\*Folder* \TopFolderA\FolderA\SubFolderA, \TopFolderA\FolderA\SubFolderB
\*FolderA\* \TopFolderA, \TopFolderA\FolderA, \TopFolderA\FolderB, \TopFolderA\FolderA\SubFolderA, \TopFolderA\FolderA\SubFolderB, \TopFolderB\FolderA
\*\FolderA \TopFolderA\FolderA, \TopFolderB\FolderA

Usage
So, suppose you want to remove  duplicate Appointments from the calendar of mailbox migtester1 using attribute matching, moving duplicate items to the DeletedItems, using Impersonation and you want to generate extra output using Verbose. In such case, you could use the following cmdlet:

Remove-DuplicateItems.ps1 -Identity migtester1 -Type Calendar -Impersonation -DeleteMode MoveToDeletedItems -Mode Full -Verbose

image

Alternative, you can use an e-mail address and specify credentials.  This allows the script to run against mailboxes in Office 365, for example:

Remove-DuplicateItems.ps1 -Identity olrik@office365tenant.com -Type Mail -DeleteMode MoveToDeletedItems -Mode Full -Credentials (Get-Credential) -Retain Oldest

A more complex example using IncludeFolders, ExcludeFolders and PriorityFolders:

$Credentials= Get-Credential
 .\Remove-DuplicateItems.ps1 -Mailbox olrik@office365tenant.com -Server outlook.office365.com -Credentials $Credentials -IncludeFolders '#Inbox#\*','\Projects\*' -ExcludeFolders 'Keep Out' -PriorityFolders '*Important*' -CleanupMode Mailbox

This will remove duplicate items from the specified mailbox in Office365, using the following options:

  • Fixed Server FQDN – bypassing AutoDiscover.
  • Limits operation against the Well-Known Inbox folder, top Projects folder, and all of their subfolders.
  • Excluding any folder named Keep Out.
  • Duplicates are checked over the whole mailbox.
  • Priority is given to folders containing the word Important, causing items in
    those folders to be kept over items in other folders when duplicates are found.

In case you want to process multiple mailboxes, you can use a CSV file which needs to contain the Identity field. An example of how the CSV could look:

Identity
francis
philip

The cmdlet could then be something like:

Import-CSV users.csv1 | Remove-DuplicateItems.ps1 ..

Download
The script is available on GitHub here.

Feedback
Feedback is welcomed through the comments. If you got scripting suggestions or questions, do not hesitate using the contact form.

This entry was posted in Exchange Online, Exchange Server, Office 365 and tagged , , , by Michel de Rooij. Bookmark the permalink.
Unknown's avatar

About Michel de Rooij

Michel de Rooij, with over 25 years of mixed consulting and automation experience with Exchange and related technologies, is a consultant for Rapid Circle. He assists organizations in their journey to and using Microsoft 365, primarily focusing on Exchange and associated technologies and automating processes using PowerShell or Graph. Michel's authorship of several Exchange books and role in the Office 365 for IT Pros author team are a testament to his knowledge. Besides writing for Practical365.com, he maintains a blog on eightwone.com with supporting scripts on GitHub. Michel has been a Microsoft MVP since 2013.

484 thoughts on “Removing Duplicate Items from a Mailbox

  1. Hello,

    thank you for the script. Found a little bug, it doesn’t properly detect number of duplicated items. I used it on O365.

    So here is what i did:
    1) created random folder inside outlook
    2) take some mail from inbox and copy it
    3) paste it 11 times inside random folder

    Running script only detected 8 of them in random folder. Took new mail from inbox, copied it to random folde 2 times and run the script again. Script deleted previous copies that remain in random folder from 1st copy action. It didn’t remove 2 new copied mails.

    I tried running the script again in 1st and 2nd scenario after 1st run finished and it didn’t detect or delete remaining copies.

    I have a problem from Google migration to O365 so I just wanted to test before I execute it customer account.

    Thanks!

    Like

          • What cmdline are you using? Note that default it utilizes PR_SEARCH_KEY to match duplicates; that key should be a unique and when copying items, that attribute should be preserved and identical on those items. Can you inspect with for example MFCMAPI if that is the case? Alternatively, you can use -Mode Full to match on a predetermined set of attributes (see help)

            Like

          • Do you have a utility to remove duplications from the online version of Office365 for contacts, calendars and mailboxes, tasks, notes? Thanks in advance for your response.

            Like

          • That’s where the script is for – not only mail-items. Have you checked with MFCMAPI to verify the PR_SEARCH_KEY attributes are indeed identical? The cmdline you use should work. On another note, those items are of type mail (IPF.Note); not some sort of stub or something else? (you can use MFCMAPI for this as well or add the Message Class field to the view)

            Like

          • Found out why it didn’t want to work. Mails don’t have same PR_SEARCH_KEY, so for example same (content) mail is inside “all mails” and “important” folder but PR_SEARCH_KEY does not match even though all data of the mail that is displayed inside outlook client is the same. Would you be interested to modify the script to fix our problem (we can discuss about the payment)? I don’t know what I was comparing few days ago…

            Like

  2. Do you know how I could get this to work when the PID searches do not match, and the Received timestamp, size, and last modified properties are all a tiny bit different? (so, essentially relying on sender, subject, time sent which remain unique)

    Like

    • Below ‘# Use predefined criteria for matching duplicates depending on ItemClass’ is the logic to match items, depending on item type (different items provide different attributes). I can’t determine “a tiny bit different” for you. There is also the danger of removing valid items, for example it happens quite often people forget to state something or add an attachment, making things like subject, sender and recipients match and only the timestamp ‘a tiny bit’ different, yet both messages should be kept.

      Like

  3. Hello Michel, the script is GenieL.
    We migrated from Lotus to Exchange 2013 but this generate many duplicates process.
    I read carefully your blog and I changed the script and the parameters to work. But, now does not fail but gives 0 items to remove

    PS C:\Windows\system32> Remove-DuplicateItems.ps1 -Mailbox email@domain.com -Type Mail -DeleteMode MoveToDeletedItems -ArchiveOnly -Verbose -Server Exchange.local -Mode Full
    VERBOSE: Loading C:\Program Files\Microsoft\Exchange\Web Services\2.2\\Microsoft.Exchange.WebServices.dll
    Processing mailbox email@domain.com (email@domain.com)
    VERBOSE: Set to trust all certificates
    VERBOSE: Using Exchange Web Services URL https://Exchange.local/EWS/Exchange.asmx
    VERBOSE: DeleteMode is MoveToDeletedItems
    VERBOSE: Processing Mail items
    VERBOSE: Processing archive mailbox email@domain.com
    VERBOSE: Searching for folder class
    VERBOSE: Processing folder (Custom Expiration\Manage Folders)
    VERBOSE: Processing folder Elementos eliminados
    VERBOSE: Processing folder FolderHiddenPublic
    VERBOSE: Processing folder Folders
    VERBOSE: Processing folder Data
    VERBOSE: Processing folder Personal
    VERBOSE: Processing folder Inbox
    VERBOSE: Processing folder Sent Items
    VERBOSE: Total number of items removed: 0
    VERBOSE: Processing finished

    Like

    • I am having this same issue only on Wave 15.1 of Office 365.

      Previous comments lead me to think that it may be a permissions issue. We have duplicates that came in from an IMAP sync and PST import but the script output looks very similar to what you posted – 0 items removed. I have granted the admin account full mailbox access as well as ApplicationImpersonationRights via the Discovery Management admin role but no joy.

      The above links regarding permissions appear to be dead so maybe there is something else I am missing with permissions here.

      Like

      • 15.1 is a bit too generic – what is you specific version, i.e. what does Outlook’s Connection Status / Version report? Meanwhile I’ll check against an 15.1.249.20 tenant.

        I’ve update the link to information on how to configure impersonation.

        Like

        • Well, my admin display version is 15.1.549.26. I’m not sure if that correlates to the specific Exchange Online version. In any case, I have verified the impersonation as well as given full mailbox access, so I don’t think permissions should be an issue at this point.

          However, I have tried both the Full and Quick mode with no items being found but no errors showing either.

          Thanks very much for the script and for your assistance!

          Eric

          Like

  4. Hi,

    Thanks for sharing such a wonderful post with us.
    I had this issue & your blog as well as one other blog, helped me to overcome this scenario of duplicate emails. Another link is as follows:
    [link removed]

    Like

  5. I’m using v1.41 The script runs fine but finds no duplicates. I even tried selected an item in my inbox, ctrl-c, ctrl-v to duplicate it. Still the script says:
    PS C:\Users\xxxx\Downloads> .\Remove-DuplicateItems.ps1 -Mailbox xxxx@yyy.com -Type Mail -DeleteMode MoveToDeletedItems -Mode Full -Verbose -MailboxOnly -Server outlook.office365.com -Credential (Get-Credential)

    cmdlet Get-Credential at command pipeline position 1
    Supply values for the following parameters:
    Credential
    VERBOSE: Loading C:\Program Files\Microsoft\Exchange\Web Services\1.2\\Microsoft.Exchange.WebServices.dll
    Processing mailbox xxxx@yyy.com (xxxx@yyy.com)
    VERBOSE: Set to trust all certificates
    VERBOSE: Using credentials xxxx@yyy.com
    VERBOSE: Using Exchange Web Services URL https://outlook.office365.com/EWS/Exchange.asmx
    VERBOSE: DeleteMode is MoveToDeletedItems
    VERBOSE: Processing Mail items
    VERBOSE: Processing primary mailbox xxxx@yyy.com
    VERBOSE: Searching for folder class
    VERBOSE: Processing folder Clutter
    VERBOSE: Processing folder Drafts
    VERBOSE: Processing folder Inbox
    VERBOSE: Processing folder Junk Email
    VERBOSE: Processing folder Outbox
    VERBOSE: Processing folder VoiceOutbox
    VERBOSE: Processing folder Quick Step Settings
    VERBOSE: Processing folder Sent
    VERBOSE: Processing folder Sent Items
    VERBOSE: Processing folder Sync Issues1
    VERBOSE: Processing folder Conflicts
    VERBOSE: Processing folder Local Failures
    VERBOSE: Processing folder Server Failures
    VERBOSE: Processing folder Trash
    VERBOSE: Total number of items removed: 0
    VERBOSE: Processing finished

    Like

  6. I got it working for me. It wasn’t for for 4 different reasons:
    1) autodiscover isn’t working for my office365 account, I just bypassed the issue adding parameter -Server outlook.office365.com
    2) -Mode Quick doesn’t seem to be able to retrieve any useful identifier for emails, so I used -Mode Full
    3) Even in -Mode Full, most of my duplicates are not recognized because they have identical time, sender, messageid, etc, but different size. That is, even if I manually duplicate a message copying it to a different mailbox, and then back, it gets a different (larger) size. Since this script compare also size (in Full Mode) it finds no duplicates. Solved by commenting out this line:
    # if ($Item.Size) { $key+= “,”+$Item.Size.ToString()}
    4) The search for a duplicate is done using an arrayList which (is inefficient and) always fails for me. Maybe because even if the two compared strings are identical they are still different objects.
    Solved by replacing line
    $UniqueList= [System.Collections.ArrayList]@()
    with
    $UniqueList = New-Object ‘System.Collections.Generic.HashSet[string]’

    I also added two more options to Retain: Largest and Smallest, in order to be able to retain the smallest.

    Like

  7. Hello Michel,

    sorry, I Need to come back to this post from early this year: https://eightwone.com/2013/06/21/removing-duplicate-items-from-a-mailbox/#comment-143576

    Would it be possible to use your script to:
    1) Lookup only contacts within a Mailbox that have the flag “crmLinkState=2”? (This would secure to work only on contacts that have been synced from Dynamics CRM)
    2) Do a merge/cleanup with data from 1) and define a master record that has a certain value (e.g. “merged master”) in the field “Nickname”

    Background:
    We found a way to merge all duplicate contact records within our CRM System. To have a filtering Option, we´d update all remaining records with the above mentioned string within the field “Nickname” which would also be synced to Exchange mailboxes.

    Thanks in advance for any Reply.

    Regards,
    Oliver

    Like

  8. I would like to be able to run the script from my computer without having the username password
    To use the office administrator 365

    Like

  9. Script seems to run without errors, the include folder is processed, but it doesn’t identify or remove any obvious duplicates. I have commented out the item.size lines for -Full, but obvious duplicates are still not removed. Tenant version is: 15.1.1341.23. Impersonation is enabled. Duplicates were copied with a third party migrator that we are trying to clean up but the same product did both runs so they are identical messages. Wonderful script if it will do what we need.

    Like

  10. Just completed a GSuite migration to Office365 and I’m using your script to clean up the duplicate mess.

    Small folders process without any issues, but larger folders fail after deleting a few thousand duplicates…

    VERBOSE: Removing 15596 items from Archive
    Process-Mailbox : Problem removing items: Exception calling “DeleteItems” with “4” argument(s): “The server cannot
    service this request right now. Try again later.”
    At D:\Users\XX\Downloads\Remove-DuplicateItems.ps1:675 char:16
    + … If(! ( Process-Mailbox $RootFolder $IncludeSearchCollection $Exc …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Process-Mailbox

    D:\Users\XX\Downloads\Remove-DuplicateItems.ps1 : Problem processing primary mailbox of
    user@domain.com (user@domain.com)
    At line:1 char:1
    + .\Remove-DuplicateItems.ps1 -Identity user@domain.com -Cr …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-DuplicateItems.ps1

    Usually, a new powershell is required to resume the operation.

    Do you have any suggestions on how to complete the operation in a single pass?

    Like

  11. Should this be able to run against a shared mailbox? I’ve a shared mailbox (ex-user mailbox that has been converted to shared, with assigned email address) on O365 that i specify in identity, using my own credentials. The script runs but from the verbose output it’s obvious it’s running on my own mailbox and archive.

    Like

  12. Hello Michel, Thanks for this script.

    But i have some problems…

    D:\Remove-DuplicateItems.ps1 : Can’t access mailbox information store: Exception calling “FindItems” with “2” argument(
    s): “The server cannot service this request right now. Try again later.”
    At line:1 char:1
    + .\Remove-DuplicateItems.ps1 -Mailbox xxxxxxxxx@xxxx.xx -Server out …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-DuplicateItems.ps1

    Like

  13. Hi, I am getting an error: Problem removing items. Maybe you have any ideas what the problem is? Thank you!

    Are you sure you want to perform this action?
    Performing the operation “Remove-DuplicateItems.ps1” on target “Remove 152 items from \Inbox”.
    [Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”): Y
    VERBOSE: Removing 152 items from \Inbox
    Process-Mailbox : Problem removing items: Attempted to divide by zero.
    At C:\Program Files\Microsoft\Exchange\Web Services\2.2\Remove-DuplicateItems.ps1:1040 char:29
    + … If (! ( Process-Mailbox -Folder $RootFolder -IncludeFilter $Inclu …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Process-Mailboxting error

    Like

  14. I am getting a repeated warning. I getting so many that the log text leading up to it has scrolled out of reach for a cut and paste. Several lines after the message telling me the script has started processing the mailbox I get:
    VERBOSE:Adding folder \ (priority 0)
    WARNING: Error performing operation FindFolders with Search options in . Error: Exception calling “FindFolders” with “3” argument(s): “Value cannot be null. Parameter name: parentFolderId”
    VERBOSE:Adding folder \\ (priority 0)
    WARNING: Error performing operation FindFolders with Search options in . Error: Exception calling “FindFolders” with “3” argument(s): “Value cannot be null. Parameter name: parentFolderId”
    This repeats with another back slash added until there are well over 800 hundred slashes.
    The script then ends with the message: Cannot access mailbox information store, error: The script failed due to call depth overflow.
    At line:1 char:1
    + C:\Users\Me\Remove-DuplicateItems.ps1 -Identity me@company.biz -Server …
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId: Microsoft.PowerShell.Commands.WriteErrorException,Remove-Duplicates.ps1

    The command line (v1.81) I am using looks like this:
    C:\Users\Me\Remove-DuplicateItems.ps1 -Identity me@company.biz -Server outlook.office365.com -Type Mail -DeleteMode MoveToDeletedItems -Mode Full -Verbose -Credentials (Get-Credential) -Retain Oldest

    Like

  15. I updated to 5.0 and the scripted worked for me too. This is great. I was surprised I didn’t have more duplicates. I found about 100 in 150,000 emails. It is really nice to have this cleaned up. Thanks Michel

    Like

    • Yes – use IncludeFolders and the tag #SentItems#, e.g. -IncludeFolders ‘#SentItems#’. But it seems you found a bug; if you only specify one element, it processes all folders. Bug filed; workaround is to specify the same folder twice, e.g. -IncludeFolders ‘#SentItems#’, ‘#SentItems#’

      Like

  16. sorry your scri[t does not work on o365 I have scaned an mailbox qith cript 60000 mails and more an returned 0 duplicates and atleast 40 % are duplicates

    Like

  17. I have a Problem with Exchange 2016. The Skript detects duplicate contacts and removes them. But it does not detect duplicate Mails.
    It lists all the Folders of the Mailbox that exist. It Shows the correct number of items that are in the Mailbox but it Shows 0 items removed. I spedify “-Mode Full -NoSize” but the duplicates are not recognized. The items are created by multiple runs of a restore, so they should be the same.

    Using the user credentials or impersonation makes no difference.

    Like

    • For e-mail with ‘Full’ there is a set of attributes which should match for it to be considered a duplicate. With NoSize, you can exempt size from this comparison, but if those others are not *all* identical, it’s not considered a duplicate. You can use tool like MFCMapi (or Outlook itself) to inspect the following attributes: DateTimeReceived, Subject, InternetMessageId, DateTimeSent, Sender and optional Size.

      Like

  18. Hi Michel. I have been running this script against a fairly large mailbox with a fair amount of duplicates and am getting following errors:

    VERBOSE: Using Exchange Web Services URL https://outlook.office365.com/EWS/Exchange.asmx
    VERBOSE: Constructing folder matching rules
    VERBOSE: Processing primary mailbox tony@billingford.com
    VERBOSE: Collecting folders to process, type All
    WARNING: Previous EWS operation failed, adjusted sleep timer to 300ms
    C:\Users\Redblade\Downloads\Remove-DuplicateItems (1).ps1 : Cannot access mailbox information store, error: Unable to find type [Microsoft.Exchange.WebServices.Data.ServerBusyException].
    At line:1 char:2
    + & ‘.\Remove-DuplicateItems (1).ps1’ -Mailbox tony@billingford.com -S …
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
    + FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-DuplicateItems (1).ps1

    Have checked impersonation which is setup correctly for the $usercredential account. Thing is if I run this against smaller mailboxes this seems to run fine, potentially ruling out impersonation rights or connectivity. There is another mailbox in the tenancy which is >10gb which gives the same error, all other mailboxes run fine. Any ideas would be much appreciated?

    Thanks

    Like

  19. Michel,

    many thanks for this script. I run it on an Exchange 2016 server.

    .\Remove-DuplicateItems.ps1 -Mailbox user@domain.com -Type Tasks -Impersonation -DeleteMode SoftDelete -Mode Full -Verbose –WhatIf

    The script finds many duplicate mails and calendar entries but no duplicate tasks. However, there are many duplicate tasks in the mailbox.

    Can you give me a clue?

    Thanks a lot
    J

    Like

      • Hello Michel,

        I have a similar problem with the processing of tasks in user mailboxes. I’ve used the following Parameters:
        .\Remove-DuplicateItems.ps1 -Mailbox user@domain.com -Type All -Impersonation -DeleteMode HardDelete -Verbose

        The Skript was able to remove evry duplicate item from the mailbox except for tasks. Even with specifing tasks as the inteded search type and playing aroud with the -DeleteMode parameter, I was unable to remove them.

        Does it have anything to do with the german translation for the task folder? Or is there anything else I can try?

        Thank you in advance!

        Best regards,
        T. Nieresel

        Like

  20. Hello!
    Can you please explain I have larger mailbox 90 GB and into folders about 80k items.
    Script didn’t work properly and didn’t all cleaned up msg. Used Full mode
    Why? And How are using pig tiles or maybe more parameters?
    Thanks!

    Like

    • 1) What you mean by pig tiles?
      2) Duplicate checks are performed on multiple attributes which all need to be equal depending on the class to be considered duplicate. That is not always the case as 3rd party software may touch items or dehydrate stubs which then look the same, but are not. Read the help for info on attributes to be considered.

      Like

  21. Michel
    I have managed to modify your script in a fairly minor way to work on Public Folders.
    Would you like me to submit my version (1.83PF) to you as I dont feel publishing it myself is valid as 95% ( & probably more) of the work is yours !

    Like

  22. hi when Using mailboxwide switch, how to change the priority of the folders. As I want to keep the emails in all the subfolders instead of Inbox and Important Folders after migrating IMAP mailbox to Office 365.

    Like

    • Use PriorityFolders to give folders priority over others; items founds in these folders are retained over duplicates in other folders. The order of folders specified with PriorityFolders also impacts which items to retain; PriorityFolders A,B will have items in folder A retained over duplicates in B. PriorityFolders also accepts well known folders, wildcards etc.

      Like

  23. Somehow a user’s contacts got duplicated and then some. She’s got over 500,000. I ran this once and it picked up and removed ~105,000. It completely ignored most of them though. One for example, there appears to be hundreds of, and it only has a name (which is a phone number) and company name. That’s not being picked up in quick or full mode. Any suggestions?

    Like

      • Even in quick mode, it’s not finding any of them.

        End of the log…

        VERBOSE: Collecting folders to process, type Contacts
        VERBOSE: Adding folder \Contacts (priority 0)
        VERBOSE: Adding folder \ExternalContacts (priority 0)
        VERBOSE: Adding folder \PersonMetadata (priority 0)
        VERBOSE: Found 3 folders that match search criteria
        Processing folder \Contacts
        Processing folder \ExternalContacts
        Processing folder \PersonMetadata
        1752592 items processed and 0 removed in 02:36:45 – average 11181 items/min
        WARNING: Cannot bind to ArchiveMsgFolderRoot – skipping. Error: Exception calling “Bind” with “2” argument(s): “The specified folder could not be found in
        the store.”
        VERBOSE: Processing xx@yy.net finished

        Still have ~390,000 that need to be removed, grateful for any advice you can provide.

        Thank you

        Like

  24. Somehow a user’s contacts got duplicated and then some. She’s got over 500,000. I ran this once and it picked up and removed ~105,000. It seemed to ignored most of them though. One contact for example there appears to be hundreds of, and it only has a name (which is a phone number) and company name. That’s not being picked up in quick or full mode. Any suggestions?

    Like

  25. Hi,
    nice work but when I run the command, only 1786 items get processed in inbox and no more. Is there a limit set somewhere? There are more than 150000 mails in inbox only.

    Thanks

    Like

  26. Hi Michel.

    First thanks, thanks a lot for this script and for all the information about Exchange in your blog.

    We have a problem with your script. The script run without problems but it detects a lot of emails duplicated, says at the end that they have been removed but the emails duplicated (and triplicated) are still in the mailbox.

    [PS] >.\Remove-DuplicateItems.ps1 -Mailbox xxx@xxxx.com -Type mail -Impersonation -DeleteMode harddelete -Mode full -IncludeFolders “#sentitems#” -mailboxonly -confirm:$false

    Processing mailbox xxx@xxxx.com (xxx@xxxx.com)
    93158 items processed and 20903 removed in 00:10:50 – average 8597 items/min

    We tried with impersonation and with the user’s credentials but the results were the same.

    We tried to check only the folder or all the mailbox but again the results were the same.

    At the first execution the script removed some of the detected duplicated emails but didn’t remove all of them.

    After that it doesn’t remove more duplicated emails even though it detects them.

    I can’t imagine why the script detects but doesn’t remove them. Do you have any idea about it?

    Thanks in advance for your response.

    Like

      • Thanks for the quick response.

        I’m checking the mailbox folder statistics in server side and I’m trying to remove the items since some days ago. The duplicated emails are still there.

        I don’t know why it doesn’t remove the duplicated emails because there is no errors in the execution. Maybe I have to put some flags and modify the script to debug my problem and see where is the strange thing which produce this behavior.

        Thanks.

        Like

      • At the end I distribute the duplicated email in 4 folders with 10.000 duplicated emails each one and it works as desired. The emails are analyzed, duplicates founded and removed (each folder contains 7.000 email duplicated more ore less)

        The problem seems to be when there a too much emails to remove.

        Like

  27. Great thanks go out to you Michel as you patiently navigate these questions and provide excellent detailed answer. I just wanted to pass along a tip on an issue I was having.
    All of my attempts to use this script were failing with authorization errors. I finally ran it against my own mailbox with the same results. Double and triple checked my credentials…still no luck.
    Knowing I had MFA enabled, I used my app password and it all started working.

    Really very nice of you to share and continue to develop a script like this. We as a community can not thank you enough.

    Like

  28. So I have a quick question. I have some shared mailboxes that I have full access to. I am identifying the shared mailbox with the identity parameter. I am using my credentials for authentication. In verbose mode, the script says its processing the shared mailbox. But the scan appears to be scanning my own mailbox. I do not have impersonation enabled. And if I try to use the switch it fails. Must I have impersonation even if I have full access?
    On the bright said, I have thoroughly cleaned dupes out of my own mailbox. Command line below is what I used (notwithstanding some anonymity.)
    $creds = get-credentials
    .\Remove-DuplicateItems.ps1 -Identity sharedmailbox@company.com -type Mail -Server outlook.office365.com -Credentials $creds -mode Quick -DeleteMode SoftDelete -MailboxWide -MailboxOnly -Verbose

    Some of the verbosity was…
    VERBOSE: Processing folder \Inbox\FTC
    VERBOSE: Processing folder \Inbox\Incident emails
    VERBOSE: Processing folder \Inbox\Helpdesk
    32310 items processed and 37 removed in 00:03:41 – average 8750 items/min
    VERBOSE: Processing sharedmailbox@company.com finished

    The folders mentioned above were in my mailbox not the shared mailbox.

    Like

      • I have to follow up on my use of this great script. I finally got application impersonation permissions to run this. (This is a difficult role to explain to someone even if they know PowerShell really well.)
        In short, this script works great for me now. I discovered that using the mode body yields the most dupes. I encourage anyone using this to try many combinations of the switches to get what you need form this.
        Michel-Thanks again! I can’t help notice what a great over all site you have. I am starting to really dig into in. You are indeed an MVP!

        Like

  29. Good afternoon; is it possible to delete duplicates only based on Subject Line and date?

    My used got the same email twice multiple times from the same user but from different alias so the only thing that it matches besides the body content is the subject line and date which are the same.

    Thanks;
    Mario

    Like

  30. So I have a significant update on my issue. I had been running this program on my workstation with my Outlook open. In retrospect, that was quite foolish. I am trying it on an exchange server (which also feels foolish.) I believe my issues are one of environment. I will report my findings as they develop.

    Like

  31. After my Remove-DuplicateItems.ps1 was executed and completed, some mailboxes got an automatic email about “Unread email has been deleted”. Some users did have unread duplicated emails and it looks like the script or Exchange-server send an email to the sender of all unread emails, so both internal and external recipients in other organisations got a notification about this. Do you know how to turn of this notification emails?

    Like

      • It was Exchange 2016 CU11. What I remember, it was NDRs back to the senders of those old emails saying “You got an unread email deleted by the recipient…”. We did not test to manually delete some of these old unread emails to see if that also gerenated NDRs. We did just close that ticket. Let’s see if it happens more times. And can reply here with more details in that case. Thanks for a good script btw!

        Like

  32. You are a life saver!! After my parent company switched from exchange to Gmail (losing a few years worth of emails in the process), I’m now switching back to Office 365 for my team and the labeling in gmail created so many issues. Thanks to your script I can merge the gmail inbox AND the original PST file from the exchange server and not have to panic about the duplicates. Incredibly well explained and detailed and reading through the responses above saved me a ton of time. (I had never used a script before in Powershell and with your direction was able to get this up and running in less than an hour) Thanks again!

    Like

  33. Great script. I am running into problems with mailboxes in a different language. I cannot do -DeleteMode MoveToDeletedItems because the DeletedItems for a German mailbox is named ‘Gelöschte Elemente’ (Error:Exception calling “DeleteItems”…

    Like

    • That shouldn’t be the problem, because we’re referring to the DeletedItems folder through something called the WellKnownFolders, which is language-independent. Care to elaborate a bit more on the issue you’re encountering?

      Like

  34. I’m still running into the EWS throttling issue on large mailboxes (error below; example mailbox is ~200,000 items). I’ve read some comments that this could be an issue with interrupted internet connectivity. So I re-ran the command from an Azure server to alleviate any local issues and ran into the same error.

    Cannot access mailbox information store, error:
    Exception calling “LoadPropertiesForItems” with “2” argument(s): “The request failed. The read operation failed, see inner exception.”

    I’ve tried multiple combinations of parameters and it seems to be only affecting running in Full mode (full script below).
    .\Remove-DuplicateItems.ps1 -Mailbox user@domain.com -Credentials $creds -Mode Full -NoSize -Impersonation -Server outlook.office365.com -Type mail -verbose

    Like

    • 1) What version of EWS Managed API are you using?
      2) Mailbox parameter has been renamed to Identity for a while now.
      First thing the script does is collect all folders and select the ones which pass the Include/Exclude filter. That should not be limited due to no. of items in a folder. That ‘Exception calling “LoadPropertiesForItems” with “2” argument(s): ‘ is the only thing reported?

      Like

      • I can’t speak for BDP, but I am facing the same exact issue across multiple different mailboxes. I am trying this against O365. The EWS Managed API I’m using is v15.00.0913.015. The exact error that I get is:

        TerminatingError(): “Exception calling “LoadPropertiesForItems” with “2” argument(s): “The server cannot service this request right now. Try again later.”

        It definitely seems to be struggling with large mailbox sizes with a couple folders that are 10GB+ (50k+ items). Unsure how to handle this situation. Is it best to try and split these across multiple folders in some way? Guess I’ll have to find a way to do that programmatically…

        Like

  35. Hi,

    First of all, thanks a lot for your help to the community.I’ve discovered your thread a few weeks ago. I can’t believe you’ve helped so many people. I’m also having issues on a migration from G Suite to O365.
    I’ve downloaded your script. I’ve been trying to use it for several days. I went through most of the issues people also had on this topic, and got them solved one after the other. (credentials, impersonation, etc).

    I’ve run the script in Full Mode and it did not find a lot of duplicates (but I know I have at least 17Gb of them :-). I’ve just launched a new run with the -noSize option, I’ll see if it works.

    I have one question : I have found manually a few examples of emails that are duplicated. Following example is :
    – the original email is folder “Important”
    – the first copy I can find is in folder “PARTNER A” (G suite label). On that email I can spot one difference : Office has considered that my forwarding this email was to be in this folder, not in important. So the mailchain is a bit different here in this folder
    – the second copy I can find is in folder “Archive”, and it looks pretty much like the one in folder “Important”.
    Do you know a way for me to check the matching criterias in the script on these 3 particular emails to understand why they were not picked up ?

    My current command line :
    .\Remove-DuplicateItems.ps1 -Mailbox myuser@mydomain.onmicrosoft.com -Type Mail -DeleteMode MoveToDeletedItems -Mode Quick -Server outlook.office365.com -Impersonation -Credentials (Get-Credential) -MailboxWide -NoSize -Report -WhatIf:$true

    Thanks in advance for your answer !

    Like

    • Just realized : better with Full Mode to use NoSize
      .\Remove-DuplicateItems.ps1 -Mailbox myuser@mydomain.onmicrosoft.com -Type Mail -DeleteMode MoveToDeletedItems -Mode Quick -Server outlook.office365.com -Impersonation -Credentials (Get-Credential) -MailboxWide -NoSize -Report -WhatIf:$true

      My question is still on 🙂

      Like

  36. Hi dear,
    It is an amazing script, really liked it. What if we could use an parameter to say what should be check as a duplicated, like “messageID”. In my environment, mails were duplicated due an replication during migration and with an forward message redirection. It means that mails were received with seconds in difference between the migration process and the forward process. If I had the parameter to say that the messageID is the same, the duplicated mails could be removed.

    Thank you for sharing it! 🙂

    Like

  37. Hi,

    Thanks for this handy script, I’m having an issue in full mode however where it says Cannot access mailbox information store, error: Exception calling “LoadPropertiesForItems” with “2” argument(s): “Requested value ‘GroupMailbox’ was not found.

    I am using exchange api 2.2 with the following command .\Remove-DuplicateItems.ps1 -Mailbox user@domain.com -Server outlook.office365.com -Credentials $Credentials -Mode Body -PriorityFolders ‘Holidays’,’Relief’,’IT Related Stuff’,'[Gmail]’,’Starred’ -MailboxWide -Report -Verbose

    Any ideas?

    Thanks
    Jamie

    Like

    • 2.2 doesn’t understand Group Mailboxes – the updated 2.2.1.2 can process them. Get the package from here, https://www.nuget.org/packages/Exchange.WebServices.Managed.Api/, or when its too complex with nuget, use ‘Download Package’, open the nupkg archive with 7zip or something else, and extract the Microsoft.Exchange.WebServices.dll & xml files to the folder where the script resides. When using verbose, script should report ‘Loaded EWS Managed API v2.2.1.0’.

      Like

      • Hello Michel,
        I am getting exactly the same error as Jamie.
        I performed the fix you mentioned, and turned on verbose output, and it reports it’s “Loaded EWS Managed API v2.2.1.0” but still gets the same error.
        Any further adice?
        Thanks,
        Roger.

        Like

  38. Hi, any news on removing duplicate items for public folder? Or may anyone else has a fork which works with PF? Thank you very much for your work so far!

    Like

    • I have modified version that works on our public folder configuration….
      note it is based 99% on v1.86 of Michel’s script & requires a mailbox with access to the entire tree to be reviewed.
      https://www.dropbox.com/s/mjfu94ie2nf6rlv/RemDup186rg2.ps1?dl=0

      I run it on a portion of the tree at a time.
      Write-Output “Start– $(get-date -Format “ddd dd MMM yyyy HHmmss”) —–”
      if(!$Credentials)
      {
      $Credentials= Get-Credential;
      }

      & $RDup -Mailbox FileMailer -PublicFolders -PFStart “_Projects\2004” -Credentials $Credentials -Impersonation -Report -Force
      & $RDup -Mailbox FileMailer -PublicFolders -PFStart “_Projects\2005” -Credentials $Credentials -Impersonation -Report -Force
      & $RDup -Mailbox FileMailer -PublicFolders -PFStart “_Projects\2006” -Credentials $Credentials -Impersonation -Report -Force

      I will have to diff it with current v1.88

      Like

      • Hello Michel, would be great if you could implement this in nearest release, this feature is expected very much on our side, thanks a lot for your magic script!

        Like

      • Could you please also clarify, what I do wrong?
        PS C:\Users\User\Downloads\Remove-DuplicateItems-master> .\Remove-DuplicateItems.ps1 -Identity ‘user@contoso.com’ -Server outlook.office365.com -Credentials $Credentials -IncludeFolders ‘#Inbox#/03 COOL/0 BPM’ -DeleteMode SoftDelete -MailboxOnly -verbose
        VERBOSE: Loading C:\Program Files\Microsoft\Exchange\Web Services\2.2\\Microsoft.Exchange.WebServices.dll
        VERBOSE: Loaded EWS Managed API v15.00.0913.015
        VERBOSE: Set to trust all certificates
        VERBOSE: Using credentials admin@contoso.com
        VERBOSE: Processing items of type All, delete mode is SoftDelete
        Processing mailbox user@contoso.com (user@contoso.com)
        VERBOSE: Using Exchange Web Services URL https://outlook.office365.com/EWS/Exchange.asmx
        VERBOSE: Constructing folder matching rules
        VERBOSE: Processing primary mailbox user@contoso.com
        VERBOSE: Collecting folders to process, type All

        (I have changed user email intentionally) It stops on the latest message and nothing continue.

        Like

  39. Michel,
    I really look forward to getting this to work, however I seem to run across a similar issue as many others:

    Cannot access mailbox information store, error: Exception calling “.ctor” with “0” argument(s): “This implementation is not part of the Windows Platform FIPS validated cryptographic algorithms.”

    I have given myself impersonation rights, as well as full permissions to the mailbox in question (a different user). I’ve tried both -Impersonation and the -Credential method.

    I see a lot of issues for people regarding “Cannot access mailbox information store” but that seems to be the permission issue that is supposed to be fixed by giving impersonation/full access (with inheritance). However, I don’t see anything regarding the follow up part of the error mentioning FIPS. Unfortunately I’m in an environment where I cannot simply “disable FIPS”, it is a security requirement. Does that mean I’m out of luck? Is there some sort of switch that bypasses what FIPS may be complaining about? Some sort of alteration in the script that will allow it to be FIPS “compliant”. It seems to scope the mailbox just fine in the debug, but fails right after it starts to process the folders. I can even see the first item of the folder that it hits. If you have any idea how to address this, I’d super appreciate it.

    .\Remove-DuplicateItems.ps1 -Mailbox user.samaccountname -Type all -Impersonation -DeleteMode MoveToDeletedItems -Mode Full -Verbose -Debug

    I’m on-prem with Exchange 2016 CU15
    Using Remove-DuplicateItems.ps1 Version 1.88
    $PSVersionTable

    Name Value
    —- —–
    PSVersion 5.1.14393.3866
    PSEdition Desktop
    PSCompatibleVersions {1.0, 2.0, 3.0, 4.0, 5.0, 5.1.14393.3866}
    BuildVersion 10.0.14393.3866
    CLRVersion 4.0.30319.42000
    WSManStackVersion 3.0
    PSRemotingProtocolVersion 2.3
    SerializationVersion 1.1.0.1

    If, in the case I’m out of luck because of FIPS, I still appreciate your time, not only in responding, but creating what looks to be a superb script.

    Like

    • Sorry, scripts are untested with FIPS locked down environments. That said, it’s not that the script shouldn’t work, I assume it’s a matter of crypto settings and defaults. Not totally into this, but could you set this (I assume no it environment is locked down) and run the script?
      HKLM\System\CurrentControlSet\Control\Lsa\FIPSAlgorithmPolicy\Enabled=0

      Like

      • Sorry for the delay. Unfortunately, manually setting the registry key (as you mentioned above) did not work. Nor did temporarily removing the GPO that enabled FIPS cryptography. Very unfortunate. I was going through your script to find what could potentially be causing this. I noticed this section:

        Function Get-Hash {
        param(
        [string]$string
        )
        $md5 = New-Object -TypeName System.Security.Cryptography.MD5CryptoServiceProvider
        $data = ([system.Text.Encoding]::UTF8).GetBytes( $string)
        return ([System.BitConverter]::ToString( $md5.ComputeHash( $data)) -replace ‘ – ‘, ”)
        }

        When I run that function all by its lonesome in a PowerShell session, I get presented with the same error! I have changed the encoding from MD5 to SHA256 in that function and now it works (or so it seems, I’m still running a test). OOOH man, so excited lol. Thanks. Crossing my fingers 🙂

        Like

  40. This script looks perfect, especially since I was advised post-migration that users had been forwarding all their email from an old domain to their new one, creating duplicates of their entire mailboxes. I’m trying to run this from the admin context against Office365, but can’t get it to work. Do you need to use the credentials of the account that you’re accessing, or can a Global Admin’s account be used? That seemed to be the function of the impersonate, but I haven’t been able to get it to execute properly. I’ve managed to get as far as getting an auth error with the user mailboxes. Appreciate your help and your awesome script!

    Like

  41. Hello,
    first of all Thanks for the Script and the Script to remove Items from a Mailbox. Is there a Way to only prioritize Subfolders of a Folder and not the Folder itself?

    Like

  42. Pingback: Annual Report 2020 | EighTwOne (821)

  43. Can this script (or maybe this one with modifications) be used to remove duplicates between two separate non-archive mailboxes? I’m hoping to locate something that can identify e-mails with identical message IDs distributed between two mailboxes and allow the deletion of one set of messages. The ability to dump the IDs and message properties to a CSV for review would also be useful. Any thoughts or pointers to get me going in the right direction? Have strong Powershell skills but the EWS component has always featured a layer of complexity beyond what I’m familiar with. Thanks in advance!

    Like

    • This script, no. Can it be made, yes. However, that would basically mean going through both, collecting things uniquely identifying mail in one (e.g. message ID and path for reference), and looking for presence in the other (reporting ID and path in mailbox A and mailbox B). That is the business case, if I may ask?

      Like

  44. Thanks Michel. Business case is a one-off unique situation – a user’s mailbox was split into two due to high folder counts and at Microsoft support’s recommendation. It was discovered later that for a period of time, emails were delivered to both mailboxes. We want to dedupe these message before we archive his mailbox as the dupes will be a source of annoyance / confusion for the end user.

    I’ve opened a case with Microsoft about this as well, but thus far they’ve been less than helpful. Your suggestions are helpful though, and I’ve made some progress just binding to a folder and producing FirstClassProperties of items.

    Like

    • Hi Kevin, to circle back on this: Could be more simple on second thought: The entry which initializes the variable to keep track of entries ‘seen’ before is initialized at the start when processing the mailbox. It is re-initialized after processing the folder, depending MailboxWide switch. You could of course move initialization to start of script, and comment all reinitializations out. Then, pass the mailboxes you want to process (you can pass more identities) so it will ‘know’ items seen in the first mailbox, and identical items from second (and third etc). identity will be considered duplicate. Now, to save you work, in 2.03 I removed MailboxWide and introduced -CleanupMode where you can specify MultiMailbox (and fixed identity parameter accepting multiple entries). So, you can do this (added whatif & report to make example non-destructive):
      .\Remove-DuplicateItems.ps1 -Identity peter@contoso.com,frank@contoso.com .. -CleanupMode MultiMailbox -Verbose -WhatIf:$true -Report

      Like

Leave a reply to Sandra Cancel reply