diff --git a/.github/actions/purge-m365-user-data/action.yml b/.github/actions/purge-m365-user-data/action.yml
index f064bb363..b4a4b26d5 100644
--- a/.github/actions/purge-m365-user-data/action.yml
+++ b/.github/actions/purge-m365-user-data/action.yml
@@ -9,10 +9,9 @@ name: Purge M365 User Data
#
# The script focuses on the cleaning up the following:
# * All folders, descending from the exchange root, of a given prefix.
-# * All folders in PersonMetadata
+# * All folders in PersonMetadata
# * All already soft-deleted items
-# * All recoverable items in Audits
-# * All recoverable items in Purges
+# * All folders under recoverable items
inputs:
user:
@@ -35,20 +34,19 @@ inputs:
runs:
using: composite
steps:
-
- - name: Run the folder-matrix purge script set
- if: ${{ inputs.folder-prefix != '' }}
+ - name: Run the all purge scripts for user
+ if: ${{ inputs.user != '' }}
shell: pwsh
working-directory: ./src/cmd/purge/scripts
- env:
+ env:
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
AZURE_CLIENT_SECRET: ${{ inputs.azure-client-secret }}
AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
run: |
- ./foldersAndItems.ps1 -WellKnownRoot root -User ${{ inputs.user }} -FolderPrefixPurge ${{ inputs.folder-prefix }} -FolderBeforePurge ${{ inputs.older-than }}
+ ./foldersAndItems.ps1 -User ${{ inputs.user }} -FolderNamePurgeList PersonMetadata --FolderPrefixPurgeList ${{ inputs.folder-prefix }} -PurgeBeforeTimestamp ${{ inputs.older-than }}
- name: Reset retention for all mailboxes to 0
- if: ${{ inputs.folder-prefix == '' && inputs.user == '' }}
+ if: ${{ inputs.user == '' }}
shell: pwsh
working-directory: ./src/cmd/purge/scripts
env:
@@ -57,25 +55,9 @@ runs:
run: |
./setRetention.ps1
- - name: Run the static purge script set
- if: ${{ inputs.folder-prefix == '' && inputs.user != '' }}
- shell: pwsh
- working-directory: ./src/cmd/purge/scripts
- env:
- AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
- AZURE_CLIENT_SECRET: ${{ inputs.azure-client-secret }}
- AZURE_TENANT_ID: ${{ inputs.azure-tenant-id }}
- # powershell doesn't like multiline commands, each of these must be on a single line
- run: |
- ./foldersAndItems.ps1 -WellKnownRoot root -User ${{ inputs.user }} -FolderNamePurge PersonMetadata
- ./foldersAndItems.ps1 -WellKnownRoot deleteditems -User ${{ inputs.user }}
- ./foldersAndItems.ps1 -WellKnownRoot recoverableitemsroot -User ${{ inputs.user }} -FolderNamePurge Audits
- ./foldersAndItems.ps1 -WellKnownRoot recoverableitemsroot -User ${{ inputs.user }} -FolderNamePurge Purges
- ./foldersAndItems.ps1 -WellKnownRoot recoverableitemsroot -User ${{ inputs.user }} -FolderNamePurge Deletions
-
- name: Run the old purge script to clear out onedrive buildup
working-directory: ./src
- if: ${{ inputs.folder-prefix != '' }}
+ if: ${{ inputs.folder-prefix != '' && inputs.user != ''}}
shell: sh
env:
AZURE_CLIENT_ID: ${{ inputs.azure-client-id }}
diff --git a/.github/workflows/ci_test_cleanup.yml b/.github/workflows/ci_test_cleanup.yml
index 795f138af..ddc7313fb 100644
--- a/.github/workflows/ci_test_cleanup.yml
+++ b/.github/workflows/ci_test_cleanup.yml
@@ -10,14 +10,9 @@ jobs:
runs-on: ubuntu-latest
continue-on-error: true
strategy:
- # jobs are expanded per user. Try to run 2 jobs per active user at a time
- max-parallel: 6
matrix:
- folder: [Corso_Restore_, TestRestore, testfolder, incrementals_ci_, Alcion_Restore_, '']
- user: [CORSO_M365_TEST_USER_ID, CORSO_SECONDARY_M365_TEST_USER_ID, EXT_SDK_TEST_USER_ID]
- include:
- - folder: ""
- user: ""
+ folder: 'Corso_Restore_, TestRestore, testfolder, incrementals_ci_, Alcion_Restore_'
+ user: [ CORSO_M365_TEST_USER_ID, CORSO_SECONDARY_M365_TEST_USER_ID, EXT_SDK_TEST_USER_ID, '' ]
steps:
- uses: actions/checkout@v3
diff --git a/src/cmd/purge/scripts/foldersAndItems.ps1 b/src/cmd/purge/scripts/foldersAndItems.ps1
index 9d8926076..0233b4c88 100644
--- a/src/cmd/purge/scripts/foldersAndItems.ps1
+++ b/src/cmd/purge/scripts/foldersAndItems.ps1
@@ -4,17 +4,14 @@ Param (
[Parameter(Mandatory = $True, HelpMessage = "User for which to delete folders")]
[String]$User,
- [Parameter(Mandatory = $False, HelpMessage = "Well-known name of folder under which to clean")]
- [String]$WellKnownRoot = "deleteditems",
+ [Parameter(Mandatory = $True, HelpMessage = "Purge folders or contacts before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp,
- [Parameter(Mandatory = $False, HelpMessage = "Purge folders before this date time (UTC)")]
- [datetime]$FolderBeforePurge,
+ [Parameter(Mandatory = $True, HelpMessage = "Name of specific folder to purge under root")]
+ [String[]]$FolderNamePurgeList,
- [Parameter(Mandatory = $False, HelpMessage = "Name of specific folder to purge under root")]
- [String]$FolderNamePurge,
-
- [Parameter(Mandatory = $False, HelpMessage = "Purge folders with this prefix")]
- [String]$FolderPrefixPurge,
+ [Parameter(Mandatory = $True, HelpMessage = "Purge folders with this prefix")]
+ [String[]]$FolderPrefixPurgeList,
[Parameter(Mandatory = $False, HelpMessage = "Azure TenantId")]
[String]$TenantId = $ENV:AZURE_TENANT_ID,
@@ -26,6 +23,10 @@ Param (
[String]$ClientSecret = $ENV:AZURE_CLIENT_SECRET
)
+Set-StrictMode -Version 2.0
+# Attempt to set network timeout to 10min
+[System.Net.ServicePointManager]::MaxServicePointIdleTime = 600000
+
function Get-AccessToken {
[CmdletBinding()]
Param()
@@ -34,11 +35,11 @@ function Get-AccessToken {
Write-Host "`nNeed to specify TenantId, ClientId, and ClientSecret as parameters or ENVs"
}
- $body=@{
- client_id=$ClientId
- client_secret=$ClientSecret
- scope="https://outlook.office365.com/.default"
- grant_type="client_credentials"
+ $body = @{
+ client_id = $ClientId
+ client_secret = $ClientSecret
+ scope = "https://outlook.office365.com/.default"
+ grant_type = "client_credentials"
}
$res = Invoke-WebRequest -Uri "https://login.microsoftonline.com/$TenantId/oauth2/v2.0/token" -ContentType "application/x-www-form-urlencoded" -Body $body -Method Post
@@ -102,20 +103,62 @@ function Invoke-SOAPRequest {
return $xmlResponse
}
-function Remove-Folder {
- [CmdletBinding(SupportsShouldProcess)]
+function IsNameMatch {
Param(
- [Parameter(Mandatory = $True, HelpMessage = "OAuth token to connect to Exchange Online.")]
- [Securestring]$Token,
+ [Parameter(Mandatory = $True, HelpMessage = "Folder name to evaluate for match against a list of targets")]
+ [string]$FolderName,
- [Parameter(Mandatory = $True, HelpMessage = "User for which to delete folders")]
- [String]$User,
+ [Parameter(Mandatory = $True, HelpMessage = "Folder names to evaluate for match")]
+ [string[]]$FolderNamePurgeList = @()
+ )
- [Parameter(Mandatory = $False, HelpMessage = "Well-known name of folder under which to clean")]
- [String]$WellKnownRoot = "deleteditems"
- )
+ return ($FolderName -in $FolderNamePurgeList)
+}
- # SOAP message for getting the folder id
+function IsPrefixAndAgeMatch {
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "Folder name to evaluate for match against a list of targets")]
+ [string]$FolderName,
+
+ [Parameter(Mandatory = $True, HelpMessage = "Folder creation times")]
+ [string]$FolderCreateTime,
+
+ [Parameter(Mandatory = $True, HelpMessage = "Folder name prefixes to evaluate for match")]
+ [string[]]$FolderPrefixPurgeList,
+
+ [Parameter(Mandatory = $TRUE, HelpMessage = "Purge folders before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp
+ )
+
+ if ($PurgeBeforeTimestamp -gt $folderCreateTime ) {
+ foreach ($prefix in $FolderPrefixPurgeList) {
+ if ($FolderName -like "$prefix*") {
+ return $true
+ }
+ }
+ }
+
+ return $false
+}
+
+function Get-FoldersToPurge {
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
+ [String]$WellKnownRoot,
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp,
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders with these names")]
+ [string[]]$FolderNamePurgeList = @(),
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders with these prefixes")]
+ [string[]]$FolderPrefixPurgeList = @()
+ )
+
+ $foldersToDelete = @()
+
+ # SOAP message for getting the folders
$body = @"
@@ -130,78 +173,360 @@ function Remove-Folder {
"@
- Write-Host "`nLooking for folders under well-known folder: $WellKnownRoot & matching folder: $FolderNamePurge$FolderNamePrefixPurge & for user: $User"
+ Write-Host "`nLooking for folders under well-known folder: $WellKnownRoot matching folders: $FolderNamePurgeList or prefixes: $FolderPrefixPurgeList for user: $User"
$getFolderIdMsg = Initialize-SOAPMessage -User $User -Body $body
$response = Invoke-SOAPRequest -Token $Token -Message $getFolderIdMsg
# Get the folders from the response
- $folders = $response | Select-Xml -XPath "//t:Folders/*" -Namespace @{t = "http://schemas.microsoft.com/exchange/services/2006/types"} |
- Select-Object -ExpandProperty Node
+ $folders = $response | Select-Xml -XPath "//t:Folders/*" -Namespace @{t = "http://schemas.microsoft.com/exchange/services/2006/types" } |
+ Select-Object -ExpandProperty Node
- $folderId = $null
- $changeKey = $null
- $totalCount = $null
+ # Are there more folders to list
+ $rootFolder = $response | Select-Xml -XPath "//m:RootFolder" -Namespace @{m = "http://schemas.microsoft.com/exchange/services/2006/messages" } |
+ Select-Object -ExpandProperty Node
+ $moreToList = ![System.Convert]::ToBoolean($rootFolder.IncludesLastItemInRange)
# Loop through folders
foreach ($folder in $folders) {
- $folderId = $folder.FolderId.Id
- $changeKey = $folder.FolderId.Changekey
- $totalCount = $folder.TotalCount
$folderName = $folder.DisplayName
$folderCreateTime = $folder.ExtendedProperty
- | Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
- | Select-Object -ExpandProperty Value
- | Get-Date
+ | Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
+ | Select-Object -ExpandProperty Value
+ | Get-Date
- if ((![String]::IsNullOrEmpty($FolderNamePurge) -and $folderName -ne $FolderNamePurge) -or
- (![String]::IsNullOrEmpty($FolderPrefixPurge) -and $folderName -notlike "$FolderPrefixPurge*") -or
- (![String]::IsNullOrEmpty($FolderBeforePurge) -and $folderCreateTime -gt $FolderBeforePurge)) {
+ $IsNameMatchParams = @{
+ 'FolderName' = $folderName;
+ 'FolderNamePurgeList' = $FolderNamePurgeList
+ }
+
+ $IsPrefixAndAgeMatchParams = @{
+ 'FolderName' = $folderName;
+ 'FolderCreateTime' = $folderCreateTime;
+ 'FolderPrefixPurgeList' = $FolderPrefixPurgeList;
+ 'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp;
+ }
+
+ if ((IsNameMatch @IsNameMatchParams) -or (IsPrefixAndAgeMatch @IsPrefixAndAgeMatchParams)) {
+ Write-Host "`nFound desired folder to purge: $folderName ($folderCreateTime)"
+ $foldersToDelete += $folder
+ }
+ }
+
+ # powershel does not do well when returning empty arrays
+ return $foldersToDelete, $moreToList
+}
+
+function Empty-Folder {
+ [CmdletBinding(SupportsShouldProcess)]
+ Param(
+ [Parameter(Mandatory = $False, HelpMessage = "List of well-known folders to empty ")]
+ [String[]]$WellKnownRootList = @(),
+
+ [Parameter(Mandatory = $False, HelpMessage = "List of folderIds to empty ")]
+ [string[]]$FolderIdList = @(),
+
+ [Parameter(Mandatory = $False, HelpMessage = "List of folder names to empty ")]
+ [string[]]$FolderNameList = @()
+ )
+
+ $folderIdsBody = ""
+ $foldersToEmptyCount = $FolderIdList.count + $WellKnownRootList.count
+
+ foreach ($wnr in $WellKnownRootList) {
+ $folderIdsBody += ""
+ }
+
+ foreach ($fid in $FolderIdList) {
+ $folderIdsBody += ""
+ }
+
+ if ($PSCmdlet.ShouldProcess("Emptying $foldersToEmptyCount folders ($WellKnownRootList $FolderNameList)", "$foldersToEmptyCount folders ($WellKnownRootList $FolderNameList)", "Empty folders")) {
+ Write-Host "`nEmptying $foldersToEmptyCount folders ($WellKnownRootList $FolderNameList)"
+
+ # DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
+ $body = @"
+
+
+ $folderIdsBody
+
+
+"@
+
+ $emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
+ $response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
+ }
+}
+
+function Delete-Folder {
+ [CmdletBinding(SupportsShouldProcess)]
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "List of folderIds to remove ")]
+ [String[]]$FolderIdList,
+
+ [Parameter(Mandatory = $False, HelpMessage = "List of folder names to remove ")]
+ [String[]]$FolderNameList = @()
+ )
+
+ $folderIdsBody = ""
+ $foldersToRemoveCount = $FolderIdList.count
+
+ foreach ($fid in $FolderIdList) {
+ $folderIdsBody += ""
+ }
+
+ if ($PSCmdlet.ShouldProcess("Removing $foldersToRemoveCount folders ($FolderNameList)", "$foldersToRemoveCount folders ($FolderNameList)", "Delete folders")) {
+ Write-Host "`nRemoving $foldersToRemoveCount folders ($FolderNameList)"
+
+ # DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
+ $body = @"
+
+
+ $folderIdsBody
+
+
+"@
+
+ $emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
+ $response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
+ }
+}
+
+function Purge-Folders {
+ [CmdletBinding(SupportsShouldProcess)]
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
+ [String]$WellKnownRoot,
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders with these names")]
+ [string[]]$FolderNamePurgeList = @(),
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders with these prefixes")]
+ [string[]]$FolderPrefixPurgeList = @(),
+
+ [Parameter(Mandatory = $False, HelpMessage = "Purge folders before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp
+ )
+
+ if (($FolderNamePurgeList.count -eq 0) -and
+ ($FolderPrefixPurgeList.count -eq 0 -or $PurgeBeforeTimestamp -eq $null )) {
+ Write-Host "Either a list of specific folders or a list of prefixes and purge timestamp is required"
+ Exit
+ }
+
+ Write-Host "`nPurging CI-produced folders..."
+ Write-Host "--------------------------------"
+
+ if ($FolderNamePurgeList.count -gt 0) {
+ Write-Host "Folders with names: $FolderNamePurgeList"
+ }
+
+ if ($FolderPrefixPurgeList.count -gt 0 -and $PurgeBeforeTimestamp -ne $null) {
+ Write-Host "Folders older than $PurgeBeforeTimestamp with prefix: $FolderPrefixPurgeList"
+ }
+
+ $foldersToDeleteParams = @{
+ 'WellKnownRoot' = $WellKnownRoot;
+ 'FolderNamePurgeList' = $FolderNamePurgeList;
+ 'FolderPrefixPurgeList' = $FolderPrefixPurgeList;
+ 'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp
+ }
+
+ $moreToList = $True
+ # only get max of 1000 results so we may need to iterate over eligible folders
+ while ($moreToList) {
+ $foldersToDelete, $moreToList = Get-FoldersToPurge @foldersToDeleteParams
+ $foldersToDeleteCount = $foldersToDelete.count
+ $foldersToDeleteIds = @()
+ $folderNames = @()
+
+ if ($foldersToDeleteCount -eq 0) {
+ Write-Host "`nNo folders to purge matching the criteria"
+ break
+ }
+
+ foreach ($folder in $foldersToDelete) {
+ $foldersToDeleteIds += $folder.FolderId.Id
+ $folderNames += $folder.DisplayName
+ }
+
+ Empty-Folder -FolderIdList $foldersToDeleteIds -FolderNameList $folderNames
+ Delete-Folder -FolderIdList $foldersToDeleteIds -FolderNameList $folderNames
+ }
+}
+
+function Create-Contact {
+ $now = (Get-Date (Get-Date).ToUniversalTime() -Format "o")
+ #used to create a recent seed contact that will be shielded from cleanup. CI tests rely on this
+ $body = @"
+
+
+
+
+
+
+ Sanitago
+ TestContact - $now
+ Corso test enterprises
+
+ sanitago@example.com
+
+
+ 4255550199
+
+ 2000-01-01T11:59:00Z
+ Tester
+ Plate
+
+
+
+"@
+
+ $createContactMsg = Initialize-SOAPMessage -User $User -Body $body
+ $response = Invoke-SOAPRequest -Token $Token -Message $createContactMsg
+}
+
+function Get-ItemsToPurge {
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "Folder under which to look for items matching removal criteria")]
+ [String]$WellKnownRoot,
+
+ [Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp
+ )
+
+ $itemsToDelete = @()
+
+ # SOAP message for getting the folder id
+ $body = @"
+
+
+ Default
+
+
+
+
+
+
+
+
+"@
+
+ Write-Host "`nLooking for items under well-known folder: $WellKnownRoot older than $PurgeBeforeTimestamp for user: $User"
+ $getItemsMsg = Initialize-SOAPMessage -User $User -Body $body
+ $response = Invoke-SOAPRequest -Token $Token -Message $getItemsMsg
+
+ # Get the contacts from the response
+ $items = $response | Select-Xml -XPath "//t:Items/*" -Namespace @{t = "http://schemas.microsoft.com/exchange/services/2006/types" } |
+ Select-Object -ExpandProperty Node
+
+ # Are there more folders to list
+ $rootFolder = $response | Select-Xml -XPath "//m:RootFolder" -Namespace @{m = "http://schemas.microsoft.com/exchange/services/2006/messages" } |
+ Select-Object -ExpandProperty Node
+ $moreToList = ![System.Convert]::ToBoolean($rootFolder.IncludesLastItemInRange)
+
+ foreach ($item in $items) {
+ $itemId = $item.ItemId.Id
+ $changeKey = $item.ItemId.Changekey
+ $itemName = $item.DisplayName
+ $itemCreateTime = $item.ExtendedProperty
+ | Where-Object { $_.ExtendedFieldURI.PropertyTag -eq "0x3007" }
+ | Select-Object -ExpandProperty Value
+ | Get-Date
+
+ if ([String]::IsNullOrEmpty($itemId) -or [String]::IsNullOrEmpty($changeKey)) {
continue
}
- if (![String]::IsNullOrEmpty($FolderNamePurge)) {
- Write-Host "`nFound desired folder to purge: $FolderNamePurge"
+ if (![String]::IsNullOrEmpty($PurgeBeforeTimestamp) -and $itemCreateTime -gt $PurgeBeforeTimestamp) {
+ continue
}
- Write-Verbose "`nFolder Id and ChangeKey for ""$folderName"": $folderId, $changeKey"
+ Write-Verbose "Item Id and ChangeKey for ""$itemName"": $itemId, $changeKey"
+ $itemsToDelete += $item
+ }
- # Empty and delete the folder if found
- if (![String]::IsNullOrEmpty($folderId) -and ![String]::IsNullOrEmpty($changeKey)) {
- if ($PSCmdlet.ShouldProcess("$folderName ($totalCount items) created $folderCreateTime", "Emptying folder")) {
- Write-Host "Emptying folder $folderName ($totalCount items)..."
+ return $itemsToDelete, $moreToList
+}
- # DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
- $body = @"
-
-
-
-
-
+function Purge-Contacts {
+ [CmdletBinding(SupportsShouldProcess)]
+ Param(
+ [Parameter(Mandatory = $True, HelpMessage = "Purge items before this date time (UTC)")]
+ [datetime]$PurgeBeforeTimestamp
+ )
+
+ Write-Host "`nCleaning up contacts older than $PurgeBeforeTimestamp"
+ Write-Host "-------------------------------------------------------"
+
+ # Create one seed contact which will have recent create date and will not be sweapt
+ # This is needed since tests rely on some contact data being present
+ Write-Host "`nCreating seed contact"
+ Create-Contact
+
+ $moreToList = $True
+ # only get max of 1000 results so we may need to iterate over eligible contacts
+ while ($moreToList) {
+ $itemsToDelete, $moreToList = Get-ItemsToPurge -WellKnownRoot "contacts" -PurgeBeforeTimestamp $PurgeBeforeTimestamp
+ $itemsToDeleteCount = $itemsToDelete.count
+ $itemsToDeleteBody = ""
+
+ if ($itemsToDeleteCount -eq 0) {
+ Write-Host "`nNo more contacts to delete matching criteria"
+ break
+ }
+
+ Write-Host "`nQueueing $itemsToDeleteCount items to delete"
+ foreach ($item in $itemsToDelete) {
+ $itemId = $item.ItemId.Id
+ $changeKey = $item.ItemId.Changekey
+ $itemsToDeleteBody += "`n"
+ }
+
+ # Do the actual deletion in a batch request
+ # DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
+ $body = @"
+
+
+ $itemsToDeleteBody
+
+
"@
- $emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
- $response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
- }
-
- if ($PSCmdlet.ShouldProcess($folderName, "Deleting folder")) {
- Write-Host "Deleting folder $folderName..."
-
- # DeleteType = HardDelete, MoveToDeletedItems, or SoftDelete
- $body = @"
-
-
-
-
-
-"@
- $deleteFolderMsg = Initialize-SOAPMessage -User $User -Body $body
- $response = Invoke-SOAPRequest -Token $Token -Message $deleteFolderMsg
- }
-
- Write-Host "Deleted folder $folderName ($totalCount items)"
+
+ if ($PSCmdlet.ShouldProcess("Deleting $itemsToDeleteCount items...", "$itemsToDeleteCount items", "Delete items")) {
+ Write-Host "`nDeleting $itemsToDeleteCount items..."
+
+ $emptyFolderMsg = Initialize-SOAPMessage -User $User -Body $body
+ $response = Invoke-SOAPRequest -Token $Token -Message $emptyFolderMsg
+
+ Write-Host "`nDeleted $itemsToDeleteCount items..."
+
}
}
}
-$token = Get-AccessToken | ConvertTo-SecureString -AsPlainText -Force
+Write-Host 'Authenticating with Exchange Web Services ...'
+$global:Token = Get-AccessToken | ConvertTo-SecureString -AsPlainText -Force
-Remove-Folder -Token $token -User $User -WellKnownRoot $WellKnownRoot
\ No newline at end of file
+$purgeFolderParams = @{
+ 'WellKnownRoot' = "root";
+ 'FolderNamePurgeList' = $FolderNamePurgeList;
+ 'FolderPrefixPurgeList' = $FolderPrefixPurgeList;
+ 'PurgeBeforeTimestamp' = $PurgeBeforeTimestamp
+}
+
+#purge older prefix folders
+Purge-Folders @purgeFolderParams
+
+#purge older contacts
+Purge-Contacts -PurgeBeforeTimestamp $PurgeBeforeTimestamp
+
+# Empty Deleted Items and then purge all recoverable items. Deletes the following
+# -/Recoverable Items/Audits
+# -/Recoverable Items/Deletion
+# -/Recoverable Items/Purges
+# -/Recoverable Items/Versions
+# -/Recoverable Items/Calendar Logging
+# -/Recoverable Items/SubstrateHolds
+Write-Host "`nProcess well-known folders that are always purged"
+Write-Host "---------------------------------------------------"
+Empty-Folder -WellKnownRoot "deleteditems", "recoverableitemsroot"
\ No newline at end of file