Archive public folder emails older than 2 years

As we all know, retention policies aren't supported for public folder mailboxes. In case you want to archive/move your old public folder emails to a public folder, specially created for archiving, this script might turn to be useful. First, it prompts you to create the public folder (archive) and then, it is recursively returning the public folder structure and looks in each folder for any items older than two years.



-The script requires EWS Managed API 2.2, which can be downloaded here:

-The "Default" user for each public folder (Get-PublicFolderClientPermission \PF -User Default) needs to have at least 'Author' permissions (which are actually the default), or of course, you can assign specific permissions to the mailbox that you are using to access the public folder structure.

-The mailbox that you are using to access the public folder structure needs to have owner permissions on the public folder root ("\) to be able to create the public folder archive.



 DISCLAIMER: This application is a sample application. The sample is provided "as is" without warranty of any kind. Microsoft further disclaims all implied warranties including without limitation any implied warranties of merchantability or of fitness for a particular purpose. The entire risk arising out of the use or performance of the samples remains with you. in no event shall Microsoft or its suppliers be liable for any damages whatsoever (including, without limitation, damages for loss of business profits, business interruption, loss of business information, or other pecuniary loss arising out of the use of or inability to use the samples, even if Microsoft has been advised of the possibility of such damages). Because some states do not allow the exclusion or limitation of liability for consequential or incidental damages, the above limitation may not apply to you.

Import-Module -Name "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll"

$service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService -ArgumentList Exchange2013_SP1

#Provide the credentials
$credential = Get-Credential -Message "Type the credentials of the mailbox with access to the public folders that you want to process for archiving"
$service.Credentials = new-object Microsoft.Exchange.WebServices.Data.WebCredentials -ArgumentList $credential.UserName, $credential.GetNetworkCredential().Password

#Exchange Online URL
$service.Url= new-object Uri("")

$RootFolderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::PublicFoldersRoot, $credential.UserName)

#Create the archive/public folder (you need owner permissions on the Root folder "\")
$TargetFolderName = Read-Host "Type the name of the public folder archive"

$TargetFolder = new-object Microsoft.Exchange.WebServices.Data.Folder($service)

$TargetFolder.DisplayName = $TargetFolderName


#Get the Public folder structure
 GetPublicFolder -FolderId $RootFolderId

function GetPublicFolder ()


param (
 $FolderId = "$( throw 'FolderId is a mandatory Parameter' )"

$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(100)

$FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Shallow

$pspropset = New-Object Microsoft.Exchange.WebServices.Data.PropertySet ([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly,




$PR_Folder_Path = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition (26293,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::String)

$SearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo ([Microsoft.Exchange.WebServices.Data.FolderSchema]::FolderClass, "IPF.Note")


$FolderView.PropertySet = $pspropset

$FindFolderResults = $service.FindFolders($FolderId,$SearchFilter,$FolderView)



foreach ($Folder in $FindFolderResults.Folders) 
Write-Host "Checking if there are messages older than 2 years in the public folder $($Folder.ExtendedProperties.Value)" -ForegroundColor White

PublicFolderEmails -FolderId $Folder.Id

if($Folder.ChildFolderCount){ GetPublicFolder -FolderId $Folder.Id }



function PublicFolderEmails

param (
 $FolderId = "$( throw 'FolderId is a mandatory Parameter' )"

$ItemView = New-Object Microsoft.Exchange.WebServices.Data.ItemView(1000)

$pspropset = New-Object Microsoft.Exchange.WebServices.Data.PropertySet ([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly,

$ItemView.PropertySet = $pspropset

$FindItemResults = $service.FindItems($FolderId,$ItemView)

if ($FindItemResults.TotalCount)  {

foreach($Item in $FindItemResults.Items)


if([datetime]$Item.DateTimeReceived -le (get-date).adddays(-730) -or [datetime]$Item.DateTimeSent -le (get-date).adddays(-730))

#Move the items older than 2 years in the target/archive public folder

$Message = [Microsoft.Exchange.WebServices.Data.EmailMessage]::Bind($service,$Item.Id)







Note: In case you want to create a folder within the primary mailbox structure (of the account used to access the public folders) and move the public folder emails older than two years there, you can do that as well. However, the script has to be slightly changed.