This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<# | |
.Synopsis | |
Sets folders specified retention flag to custom flag in Exchange online | |
.DESCRIPTION | |
This script is based from the following sources. | |
https://blogs.msdn.microsoft.com/akashb/2011/08/10/stamping-retention-policy-tag-using-ews-managed-api-1-1-from-powershellexchange-2010/ | |
http://blogs.perficient.com/microsoft/2016/03/office-365-script-to-recreate-managed-folders-functionality/ | |
This script search for and sets all folders found for the retention flag specified. See this blog post for more information: | |
.PARAMETER TargetMailboxes | |
A file that contains mailboxes that you want to populate. Single user per line. | |
IE user@domain.com | |
user2@domain.com | |
.PARAMETER logfile | |
Name of a logfile to create with results | |
.PARAMETER FolderName | |
Name of the folder to search for and update. | |
.PARAMETER RetentionTag | |
Name of the Retention tag to assign to the folder. | |
.PARAMETER AutoD | |
If specified as $True, Autodiscover is used to determine the EWS endpoint. Default | |
value is $True. | |
.PARAMETER EwsUri | |
EWS endpoint for target mailbox. Default value is to use Office 365 if not using Autodiscover. | |
.PARAMETER ApiPath | |
Location of EWS API. Default path is "C:\Program Files\Microsoft\Exchange\ | |
Web Services\2.2\Microsoft.Exchange.WebServices.dll". | |
.PARAMETER Version | |
Exchange version to be used by EWS. Default is "Exchange2013_SP1" and likely | |
does not need to be changed. | |
.PARAMETER ConnectionUri | |
Connection to Exchange online | |
.EXAMPLE | |
.\Set-ManagedFolders.ps1 -TargetMailboxes c:\temp\mailboxes.txt -logfile c:\temp\mylog.log -FolderName "ok" -RetentionTag "TestRetention" | |
#> | |
Param( | |
[Parameter(Mandatory=$True)] | |
[string]$TargetMailboxes, | |
[Parameter(Mandatory=$True)] | |
[string]$logfile, | |
[string]$FolderName='ok', | |
[string]$RetentionTag='TestRetention', | |
[Parameter(Mandatory=$False)] | |
[string]$AutoD = $False, | |
[Parameter(Mandatory=$False)] | |
[string]$EwsUri = "https://mail.office365.com/ews/exchange.asmx", | |
[Parameter(Mandatory=$False)] | |
[string]$ApiPath = "C:\Program Files\Microsoft\Exchange\Web Services\2.2\Microsoft.Exchange.WebServices.dll", | |
[Parameter(Mandatory=$False)] | |
[string]$Version = "Exchange2013_SP1", | |
[string]$connectionUri = 'https://outlook.office365.com/powershell-liveid/' | |
) | |
function Get-MailBoxfolders | |
{ | |
[CmdletBinding()] | |
param | |
( | |
[Parameter(Mandatory=$true, Position=0, HelpMessage='A service that points to exchange instance you wish to query')] | |
[Microsoft.Exchange.WebServices.Data.ExchangeService]$Service, | |
[Parameter(Mandatory=$true, Position=1, HelpMessage='A mailbox (smtp) that the service has access to')] | |
[string]$targetMailbox, | |
[string]$Folder2Find | |
) | |
#$ImpersonatedUserId = New-Object -TypeName Microsoft.Exchange.WebServices.Data.ImpersonatedUserId -ArgumentList ([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $TargetMailbox) | |
Write-Verbose -Message "create an object that gets the root folder for the mailbox" | |
$fvFolderView = new-object Microsoft.Exchange.WebServices.Data.FolderView(1000) | |
$fvFolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep | |
$folderid = new-object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$targetMailbox) | |
$tfTargetFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($service,$folderid) | |
$findFolderResults = $tfTargetFolder.FindFolders($fvFolderView) | |
foreach($folder in $findFolderResults.Folders){ | |
if($folder.FolderClass -eq 'IPF.Note') | |
{ | |
$parentfolder = ($findFolderResults.Folders |?{$_.id.uniqueid -eq $folder.ParentFolderId.UniqueId}).displayname | |
if(-not $parentfolder) | |
{$parentfolder = 'Root'} | |
if($Folder2Find) | |
{ | |
if($folder.DisplayName -eq $folder2find) | |
{ | |
[pscustomobject] @{ | |
'name'= $folder.DisplayName | |
'folderid' = $folder.Id.UniqueId | |
'ParentFolderName' = $parentfolder | |
'ParentFolderId' = $folder.ParentFolderId.UniqueId | |
'folderclass' = $folder.FolderClass | |
} | |
} | |
} | |
else | |
{ | |
[pscustomobject] @{ | |
'name'= $folder.DisplayName | |
'folderid' = $folder.Id.UniqueId | |
'ParentFolderName' = $parentfolder | |
'ParentFolderId' = $folder.ParentFolderId.UniqueId | |
'folderclass' = $folder.FolderClass | |
} | |
} | |
} | |
} | |
} | |
'___________________________________'|out-file -FilePath $logfile -Append | |
get-date | out-file -FilePath $logfile -Append | |
'___________________________________'|out-file -FilePath $logfile -Append | |
$ImpersonationCreds = Get-Credential -Message "Enter Credentials for Account with Impersonation Role..." | |
$Session = New-PSSession -ConfigurationName Microsoft.Exchange -ConnectionUri $connectionUri -Authentication Basic -Credential $ImpersonationCreds | |
Import-PSSession $Session | |
If((test-path -pathtype Leaf $TargetMailboxes) -and (Get-Command get-mailbox -ErrorAction Ignore)) #test target mailbox if | |
{ | |
$mailboxes = get-content $TargetMailboxes | |
$returnStatus =@() | |
Add-Type -Path $ApiPath | |
$ExchangeVersion = [Microsoft.Exchange.WebServices.Data.ExchangeVersion]::$Version | |
$Service = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService($ExchangeVersion) | |
$Creds = New-Object System.Net.NetworkCredential($ImpersonationCreds.UserName, $ImpersonationCreds.Password) | |
$RetentionPeriod = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301A,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); | |
$RetentionFlags = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x301D,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Integer); | |
$PolicyTag = New-Object Microsoft.Exchange.WebServices.Data.ExtendedPropertyDefinition(0x3019,[Microsoft.Exchange.WebServices.Data.MapiPropertyType]::Binary); | |
foreach($TargetMailbox in $mailboxes) | |
{ | |
write-output "----------Mailbox $Targetmailbox --------------------" | |
$Guid = 'No Guid' | |
$status = $null | |
if(get-mailbox -identity $TargetMailbox -ErrorAction Ignore) | |
{ | |
$Service.Credentials = $Creds | |
if ($AutoD -eq $True) { | |
$Service.AutodiscoverUrl($TargetMailbox,{$True}) | |
"EWS URI = " + $Service.url | |
} | |
else { | |
$Uri=[system.URI] $EwsUri | |
$Service.Url = $uri | |
} | |
$Service.ImpersonatedUserId = New-Object Microsoft.Exchange.WebServices.Data.ImpersonatedUserId([Microsoft.Exchange.WebServices.Data.ConnectingIdType]::SmtpAddress, $TargetMailbox) | |
$FolderId= New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$TargetMailbox) | |
$EWSParentFolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service,$FolderId) | |
$FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(1) | |
$SearchFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$FolderName) | |
$FindFolderResults = Get-MailBoxfolders -service $service -targetmailbox $targetmailbox -folder2find $FolderName | |
if($FindFolderResults) #foldercount if | |
{ | |
$folderresults= @() | |
foreach ($folderfound in $FindFolderResults) #foreach | |
{ | |
$Tag = ($Service.GetUserRetentionPolicyTags().RetentionPolicyTags | where {$_.DisplayName -eq $RetentionTag}) | |
[Microsoft.Exchange.WebServices.Data.FolderId]$folderid = $folderfound.Folderid | |
$ofolder = [Microsoft.Exchange.WebServices.Data.Folder]::Bind($Service, $FolderId) | |
write-verbose "setting the retention flag" | |
$ofolder.SetExtendedProperty($RetentionFlags,129) | |
write-verbose "Set the value of the retention equal to the value from our tag retention period" | |
$ofolder.SetExtendedProperty($RetentionPeriod, $tag.RetentionPeriod) | |
write-output "set the exended property policy tag name $($tag.DisplayName) using it's guid $($tag.RetentionId)" | |
$oFolder.SetExtendedProperty($policytag, ($Tag.RetentionId).ToByteArray()) | |
try | |
{ | |
$ofolder.Update() | |
$status = 'updated' | |
$Guid = $tag.RetentionId | |
} | |
Catch [System.Exception] | |
{ | |
$status = "$('Error Output was' + ($Error[0] | Select-Object *))" | |
write-verbose ('Error Output was' + ($Error[0] | Select-Object *)) | |
} | |
$folderresults += [pscustomobject] @{ | |
'foldername'= $folderfound.name | |
'folderGUID' = $folderfound.folderid | |
'ParentFolder' = $folderfound.parentfolderName | |
'status' = $status} | |
} #end foreach | |
} #end folder count if | |
else #else folder count | |
{ | |
$status = 'No Folder' | |
} #end else folder count | |
$return = [PSCustomObject]@{ | |
'mailboxName' = $TargetMailbox | |
'Guid' = $Guid | |
'folders' = "$($folderresults.foldername -join ',')" | |
'folderGUID' = "$($folderresults.folderguid -join ',')" | |
'ParentFolder'= "$($folderresults.parentfolder -join ',')" | |
'Status' = "$($folderresults.status -join ',')" | |
} | |
$returnStatus += $return | |
Write-Output '___________________________________' | |
}#foreach | |
} #end get identiy mailbox | |
if($returnStatus) | |
{ | |
$returnStatus | out-file -FilePath $logfile -Append | |
} | |
} | |
else{ | |
write-error "Cannot Find File $targetmailboxes or cannot the Get-mailbox command is unavailable" #test target mailbox if | |
} | |
get-pssession | Remove-PSSession | |
I am running the script against an Exchange 2016 server. I had to change the line 169
$ofolder.SetExtendedProperty($RetentionFlags,129)
to
$ofolder.SetExtendedProperty($RetentionFlags,137)
so that the policy was set cleanly
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Can you explain why $Guid = 'No Guid'? I tried this script and nothing happens.