Skip to content

Instantly share code, notes, and snippets.

@crshnbrn66
Created February 9, 2017 15:06
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save crshnbrn66/35e5d630c2c429bcf9f765433e29be85 to your computer and use it in GitHub Desktop.
Save crshnbrn66/35e5d630c2c429bcf9f765433e29be85 to your computer and use it in GitHub Desktop.
<#
.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
@BanannaJoe
Copy link

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