Last version: 2.00, February 27th, 2021
Recently, I was asked if it is possible to remove stub items. The reason was they were going to transition to a newer version of Exchange and they wouldn’t be using the archiving solution in the new environment. When required, vendor tooling would be used to search through the existing archives.
In such cases it makes sense to remove the stubs from the mailbox, which are shortcut messages that points to a copy of the original message in the archive solution. The new environment won’t contain the required Outlook plugins or extensions to retrieve the original message from the archive using the stub, making the stub lead to a partial or empty message.
To identify stubs, one can filter on an attribute of each item, MessageClass. This attribute defines which kind of item it is (in fact, determines what form Outlook should use in order to present or process the information). Examples of MessageClass definitions are IPM.Note (regular e-mail messages), IPM.Note.EnterpriseVault.Shortcut (message archived by Enterprise Vault) or IPM.ixos-archive (message archived by Opentext/IXOS LiveLink E-Mail Archive).
To identify stubs from Outlook, add the Message Class field to your Outlook view, e.g.:
When you want to remove the stubs using Outlook, you can utilize the Advanced Find function of Outlook, but that is a very labor intensive, tedious and non-centralized per-mailbox procedure:
Requirements
Using the 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-MessagesClassItems.ps1 uses the following syntax:
Remove-MessageClassItems.ps1 [-Identity] [-MessageClass] [-Type] [-Server ] [-Impersonation] [-DeleteMode ] [-Type] [-Before ] [-MailboxOnly] [-ArchiveOnly] [-IncludeFolders] -ExcludeFolders [-NoProgressBar] [-Force] [-WhatIf] [-Confirm] [-Secret] [-CertificateThumbprint] [-CertificateFile] [-CertificatePassword] [-TenantId] [-ClientId] [-TrustAll]
A quick walk-through on the parameters and switches:
- Identity is the name or e-mail address of the mailbox.
- MessageClass specifies the Message Class to remove, for example IPM.Note.EnterpriseVault.Shortcut (EnterpriseVault). You can use wildcards around or at the end to include folders containing or starting with this string, e.g. ‘IPM.ixos*’ or ‘*EnterpriseVault*’. Matching is always case-insensitive.
- Server is the name of the Client Access Server to access for Exchange Web Services. When omitted, the script will attempt to use Autodiscover.
- Type determines what folder class to process. Options are Mail, Calendar, Contacts, Tasks, Notes or All (Default).
- Switch Impersonation specifies if 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). Note that the Deleted Items folder will be processed, unless MoveToDeletedItems is used.
- Before can be used to only remove items received before specified date.
- 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. - NoProgressBar prevents displaying a progress bar as folders and items are being processed.
-
ReplaceClass specifies that instead of removing the item, its PR_MESSAGE_CLASS class property will be modified to this value. For example, can be used in conjunction with MessageClass to modify any IPM.Note items pending Evault archival back to regular items, using: -MessageClass IPM.Note.EnterpriseVault.PendingArchive -ReplaceClass IPM.Note
- 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.
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).
Well-Known Folders
For IncludeFolders, ExcludeFolders, 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 or ExcludeFolders, 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 |
Example
Suppose you want to remove IPM.Note.EnterpriseVault.Shortcut items from the mailbox of user1 and personal archive when enabled, moving the items to the DeletedItems by Impersonation. In such case, you could use the following cmdlet:
Remove-MessageClassItems.ps1 -Identity user1 -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode MoveToDeletedItems -Impersonation –Verbose
Note: Screenshot shows Mailbox parameter, which is per 1.52 renamed to Identity
Note: By default, Remove-MessageClassItems will only search IPF.Note class folders (i.e. containing mail items), so you’ll only see those being processed. If you want all folders scanned (also classless), use the ScanAllFolders switch.
The script also supports Office 365. For example, to remove all items with ‘Enterprise’ in their message class text, received before 1/1/2014, only from the primary mailbox, excluding the folder Personal, using Basic Authentication, you can use:
$Credentials= Get-Credential Remove-MessageClassItems.ps1 -Identity olrik@office365tenant.com -DeleteMode MoveToDeletedItems -MessageClass *EnterpriseVault* -Before 1/1/2014 -MailboxOnly -ExcludeFolder Personal -Credentials $Credentials
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-MessageClassItems.ps1 -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode HardDelete
Feedback
You’re feedback is welcomed through the comments; if you got scripting suggestions, please use the contact form.
Download
You can download the script from the GitHub here.
Pingback: Removing Messages by Message Class (Updated) | EighTwOne (821) | JC's Blog-O-Gibberish
Michel, I would appreciate to learn more about the migration from EV to Exchange archiving. We are planning on moving from an Exchange 2007/EV 9.0.2 implementation to Exchange 2013 and the road block is the 34TB of data in EV and how best to get it back to exchange. On the plus side, we are not stubbing our emails.
LikeLike
Transvault 🙂
Nb : when you say 34TB is y compressed and duplicated DATA (singleinstanceless) ? Or just the DATA in disk ?
Regards,
Ben
LikeLike
Depends on scenario and setup. This customer cut off their archived data (ie isolated, available when required using vendor tools) and will move not (yet) archived mailbox data to the new e-mail environment, facilitating large mailboxes. Otherwise, they’d have to inject the original mail items using the stubs from the archive, but as that data is rarely consulted but has a significant storage footprint, they chose to cut it off.
LikeLike
Fantastic script! This is extremely useful in removing third-party voice mail messages from the Exchange environment. Not being very adept at EWS scripitng(but learning); I’d like to know how would the script be modified to find messages of a specific class older than, let’s say, 45-days?
(define in base property set and then filter?)
LikeLike
The line with “[Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, $MessageClass)” defines the item filter. It’s a single condition; if you want to combine multiple conditions, you need to utilize a SearchFilterCollection where you add all the individual conditions. Then, pass that collection instead of the single condition to FindItems, e.g.
..
$ItemSearchFilter1= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo( [Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, $MessageClass)
$ItemSearchFilter2= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo( [Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, (Get-Date).AddDays(-45))
$SearchFilterCollection= New Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
$SearchFilterCollection.add( $ItemSearchFilter1)
$SearchFilterCollection.add( $ItemSearchFilter2)
Do {
$ItemSearchResults= $SubFolder.FindItems( $ItemSearchFilterCollection, $ItemView)
..
Let me know if there’s more animo for this; I could make item age a parameter of course 🙂
LikeLike
Thank you for the prompt reply. When I replace the code to create the SearchFilterCollection..I get an error regarding “New”…seems to run, then remove all messages, not just message class specified. (Of course, working in a test environment)
[PS] E:\hold\msgclass>.\Remove-MessageClassItems45days.ps1 -Mailbox mbxrestore -MessageClass IPM.Note.Adomo.VM -DeleteMode MoveToDeletedItems -Impersonation -Verbose
Processing mailbox mbxrestore
VERBOSE: Loading Microsoft.Exchange.WebServices.dll
VERBOSE: Set to trust all certificates
VERBOSE: Using MBX.Restore@xxxxxx.xxxfor impersonation
VERBOSE: Looking up EWS URL using Autodiscover for MBX.Restore@xxxxxx.xxx
VERBOSE: Using EWS on CAS https://owa.xxxxxx.xxx/EWS/Exchange.asmx
VERBOSE: DeleteMode is MoveToDeletedItems
VERBOSE: Removing messages of class IPM.Note.Adomo.VM
VERBOSE: Processing folder Drafts
The term ‘New’ is not recognized as the name of a cmdlet, function, script file, or operable program. Check the spellin
g of the name, or if a path was included, verify that the path is correct and try again.
At E:\hold\msgclass\Remove-MessageClassItems45days.ps1:166 char:38
+ $SearchFilterCollection= New <<<< Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollec
tion([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
+ CategoryInfo : ObjectNotFound: (New:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
You cannot call a method on a null-valued expression.
At E:\hold\msgclass\Remove-MessageClassItems45days.ps1:167 char:35
+ $SearchFilterCollection.add <<<< ( $ItemSearchFilter1)
+ CategoryInfo : InvalidOperation: (add:String) [], RuntimeException
+ FullyQualifiedErrorId : InvokeMethodOnNull
LikeLike
New should be New-Object. Additional code was provided as guidance (so you get the idea on the approach), not as working example. I’ll have a look at it later on.
LikeLike
Ok. Sounds good.Thanks again.
LikeLike
Change:
$ItemSearchFilter= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo( [Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, $MessageClass)
Do {
$ItemSearchResults= $SubFolder.FindItems( $ItemSearchFilter, $ItemView)
to:
$ItemSearchFilter1= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo( [Microsoft.Exchange.WebServices.Data.ItemSchema]::ItemClass, $MessageClass)
$ItemSearchFilter2= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsLessThanOrEqualTo( [Microsoft.Exchange.WebServices.Data.ItemSchema]::DateTimeReceived, (Get-Date).AddDays(-45))
$ItemSearchFilterCollection= New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+SearchFilterCollection([Microsoft.Exchange.WebServices.Data.LogicalOperator]::And);
$ItemSearchFilterCollection.add( $ItemSearchFilter1)
$ItemSearchFilterCollection.add( $ItemSearchFilter2)
Do {
$ItemSearchResults= $SubFolder.FindItems( $ItemSearchFilterCollection, $ItemView)
LikeLike
Fantastic! Works perfectly! Thanks so much for your effort. I enjoy your blog and the UC Podcasts.
Regards.
LikeLike
Pingback: The UC Architects » Episode 22: A Game of Clouds
Fantastic !! Can’t thank you enough. Is it possible to make age as one of the parameters and also parameter to include a specific folder.
Regards.
LikeLike
Thanks for your suggestions; was already working on update, which has just been published. Might consider Exclude/Include options for future releases.
LikeLike
Can you give me some pointer as how to exclude messages in “Managed Folder” and its subfolders. We use Exchange Managed Folders for classifying important emails.
Regards
LikeLike
Took a while, but 1.5 contains what you’re looking for 🙂
LikeLike
Oops!! I meant exclude a specific folder.
Thanks
LikeLike
Added as option in 1.5
LikeLike
Thanks for the script. I am going to try to use it to see if my novice PS skills can change it from deleting items with a specified message class to changing them to a similiar but different message class. If you happen to catch this and have suggestions they would be appreciated.
Thanks again for your contributions to date.
J
LikeLike
I found a similar solution using the search-mailbox command. I chose this meathod because I’m not using Exchange Web Services.
Search-Mailbox -Identity $UserName -SearchQuery “IPM.NOTE.EnterpriseVault.Shortcut” -DeleteContent
You can test with the following commands.
This produces a report with the number of hits
Search-Mailbox -Identity $UserName -SearchQuery “IPM.NOTE.EnterpriseVault.Shortcut” –EstimateResultOnly
This will search a mailbox, and all hits will be copied to another mailbox. You can look at that mailbox and see exactly what would be deleted if you used the -DeleteContent command.
Search-Mailbox -Identity $UserName -SearchQuery “IPM.NOTE.EnterpriseVault.Shortcut” -TargetMailbox “TestMB” -TargetFolder “$UserName”
LikeLike
Mike,
sorry to latch on so late, but i’ve tried doing the search way (because i thought it would be faster), but the content detected doesn’t seem to catch everything. I’d like to use search because it’s faster.
Thoughts?
LikeLike
Just tried this script today but unfortunately it’s not working for me. In verbose mode I can see it’s processing all the folders, but it didn’t find any e-mails with the class “IPM.Note.EnterpriseVault.Shortcut”.
LikeLike
So, there aren’t any of those classes or the class specified is not matching. Can you elaborate a bit more on the situation?
LikeLike
After reading the comment below, I know why it’s not working for me. The stub mail items are all in the archive mailbox. Because the script did show all folders including the ones in the archive mailbox I thought it was also working for the archive. I will use the search-mailbox cmdlet for now. If you include the option to process the archive it will be a great script. Keep up the good work!
LikeLike
As you may have read below, I’ve put archive processing on the list 🙂
LikeLike
This is an awesome script. Thank you so much for taking the time to publish it.
What if the stub is already in the user’s Personal Archive? Can we use the script to remove stubs that have already been moved to the user’s archive?
LikeLike
Script currently only processes mailbox, but good suggestion,thank you. I’ll put it on the to do list.
LikeLike
This is gold! Thanks so much.
LikeLike
Hello Michel,
when I run the script I get the following. I’m running the script as a Exchange Administrator and I have full mailbox rights on this test account. I doesn’t remove any of the EAS messageClass items.
[PS] C:\>.\Remove-MessageClassItems.ps1 -Mailbox Training6 -DeleteMode SoftDelete -MessageClass IPM.Note.EAS -ScanAllFolders -verbose
Processing mailbox Training6
VERBOSE: Loading Microsoft.Exchange.WebServices.dll
VERBOSE: Set to trust all certificates
VERBOSE: Looking up EWS URL using Autodiscover for Training6@****.com
VERBOSE: Using EWS on CAS https://mail.****.com/EWS/Exchange.asmx
VERBOSE: DeleteMode is SoftDelete
VERBOSE: Removing messages of class IPM.Note.EAS
VERBOSE: Scanning all folders
VERBOSE: Processing folder Calendar
VERBOSE: Processing folder Contacts
VERBOSE: Processing folder Conversation Action Settings
VERBOSE: Processing folder Drafts
VERBOSE: Processing folder Inbox
VERBOSE: Processing folder Journal
VERBOSE: Processing folder Junk E-Mail
VERBOSE: Processing folder Notes
VERBOSE: Processing folder Outbox
VERBOSE: Processing folder Quick Step Settings
VERBOSE: Processing folder RSS Feeds
VERBOSE: Processing folder Sent Items
VERBOSE: Processing folder Suggested Contacts
VERBOSE: Processing folder Sync Issues
VERBOSE: Processing folder Conflicts
VERBOSE: Processing folder Local Failures
VERBOSE: Processing folder Server Failures
VERBOSE: Processing folder Tasks
LikeLike
Please check permissions or configure impersonation (see links in article for instructions) and try again.
LikeLike
Yup the impersonation rights worked! I guess the full mailbox isn’t good enough!
Thanks a lot you have no idea how much time this will save me lol 🙂
LikeLike
Great script. Thanks for it. I have a few suggestions that you can take or leave.
Enhancement Suggestions:
– Include a parameter to specify the EWS API location of not installed to the default location
– Include a parameter to run as a desired account to impersonate.
-Include a parameter to change the default EWS Exchange2007_SP1 config to other versions of Exchange
+ I did this as part of Troubleshooting my issues and it appeared to not be the root cause of the issue. Perhaps this is not required because of it.
– Provide a parameter to output verbose output to a log file (I know we can pipe it… but it would be nice to have on screen and off screen output)
Thanks again for the hard work and responsive assistance
LikeLike
Hi,
I’ve managed to get the script to run without error now (had various syntax issues), but it doesn’t seem to be doing anything. After hitting enter, I just get a line showing ‘>>’ and no further action happens.
I am trying to permanently remove EV stubs in Exchange 2010:
.\Remove-MessageClassItems.ps1″ -Mailbox TomU -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode HardDelete -Impersonation –Verbose
Any ideas please?
Thanks
LikeLike
You shouldn’t have to edit the script. If you copied/pasted the exact cmdlet, there’s a quote mismatch (the >> means its waiting for more input since you didn’t enter a closing quote). Try this:
.\Remove-MessageClassItems.ps1 -Mailbox TomU -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode HardDelete -Impersonation –Verbose
LikeLike
My bad, I didn’t edit the script, just the cmdlet. Your amendment now generates an error telling me it is not digitally signed? Appreciate your help.
File C:\2010\Remove-MessageClassItems.ps1 cannot be loaded. The file C:\2010\Remove-MessageClassItems.ps1 is not digitally signed. The script will not execute on the system. Please see “get-help about_signing” for more details..
At line:1 char:31
+ .\Remove-MessageClassItems.ps1 <<<< -Mailbox TomU -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode HardDe
lete -Impersonation -Verbose
+ CategoryInfo : NotSpecified: (:) [], PSSecurityException
+ FullyQualifiedErrorId : RuntimeException
LikeLike
Run the script after executing
Set-ExecutionPolicy Unrestricted
LikeLike
Thanks, getting there…. A whole host of errors now though. Appreciate your time but understand if you have better things to be doing!
Processing mailbox TomU
VERBOSE: Loading Microsoft.Exchange.WebServices.dll
Exception calling “LoadFile” with “1” argument(s): “The system cannot find the file specified. (Exception from HRESULT:
0x80070002)”
At C:\2010\Remove-MessageClassItems.ps1:253 char:46
+ [void][Reflection.Assembly]::LoadFile <<<< ( $EwsDll)
+ CategoryInfo : NotSpecified: (:) [], MethodInvocationException
+ FullyQualifiedErrorId : DotNetMethodException
Unable to find type [Microsoft.Exchange.WebServices.Data.ExchangeVersion]: make sure that the assembly containing this
type is loaded.
At C:\2010\Remove-MessageClassItems.ps1:257 char:80
+ $ExchangeVersion= [Microsoft.Exchange.WebServices.Data.ExchangeVersion] <<<< ::Exchange2007_SP1
+ CategoryInfo : InvalidOperation: (Microsoft.Excha…ExchangeVersion:String) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
New-Object : Cannot find type [Microsoft.Exchange.WebServices.Data.ExchangeService]: make sure the assembly containing
this type is loaded.
At C:\2010\Remove-MessageClassItems.ps1:258 char:32
+ $EwsService= New-Object <<<< Microsoft.Exchange.WebServices.Data.ExchangeService( $ExchangeVersion)
+ CategoryInfo : InvalidType: (:) [New-Object], PSArgumentException
+ FullyQualifiedErrorId : TypeNotFound,Microsoft.PowerShell.Commands.NewObjectCommand
Property 'UseDefaultCredentials' cannot be found on this object; make sure it exists and is settable.
At C:\2010\Remove-MessageClassItems.ps1:259 char:21
+ $EwsService. <<<< UseDefaultCredentials= $true
+ CategoryInfo : InvalidOperation: (UseDefaultCredentials:String) [], RuntimeException
+ FullyQualifiedErrorId : PropertyNotFound
VERBOSE: Set to trust all certificates
VERBOSE: Using TomU@contoso.com for impersonation
Unable to find type [Microsoft.Exchange.WebServices.Data.ConnectingIdType]: make sure that the assembly containing this
type is loaded.
At C:\2010\Remove-MessageClassItems.ps1:270 char:165
+ $EwsService.ImpersonatedUserId= New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Micros
oft.Exchange.WebServices.Data.ConnectingIdType] <<<< ::SmtpAddress, $EmailAddress)
+ CategoryInfo : InvalidOperation: (Microsoft.Excha…onnectingIdType:String) [], RuntimeException
+ FullyQualifiedErrorId : TypeNotFound
VERBOSE: Looking up EWS URL using Autodiscover for TomU@contoso.com
Write-Error : A positional parameter cannot be found that accepts argument 'You cannot call a method on a null-valued e
xpression.'.
At C:\2010\Remove-MessageClassItems.ps1:286 char:28
+ Write-Error <<<< "Autodiscover failed: " $error[0]
+ CategoryInfo : InvalidArgument: (:) [Write-Error], ParentContainsErrorRecordException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Microsoft.PowerShell.Commands.WriteErrorCommand
LikeLike
@Tom: “Using this script requires Exchange 2007 or later and Exchange Web Services Managed API 1.2 (or later) which you can download here or you can copy the Microsoft.Exchange.WebServices.DLL locally and adjust the DLL path mentioned in the script when necessary. “
LikeLike
Ah ok thanks, we are using 2010 but I will need to discuss with our main admin about the web services DLLs ec.
Appreciate your time.
LikeLike
@No need to install; you can install it elsewhere, copy the Microsoft.Exchange.WebServices.DLL in the same location as the script and change the location (in the script) accordingly. Updated version of script will have additional logic to look for that DLL by the way.
LikeLike
Great, thanks!
LikeLike
Me again…. Now I’ve got this far… “Can’t access mailbox information store” ?
Cheers
Processing mailbox TomU
VERBOSE: Loading Microsoft.Exchange.WebServices.dll
VERBOSE: Set to trust all certificates
VERBOSE: Using TomU@square-enix.com for impersonation
VERBOSE: Looking up EWS URL using Autodiscover for TomU@xxx
VERBOSE: Using EWS on CAS https://xxx/EWS/Exchange.asmx
C:\2010\Remove-MessageClassItems.ps1 : Can’t access mailbox information store
At line:1 char:31
+ .\Remove-MessageClassItems.ps1 <<<< -Mailbox TomU -MessageClass IPM.Note.EnterpriseVault.Shortcut -DeleteMode HardDe
lete -Impersonation -Verbose
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-MessageClassItems.ps1
LikeLike
Permissions; see instructions on usage (for links on) how to configure.
LikeLike
Ok , I did see that just thought I’d have permissions on my own mailbox already 8)
Thanks again! By the way, is there anyway to delete (or edit) this thread? I fear leaving a full email address showing from the scripts wasn’t ideal.
LikeLike
No, but changed them for you; you now work for Contoso 🙂
LikeLike
You’re too kind 🙂
LikeLike
I have tried on a couple of users who’s mailboxes I have full access permissions on, however I am still getting an error stating it can’t access the mailbox information store.
Do I have to use impersonation in 2010 or something?
Thanks
LikeLike
That would be the most elegant way. There are some pointers on how to set this up here
LikeLike
Is it possible to target only one folder? For instance I want to delete the
IPM.Note.Microsoft.Conversation files from the ConversationHistory folder on 139 mailboxes. I have my csv file ready but I was hoping to avoid running the script against all of the folders in each mailbox.
Thanks!
LikeLike
No, not yet. I’ll put it on the request list.
LikeLike
Thanks! One more thing – how can I export the results to a file? I need to run all my mailboxes with the whatif switch and analyse the results before I allow the actual deletions. Great script by thwe way.
LikeLike
whats wrong with just using:
Search-Mailbox -Identity jobloggs -SearchQuery “IPM.NOTE.EnterpriseVault” -DeleteContent
LikeLike
Hi,
I wanted to know whether this script will work on a 2013 exchange evironment? i have followed the directions posted in reference to impersonation, but still running into errors whether i excute the script from a CAS or MBX server. I am trying to delete stubs from a legacy email archive solution.
Thanks!
LikeLike
Have you waited for permissions to propagate? It can take up to 2 hrs due to caching etc.
LikeLike
Thanks for this script.. I’m trying to purge EV Shortcuts from a broken EV environment before a mail migration to O365. Script works fine for the most part but for a few users I get the “Can’t access mailbox information store” at line 1 char:31. These are users that are on the exact same mailbox database that users that the script works fine for. Impersonation is set on the account I’m using to run the script and again seems to work for the other users. Size issue? (these are fairly large Exchange 2010 mailboxes) I went so far as to specifically add Full right and send as to these problem mailboxes with no luck
LikeLike
Quick follow up.. I notice for some of my users that the script is working for I have to run it a few times to catch all the EV stubs. Not sure if that means anything.
LikeLike
Figured it out.. I did a
get-mailbox -identity “username” | export-csv user.csv -notype
On the users that were not working and discovered that despite showing as a regular User Mailbox in Exchange 2010 Management Console these mailboxes were apparently Linked Mailboxes. I discovered this by comparing all the properties of the mailboxes that did not work vs the ones that did and discovered that the failing mailboxes had a Linked Maser Account value (I have a very old Exchange environment that originally started as Exchange 5.5 so somewhere along the way during the migrations some mailboxes came across as Linked)
So I ran
Set-User -Identity user@fabrikam.com -LinkedMasterAccount $null
against the failing mailboxes and now the script is working.
LikeLike
Will this work against office 365. I have tried several times without luck. Getting the following error.
C:\Scripts\Remove-MessageClassItems.ps1 : Can’t access mailbox information store
LikeLike
No, not yet. o365 support is on the to-do list.
LikeLike
Pingback: Script Updates | EighTwOne (821)
Hi,
I’m running the script and it seems to be working great, (both against on prem and cloud users), however on certain users it just stalls out on various folders. They don’t seem to be that large but they just can’t process past them. I’ve run it in verbose but i don’t see anything specific being reported.
LikeLike
I dont think the “before” switch is working, or I am using the wrong format. What format does the -before switch need. Does it need the date that you want all items older than that to be deleted, or is it the number of days before. If it is date, what format do you need date? I tried MM/DD/YYYY and YYYY/MM/DD and it does not work properly with any of those. Or at least it’s not parsing it correctly. See the results below. Using the -before, it is still trying to remove ALL my stubs, not just the ones before the date I have specified. I am running it against an Exchange 2007 SP3 environment in preparation for moving to Exchange 2013 SP1
[PS] C:\Download>.\Remove-MessageClassItems.ps1 -Mailbox %USERNAME% -MessageClass IPM.Note.MimosaStubmimosa1 -Server cas2.MYDOMAIN.COM -DeleteMode har
ddelete -Before 2013/06/01 -Verbose
VERBOSE: Loading C:\Program Files\Microsoft\Exchange\Web Services\2.0\\Microsoft.Exchange.WebServices.dll
Processing mailbox USERNAME (%USERNAME%@MYDOMAIN.COM)
VERBOSE: Set to trust all certificates
VERBOSE: Using Exchange Web Services URL https://cas2.MYDOMAIN.COM/EWS/Exchange.asmx
VERBOSE: DeleteMode is harddelete
VERBOSE: PartialMatching is False
VERBOSE: Removing messages of class IPM.Note.MimosaStubmimosa1
VERBOSE: Removing messages older than 06/01/2013 00:00:00
VERBOSE: Scanning all IPF.Note (E-mail) folders
VERBOSE: Processing folder Deleted Items
VERBOSE: Processing folder Drafts
VERBOSE: Processing folder Inbox
Confirm
Are you sure you want to perform this action?
Performing operation “Remove-MessageClassItems.ps1” on Target “Remove 431 items from Inbox”.
[Y] Yes [A] Yes to All [N] No [L] No to All [S] Suspend [?] Help (default is “Y”):
LikeLike
The format provided should be in the current locale, e.g. mm/dd/yyyy (it’s of type datetime so you could fit in a time as well). This is evaluated against the item’s Received attribute. To see the expected format, use:
(Get-Culture).dateTimeFormat | Select *Pattern
(don’t have Ex2007 at hand, should this be a PoSH 1 quirk, you can run it from system running a more recent version of PoSH – it will run against your mailbox on Ex2007SP1+).
LikeLike
I ended up finding out it was an issue with impersonation. When I use impersonation it works fine. I also ran it from a 2012 server running Powershell 3 and the Exchange 2013 tools on it. One additional thing, when it goes to delete the items, it always prompts you to confirm. This is a good thing by and large. But it seems for whatever reason when it calculates the number of items in the inbox, it is more than double what the actual stubbed email count is. Every other folder it seems to be 100% accurate. Can you think of a reason for this, or perhaps it might be a quirk?
At any rate, I have to compliment you on this and a couple other powershell scripts I have found on your site (the delete duplicate items one), they have saved me a ton of hassle. I was planning on just using managed default folder policy to just delete all emails older than a certain thresshold just to purge the stubs, but this is much more palatable to the end user…
LikeLike
Michael, I found another thing I cannot explain. When running the script, it appears to not parse certain mail folders inside certain users mailboxes at all. Nothing special about these folders. I thought it might be a permissions thing, but looking at folder permissions, it seems that there would be nothing inhibiting it. Plus I thought with Impersonation, folder permission should be irrelavent. I could look at something in MFCMapi or PFDavAdmin if you want, but I am not sure what to look for. I did verify the messageclass is identical across all instances, (IPM.Note.MimosaStubMimosa1), so it’s not like some stubs have different message class than others. Every test user I have run this against has similar results. It’s just not hitting all folders.
LikeLike
Michael, I think I may have found my problem, let me know if you think. When looking at the script run, I found this text when running in verbose mode: “VERBOSE: Scanning all IPF.Note (E-mail) folders”. This led me to go into MFCMapi and look at the folders not being parsed. It appears none of these folders have the “PR_CONTAINER_CLASS” of IPF.Note. In fact, the folders do not have even have the “PR_CONTAINER_CLASS” field at all. Not just not poplulated, they do not have that attribute at all. For your information, about 80% of my users were migrated to Exchange from Groupwise many years ago, and it’s possible that when these folders were created in Exchange at that time by the (Quest) Migration tool, it created the folders as some odd type? Just throwing this out there. You may or may not have a way to fix this… thanks again.
LikeLike
The ScanAllFolders switch should allow the script to find (and remove) items in all folders (default is IPF.Note only). I’m not sure if Exchange would return “class-less folders”.
LikeLike
Thank you very much Michel, the -scanallfolders switch did absolutely work! this is great!
LikeLike
Message Classes can be exported and deleted with a simple command of which I blogged about here:
http://mrmapi.com/2014/01/08/migrating-from-symantec-enterprise-vault-to-exchange-archive-mailbox/
Thanks,
Jason
LikeLike
All roads lead to Rome. Yet, that requires Ex2010 or up, EMS or being member of the Discovery Management role group to name a few. There are lots of pre-Ex2010 customers that want to get rid of the stubs before moving data over (On-Prem or ExO). The script is not meant to be a replacement for Search-Mailbox (as indicated in another comment).
LikeLike
The search-mailbox command does not exist in Exchange 2007. Just a heads up that there are thousands of customers out there still using Exchange older than 2010. Sometimes Microsoft forgets that. We cant all be bleeding edge.
LikeLike
For those wanting to actually bring their Enterprise Vault archived data to their new environment (Exchange 2010, Exchange 2013, Office 364 or Google Apps for Business), our Archive Accelerator Restore product can do that. (link removed)
Dave
LikeLike
I have written it to remove message by using outlook script
http://msexchange.me/2014/11/15/remove-messages-based-on-message-class-outlook-powershell/
LikeLike
Pingback: Remove EnterPriseVault Shortcut Class Message after Office 365 Migration | Microsoft Technologies Blog
Hi Michel,
Thanks for the script!
I was using search-mailboxformessageclass.ps1 first, but this one seems easier to use. (especially that you can use the partial parameter)
I do have a problem however that no emails are found.
When I run it with the other powershell, it does find results.
I’m looking in the correct mailbox (not archive)
LikeLike
“the other zPowerShell” ? Script needs to be run (read: Tested) from regular PoSH
LikeLike
Hi Michel,
I previously used the script used here :
http://blogs.msdn.com/b/emeamsgdev/archive/2013/06/25/powershell-search-mailbox-for-items-of-a-particular-message-class-itemclass.aspx
I’ve managed to get your script working after configuring impersonation.
I can’t get it running without it.
The account I’m using is in another domain than the user mailboxes, so that might be the reason?
LikeLike
I am not aware of any resource-forest limitations. What is the issue?
LikeLike
I Love the script ! Its saved no end of time and effort, its very easy to use and does exactly what it says,
What it does do though, is if a read reciept had been archived and it removed the reciept stub, Exchange sends an email to sender of message stating that the item was deleted and not read.
Is there anyway to prevent this happening ?
This will no doubt generate quite a few bits of confusion on mass mailbox enviroments.
LikeLike
Thanks for the suggestion. That has already been put on the list to be implemented in a next version.
LikeLike
We resolved this by creating a transport rule which caught read-receipts from sender (mailboxes being processed ) this caught them whilst script ran.
LikeLike
Really helpful script, I am looking for option to get only the shortcut count not to delete them.
If you help me with this I will be really great
LikeLike
You can add output showing the number of items found, without performing the actual removal. For example:
If( $ItemSearchResults.Items.Count -gt 0) {
Write-Output “Found $($ItemSearchResults.Count items in $($SubFolder.DisplayName)”
}
LikeLike
I couldn’t get this working, if possible can you add in the script and post here please.
LikeLike
Any other options for processing against multiple mailboxes?
I’ve tried the imiport-csv option but I get an error that The term ‘Remove-MessageClassItems.ps1’ is not recognized as the name of a cmdlet. I would like to be able to run this on a per database level.
get-mailboxdatabase | get-mailbox | The term ‘Remove-MessageClassItems.ps1
LikeLike
pasted bad:
get-mailboxdatabase | get-mailbox | Remove-MessageClassItems.ps1
LikeLike
Try .\Remove-MessageClassItems.ps1
LikeLike
Getting issue as below…..
C:\Remove-MessageClassItems.ps1 : Can’t access mailbox information store
At line:1 char:1
+ .\MessageClass1.ps1 -Mailbox Test1 -MessageClass IPM.Note.Aftermail …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-MessageClassItems.ps1
LikeLike
Check the other comments, attention areas are permissions, firewalls etc.
LikeLike
My comment on the get-mailboxdataBase | removemessageclass was a request. It would be nice to run this on a database level.
LikeLike
Hi Michel, We have 1200 mailboxes which need the archive stub removed, and the script runs fine, but fails on 10%, for whatever reason, is there a way to ID why and which mailboxes failed.
LikeLike
I’m using exchange 2007 and moving to 2010.
LikeLike
Does the script work against Office 365 mailboxes? I have ~200 mailboxes on Office 365 and I get below error when I run the script:
C:\Scripts\Remove-MessageClassItems.ps1 : A positional parameter cannot be found that accepts argument ‘Exception
calling “AutodiscoverUrl” with “2” argument(s): “The Autodiscover service couldn’t be located.”‘.
At line:1 char:1
+ .\Remove-MessageClassItems.ps1 -Mailbox rafatsum@genedemo.onmicrosoft.com -Messa …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : InvalidArgument: (:) [Remove-MessageClassItems.ps1], ParameterBindingException
+ FullyQualifiedErrorId : PositionalParameterNotFound,Remove-MessageClassItems.ps1
LikeLike
As already answered through e-mail, check your Autodiscover configuration, DNS entries, firewall settings etc.
You could bypass Autodiscover process directly specifying the EWS endpoint (using Server parameter), e.g. outlook.office365.com
Are you using Hybrid configuration?
LikeLike
Yes this is a Hybrid configuration. As a matter of fact, i have also tried a pure Office 365 tenant, from different location and got excat same error.
I have used the -server switch with Outlook.Office365.com and got “can’t access mailbox information store” error.
In both cases, i have given a user account that has tenant global admin, Exchange Org Managrnt and impersonation rights (I followed the instructions and assigned the right using the GUI)
??
Thanks for your help
Rafat
LikeLike
Thanks for the script. It ran successfully however as it ran, I received couple undelivered messages which I did not send and also don’t have on my sent items. I tested with another user got the same issue. Any idea, could it be read receipt of unread emails?
LikeLike
It’s the processing of read receipts or calendar invites. It’s on the list of enhancements.
LikeLike
the enhancements is still to come, or I must download again? Thanks for the quick response
LikeLike
Not in there yet – stay tuned
LikeLike
Can you provide me a resource as to make this script work. I have no knowledge of scripting with EWS. I have installed the API but all attempts to make it work have failed.
Thanks
Jamie
LikeLike
I think I have it now. Didn’t see the download for the script.
LikeLike
Script runs but doesn’t delete anything. I have tried exact message class name and partialmatching switch with general class name and neither will delete the items from my deleted items.
LikeLike
Account has (full access) permissions or impersonate permissions, and permissions on the folder containing duplicate items (per folder)?
LikeLike
Yes. Running on CAS with domain admin rights. Don’t understand your permissions on the folder containing duplicate items question.
LikeLike
Users can explicitly set folder permissions (right-click folder, Permissions). Domain admin rights may not suffice. More info on permissions at https://eightwone.com/2014/08/13/application-impersonation-to-be-or-pretend-to-be/
LikeLike
Folder permissions from Outlook are Default and Anon. – None. Shouldn’t I get an error if I don’t have rights? I will read more into the impersonation.
LikeLike
Hi Michael,
Thanks for the script. it is working fantastically for most of our mailboxes and folders within it. we are triggering the script from Exchange 2010 and we have exchange 2010 as well as exchange 2013 in our environment.
We have processed most of the mailboxes and folders within it but suddenly for one of the folder of anyone mailbox we faced following error as shown below. we tried accessing this folder and we could access it. the common thing is that we are facing issue only with mailboxes located in exchange 2013. we have verified personification permission and are good on that side for user credentials being used. also, it is working for all folders except few from exchange 2013. request you to kindly look into it.
PS>TerminatingError(): “Exception calling “FindItems” with “2” argument(s): “The request failed. The operation has timed out””
C:\do not delete\remove\Remove-MessageClassItems.ps1 : Can’t access mailbox
information store
LikeLike
Default timeout for EWS operations is 100 sec. Extend that period inserting the following line below “$EwsService.UseDefaultCredentials= $true”:
$EwsService.Timeout= X
where X is the timeout in milliseconds
A ‘timeout’ parameter is on the wishlist.
LikeLike
hi Michael,
Thanks for the suggestions. However, we are facing another issue with the same script. for some folders it prompts the previous error and for some the one that is displayed below.
I verified on permission side and also tried accessing those folders by logging to users profile by admin account, it is accessible in that way. Any kind of help or suggestions would be helpful. also, any link or blog with in depth information about EWS operations and flow and specifically in regards to this script would be of a great help to us.
C:\do not delete\remove\Remove-MessageClassItems.ps1 : Can’t access mailbox information store
At D:\Messaging_ShortcutReport\shrtct_rpt_ForTesting.ps1:9 char:26
+ Import-CSV .\users.csv | .\Remove-MessageClassItems.ps1 -MessageClass IPM.Note.E …
+ ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : NotSpecified: (:) [Write-Error], WriteErrorException
+ FullyQualifiedErrorId : Microsoft.PowerShell.Commands.WriteErrorException,Remove-MessageClassItems.ps1
Transcript stopped, output file is C:\Do not delete\remove\ShrtctCounts-09-04-2015.txt
Regards,
Rohit M. Dhole
LikeLike
just to add that it processed most of the folders very well in this mailbox. However, failed for a specific folder which is different than the todays folder.
Regards,
Rohit M. Dhole
LikeLike
Permissions are in order?
LikeLike
Yes, permissions are very much in order and so it is working fine with other users and folder on the same server. However, if you want me to verify some permissions please let me know so that I could verify and get back with result.
LikeLike
Hi Michael,
At the beginning of the script I saw another error message, don’t know if it has anything to do with the error. I have given that error below which is related to EWSManagedAPI.
WARNING: Active Directory server settings remained unchanged.
Load-EWSManagedAPIDLL : The term ‘Load-EWSManagedAPIDLL’ 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 C:\do not delete\remove\Remove-MessageClassItems.ps1:341 char:5
+ Load-EWSManagedAPIDLL
+ ~~~~~~~~~~~~~~~~~~~~~
+ CategoryInfo : ObjectNotFound: (Load-EWSManagedAPIDLL:String) [], CommandNotFoundException
+ FullyQualifiedErrorId : CommandNotFoundException
Regards,
Rohit M. Dhole
LikeLike
After making changes in EWS time out as suggested by you, here is the next error.
PS>TerminatingError(): “Exception calling “FindItems” with “2” argument(s): “An internal server error occurred. Try again later.””
C:\do not delete\remove\Remove-MessageClassItems.ps1 : Can’t access mailbox information store
Any help or any pointer would really be of great help !
Regards,
Rohit M. Dhole
LikeLike
Hi Michel,
Thanks a ton for your solution. I believe the first solution for Time Out value worked for me, I am able to complete the reports fluently. it gave above errors and I just increased the Time out value and it started working.
I am further looking for a script which could help me to remove older data which is older than specific date in a Mailbox.. it would be great if you could guide me to any script which could help me in this case.
Also, tough the reports are successful. I am getting this error at the beginning of all users information. do we have any workaround to overcome it ?
$EwsService.Timeout= X
where X is the timeout in milliseconds
A ‘timeout’ parameter is on the wishlist.
Regards,
Rohit M. Dhole
LikeLike
What error?
Older data .. why not apply a retention policy clearing out item older than X days, or is it a one-time task only?
LikeLike
Hi Michel,
Yes, it is the one time task and need to do on multiple users at a time. so just for one time activity we can’t go ahead and have retention tags and policies for multiple users.
Also, I pasted the error that I am getting in current script. Thanks for looking into it.
Regards,
Rohit M. Dhole
LikeLike
I believe I pasted wrong error,
Load-EWSManagedAPIDLL : The term ‘Load-EWSManagedAPIDLL’ 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.
Regards,
Rohit M. Dhole
LikeLike
Hello Michael,
I am wondering when the messages are being deleted from the mailbox, if there is a way to suppress responses to and silently delete delivery receipts/read receipts. I am finding when we remove these messages for any archives messages that had any of these requests tagged a lot of auto responses get generated like “not read: re..” etc
Thanks,
J-
LikeLike
Yes, check the other comments. It’s on the shortlist of enhancements.
LikeLike
Great, thank you for the prompt response.
LikeLike
Hi Michel, great script! I am trying to use it to delete stubs from Enterprise Vault old than xx/xx/xxxx and it seems to be working as far as scanning the mailbox, etc. However, no items get deleted as it finds none. I notice that it is not scanning a folder that our PST migration process creates in the mailbox called _Personal Archive. This folder is created directly under the user mailbox such as:
>Joe.Smith@contoso.com
>Inbox
>_Personal Archive
I also tried -ScanAllFolders with no luck.
Am I missing something as to why it wont scan this particular folder? I read through entire blog and comments and didn’t see anything jump out.
Thanks for any guidance you can provide!!!
LikeLike
Hi Michel,
we are doing the same migration but i can’t delete anything for now… i need to create a search folder in everyone’s outlook with all the message Class IPM.NOTE.EnterpriseVault.Shortcut in it so the user can clean their own vault.
can you help me please?
LikeLike
This should do the trick:
New Search Folder > Create custom Search Folder, Choose > Name: Something, Criteria > Advanced tab > Add Field Mail Item, Message Class is IPM.NOTE.EnterpriseVault.Shortcut > Add to List > OK > OK > OK
LikeLike
oh sorry … i know how to do it manually but i want to script it to be able to push it to everyone the the company…
regards
LikeLike
This should get you started
http://gsexdev.blogspot.nl/2011/09/create-search-folder-using-ews-managed.html
LikeLike
Hi:
I’m trying to execute this command against a specific database and get an error. The command is
Get-MailboxDatabase DB_xxx | Get-Mailbox | .\Remove-MessageClassItems.ps1 -Impersonation -Verbose -DeleteMode SoftDelete -MessageClass EnterpriseV
ault -PartialMatching -ScanAllFolders -Before ((Get-Date).AddDays(-730))
The error is:
The input object cannot be bound to any parameters for the command either because the command does not take pipeline input or the input and its properties do not match any of the parameters that take pipeline input.At line:1 char:79
Any ideas?
Thanks
Patxi
LikeLike
The name of the mailbox parameter is mailbox, and you’re not passing that one via Get-Mailbox. Instead, try:
Get-MailboxDatabase DB_xxx | Get-Mailbox | ForEach { .\Remove-MessageClassItems.ps1 -Mailbox $_.Identity -Impersonation -Verbose -DeleteMode SoftDelete -MessageClass EnterpriseV
ault -PartialMatching -ScanAllFolders -Before ((Get-Date).AddDays(-730)) }
LikeLike
Hi Michel:
Thanks for your quick response. !!!!That worked¡¡¡¡
I only had to change $_.Identity for $_.Alias to make it work, as the Identity value has spaces, and Alias does not.
Thank you very much for your help. It saved me a lot of time
Best regards
Patxi
LikeLike
Hi Michel:
Another tricky question, at least for me…
Running your script to all mailboxes of a specific database, asks for deletion confirmation for every mailbox it encounters. Is there any way to automate this response (for example A to delete all ítems, etc.) to avoid typing this for every mailbox?
Thanks for your great Support.
Patxi
LikeLike
You can use -Confirm:$false
LikeLike
Perfect.
Thanks again Michel.
Have a nice day
Patxi
LikeLike
Hi Michel,
Awesome script. It’s weird that MS decided not to allow this in the “advanced” search applets of Exchange 2013.
I do have a feature request:
It is possible to move the items to the deleted items folder, but what I want to do is to export the items to a PST file and remove them. If it was possible to move the items to a random new empty folder, that would be great. If this folder could be located in a different mailbox, that would be even better. Is this something that would be hard to add on?
Thank you in advance!
Milan
LikeLike
Exporting to PST yes, as I’m interacting with the mailbox through EWS and have no ‘PST library’ at my disposal. I could create a ‘Duplicates’ folder and dump everything in there; noted on the wish list.
LikeLike
Ofcourse, I thought exporting to a PST would be difficult at the least. But moving items to a new seach folder should be straight forward …
Thank you for putting it on the wish list.
LikeLike
Could you give an indication on how much trouble this would be and when you could possibly come around to it, if ever? I apologise for sounding a bit snobby, i don’t mean to be, but we’re kind of in a jam with this being the only option and no EWS expertise or experience…
Bedankt voor het antwoord alvast!
LikeLike
As a work-around, could you not clear out the deleted items folder temporarily, and allow for a “Move to Deleted Items” execution? This would isolate your results into the Deleted Items Folder.
LikeLike
This is not an option, users often have good reasons for keeping messages in their Deleted Items Folder (I only have one, but hey …). Also using the Deleted items folder for live data, or actually anything else but junk, makes my techy-sences tingle inappropriately.
LikeLike
Yeah, my point was to use this as a potential temporary one-off process for one (or a small number of users) who may have a large number of items of a particular message class which were looking to export to PST.
That workflow would involve (per user) temporarily moving all items out of Deleted Items (into a subfolder), and using the script to “delete” the particular message class items into the Deleted items. Since the Deleted items would then contain nothing but the items with that particular message class, you could then export it to PST.
Once complete, you’d then place the original deleted items back into the Deleted Items folder, and leave the user alone.
I’m assuming you’d like to script this out for many users, in which case my idea wouldn’t work at all…
LikeLike
Yeah, it’s A LOT of mailboxes in this case. And doing it by hand, it would probably be easier running a search on messageclass in outlook and then dragging the results to a temp mailbox, folder or PST. Thaks though… workrounds are welcome too.
LikeLike
Oh, and yeah…Users that “file” stuff in Deleted Items, make me nervous…
LikeLike
Never mind. I figured it out.
A script from MSDN was easily adapted to do exactly what I needed it to do:
http://blogs.msdn.com/b/emeamsgdev/archive/2012/04/27/powershell-script-to-move-items-from-one-folder-to-another-in-a-user-s-mailbox.aspx?CommentPosted=true#commentmessage
All it needed was a check on ItemClaas before moving and a search iteration per folder to improve efficiency. It recreates teh folder structure at the target and it automatically skips the target folder when it a subfolder of the source folder, so you can just create target folder and move everything from “\” (=root) to it and it will all be just fine.
Available here:
https://sites.google.com/site/bikerbuva/software
LikeLike
Glad you figured it out
LikeLike
I’m no Powershell expert, but I can’t seem to be able output this to a log-file using redirection or piping to an “out-file.”
Am I missing something easy?
LikeLike
For the record, the following works to pipe the Get-Mailbox command to the script:
Get-Mailbox -database databasename | select samaccountname | Select-Object @{ expression={$_.samaccountname};label=’Mailbox’ } | .’C:scriptsRemove-MessageClassItems.ps1′ -MessageClass IPM.Note.EnterpriseVault.Shortcut -Confirm:$false -DeleteMode SoftDelete -Verbose -Impersonation -ScanAllFolders -Before ((Get-Date).AddDays(-30))
LikeLike
Only the parameter Mailbox accepts pipeline input, the the name of the attribute passed through the pipeline needs to match. The script doesn’t output objects, it outputs to the console (incl. warnings and errors), and additionaly the verbose or debug channel (if related common parameter is specified). You can redirect that console output the traditional way, see https://technet.microsoft.com/en-us/library/hh847746%28v=wps.620%29.aspx
LikeLike
Yeah, I’d figured that out, thanks…I’m using Select-Object @{ expression={$_.samaccountname};label=’Mailbox’ } for that…
LikeLike
I am getting this error while deleting the EV shortcuts from Office 365 mailbox:
Remove-MessageClassItems.ps1 : Can’t access mailbox information store
At line:1 char:1
I am running this command:
.\Remove-MessageClassItems.ps1 -Mailbox user@domain.com -Verbose -DeleteMode MoveToDeletedItems -MessageClass IPM.Note.EnterpriseVault.Shortcut -MailboxOnly -WhatIf -Server outlook.office365.com
The account used to run this command has got the Full Access and Impersonation rights on the mailbox. Any help with this will be appreciated a lot.
Thanks in advance.
LikeLike
What’s that ‘mailto…’ doing in there? Also, please relog before trying again.
LikeLike
I do not have mailto in the command which I am running, it’s just when you hover your mouse you get to see that, which is expected, I think. The same command worked on one of my colleague’s machine. I have installed the same version of EWS Managed API, still no go. Will try few more things and keep you updated.
LikeLike
Ah, I replied to the notification mail which showed the mailto HTML tag as plain text. Odd. Anyway, cmd looks ok – can’t access information store is usually something with access (permissions). You did specify Credentials, providing credentials with sufficient access?
LikeLike