Advertisement
chrislangevin

DeleteSpecificExchangeFolder.ps1

Mar 19th, 2018
1,515
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. # Scan through mailboxes and delete folder with specific name
  2.  
  3.  
  4. <#
  5. .SYNOPSIS
  6. Uses EWS to scan Exchange mailboxes for folders with a specific name and deletes them.
  7.  
  8. .DESCRIPTION
  9. This script is designed to find folders with a specific name in Exchange mailboxes. It can scan multiple mailboxes and find all the folders that fit the criteria. It will save a CSV report file with the details of each folder (Mailbox, FolderName, FolderId). It will also save a debug log. If you choose, it will also delete each found folder.
  10.  
  11. .PARAMETER LogDirectory
  12. Specifies a path to a folder in which the log and report files are to be written. Paths that contain spaces must be enclosed in quotes. The default is the same folder as contains the script.
  13.  
  14. .PARAMETER Mailbox
  15. Specifies the name of a mailbox to scan for items matching the size criteria. This must be in the format of an SMTP address, e.g., "user1@domain.com". Multiple mailboxes can specified, separated by commas.
  16.  
  17. .PARAMETER InputObject
  18. Specifies the mailbox to scan for items matching the size criteria. This must be in the format of an object containing a PrimarySMTPAddress property, such as the Microsoft.Exchange.Data.Directory.Management.Mailbox or Microsoft.Exchange.Data.WebServices.Mailbox object types. This parameter allows the script to accept pipeline input from the Exchange Management Shell's Get-Mailbox cmdlet.
  19.  
  20. .PARAMETER Timeout
  21. Specifies the Timeout parameter of the ExchangeService object, in milliseconds. Default value is 100000 (100 seconds) if not specified. See https://msdn.microsoft.com/en-us/library/office/microsoft.exchange.webservices.data.exchangeservicebase.timeout%28v=exchg.80%29.aspx
  22.  
  23. .PARAMETER EWSUrl
  24. Specifies an explicit URL to Exchange Web Services (EWS). Use this if Autodiscover fails to discover the EWS URL.
  25.  
  26. .PARAMETER RunAsAlternateUser
  27. Allows the user to send the EWS requests as a different user than the one who is running the PowerShell session. Use this if the PowerShell user does not have access to all the mailboxes you want to scan. This is a switch parameter which will pop up a credential prompt at the start of the script; you do not have to supply any part of the credentials on the command line.
  28.  
  29. .PARAMETER FolderName
  30. This is the name of the folder you want to find and delete.
  31.  
  32. .PARAMETER Delete
  33. Add this parameter to delete the found folders. Without it, the script will just generate a report.
  34.  
  35. .EXAMPLE
  36. .\DeleteSpecificExchangeFolder.ps1 -Mailbox BobDole@didntwin.com -FolderName "FindMe"
  37. Scans the BobDole@didntwin.com mailbox and writes a report of all folders named "FindMe"
  38.  
  39. .EXAMPLE
  40. .\DeleteSpecificExchangeFolder.ps1 -Mailbox AlGore@didntwin.com,JohnKerry@didntwin.com -FolderName "Skype for Business Contacts" -Delete
  41. Scans the mailboxes of AlGore@didntwin.com and JohnKerry@didntwin.com for all folders named "Skype for Business Contacts" and deletes them.
  42.  
  43. .EXAMPLE
  44. Get-Mailbox *@didntwin.com | .\DeleteSpecificExchangeFolder.ps1 -FolderName "Skype for Business Contacts" -Delete -EWSUrl "https://mail.didntwin.com/ews/exchange.asmx" -Timeout 200000 -RunAsAlternateUser
  45. Scans all mailboxes returned by the Get-Mailbox cmdlet, reporting on and deleting all folders named "Skype for Business Contacts". The scan's EWS requests will use the specific URL provided (instead of relying on the Autodiscover service), they will have an extended timeout of 200 seconds, and they will be sent using a separate set of credentials entered in a secure prompt.
  46. #>
  47.  
  48.  
  49. Param
  50.     (
  51.         [Alias("o")]
  52.         [ValidateScript({Test-Path -Path $_ -IsValid})]
  53.         [string]
  54.         $LogDirectory = (Split-Path -Parent $MyInvocation.MyCommand.Path)
  55.         ,
  56.         [Alias("m")]
  57.         [Parameter(Mandatory=$true, ParameterSetName="typed")]
  58.         [string]
  59.         $Mailbox
  60.         ,
  61.         [Alias("f")]
  62.         [Parameter(Mandatory=$true)]
  63.         [string]
  64.         $FolderName
  65.         ,
  66.         [Alias("d")]
  67.         [switch]
  68.         $Delete
  69.         ,
  70.         [Parameter(Mandatory=$true, ParameterSetName="piped", ValueFromPipeline=$true)]
  71.         #[Microsoft.Exchange.Data.Directory.Management.Mailbox]
  72.         $InputObject
  73.         ,
  74.         [Alias("t")]
  75.         [int]
  76.         $Timeout = 100000
  77.         ,
  78.         [Alias("ews")]
  79.         [string]
  80.         $EWSUrl
  81.         ,
  82.         [switch]
  83.         $RunAsAlternateUser
  84.     )
  85.  
  86.  
  87.  
  88. #region Functions
  89. #------------------------#
  90. #  Define our functions  #
  91. #------------------------#
  92.  
  93. Function Log-Line
  94.     {
  95.         Param ($logtext)
  96.         Out-File -InputObject "$(Get-Date -Format HH:mm:ss.fff)          $logtext" -FilePath $Logfile -Append
  97.         Write-Verbose $logtext
  98.     }
  99.  
  100. Function Find-NamedFolder
  101.     {
  102.         Param
  103.             (
  104.                 [string]
  105.                 $Name
  106.                 ,
  107.                 [string]
  108.                 $Mailbox
  109.             )
  110.  
  111.         $mbx = New-Object Microsoft.Exchange.WebServices.Data.Mailbox($Mailbox)
  112.         $TOISFolderId = New-Object Microsoft.Exchange.WebServices.Data.FolderId([Microsoft.Exchange.WebServices.Data.WellKnownFolderName]::MsgFolderRoot,$mbx)
  113.  
  114.         $FolderFilter = New-Object Microsoft.Exchange.WebServices.Data.SearchFilter+IsEqualTo([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName,$Name)
  115.  
  116.         $FolderView = New-Object Microsoft.Exchange.WebServices.Data.FolderView(100)
  117.         $FolderView.Traversal = [Microsoft.Exchange.WebServices.Data.FolderTraversal]::Deep
  118.         $FolderPropertySet = New-Object Microsoft.Exchange.WebServices.Data.PropertySet([Microsoft.Exchange.WebServices.Data.BasePropertySet]::IdOnly)
  119.         $FolderPropertySet.Add([Microsoft.Exchange.WebServices.Data.FolderSchema]::DisplayName)
  120.  
  121.  
  122.         $FolderResults = $exchService.FindFolders($TOISFolderId,$FolderFilter,$FolderView)
  123.         Return $FolderResults
  124.     }
  125.  
  126.  
  127. #-----------------------------#
  128. #   End function definitions  #
  129. #-----------------------------#
  130. #endregion Functions
  131.  
  132.  
  133.  
  134. #-------------------#
  135. #   Setup logging   #
  136. #-------------------#
  137.  
  138. # Create log file path if it does not exist
  139. If ((Test-Path $LogDirectory) -eq $false) {mkdir $LogDirectory | Out-Null}
  140.  
  141. $Logfilesuffix = (Get-Date -Format yyyyMMddHHmmss) + "_" + (Get-Random).ToString().Substring(0,3)
  142. $Logfile = "$LogDirectory\DeleteSpecificExchangeFolder_Log_$Logfilesuffix.log"
  143.  
  144.  
  145. # Initialize new log file
  146. Out-File -InputObject "Delete Specific Exchange Folder Script`n`n" -FilePath $Logfile
  147.  
  148. Log-Line "Start of script"
  149. # Collect start time for metrics
  150. $starttime = Get-Date
  151.  
  152. #-------------------#
  153. # End Logging setup #
  154. #-------------------#
  155.  
  156.  
  157.  
  158. #------------------------------#
  159. #     Start of main script     #
  160. #------------------------------#
  161.  
  162.  
  163. # Load Exchange dependencies
  164. Log-Line "Loading Exchange dependencies..."
  165. If (-not (Get-Module Microsoft.Exchange.WebServices)) {Import-Module -Name ".\Microsoft.Exchange.WebServices.dll" -ErrorAction Stop}
  166. Log-Line "Exchange dependencies loaded"
  167.  
  168. Log-Line "Setting up Exchange objects..."
  169.  
  170. Log-Line "Creating ExchangeService object"
  171. $exchService = New-Object Microsoft.Exchange.WebServices.Data.ExchangeService
  172.  
  173. # Get credentials for the alternate user
  174. if ($RunAsAlternateUser)
  175. {
  176.     $psCreds = Get-Credential -Message "Type the credentials of a user with access to all mailboxes. Use DOMAIN\User format." -UserName ($env:USERDOMAIN + "\" + $env:USERNAME)
  177.     # Convert to the format used by ExchangeService object
  178.     $exchService.Credentials = $psCreds.GetNetworkCredential()
  179. }
  180.  
  181. # Otherwise just use the credentials of whoever is running PowerShell
  182. else
  183. {$exchService.UseDefaultCredentials = $true}
  184.  
  185.  
  186. $exchService.Timeout = $Timeout
  187.  
  188. # Get the mailboxes to process
  189.  
  190. $mailboxes = @()
  191.  
  192. if ($PSCmdlet.ParameterSetName -eq "typed")
  193. {$mailboxes += $Mailbox}
  194.  
  195. elseif ($PSCmdlet.ParameterSetName -eq "piped")
  196. {
  197.     foreach ($i in $input)
  198.     {
  199.         $mailboxes += $i.PrimarySmtpAddress.ToString()
  200.     }
  201. }
  202.  
  203.  
  204. Log-Line "Found $($mailboxes.Count) mailboxes to process"
  205.  
  206. $MailboxCounter = 1
  207. $TotalFolderCounter = 0
  208. $TotalDeleteCounter = 0
  209. :mailboxLoop foreach ($mbx in $mailboxes)
  210.     {
  211.         Log-Line "Processing mailbox $MailboxCounter of $($mailboxes.Count): [$mbx]"
  212.         Write-Progress -Id 1 -Activity "Processing Mailboxes" -Status "Mailbox $MailboxCounter of $($mailboxes.Count)" -PercentComplete (($MailboxCounter/$mailboxes.Count) * 100) -CurrentOperation "[$mbx]"
  213.        
  214.         If ($EWSUrl)
  215.         {
  216.             Log-Line "Setting EWS virtual directory from parameter value: $EWSUrl"
  217.             $exchService.Url = $EWSUrl
  218.         }
  219.         Else
  220.         {        
  221.             Log-Line "Setting EWS virtual directory from Autodiscover for mailbox [$mbx]"
  222.             $exchService.AutodiscoverUrl($mbx)
  223.         }
  224.  
  225.         try
  226.         {
  227.             $FoldersToCheck = Find-NamedFolder -Mailbox $mbx -Name $FolderName
  228.             Log-Line "Found $($FoldersToCheck.Count) folders in the mailbox [$mbx]"
  229.         }
  230.         catch
  231.         {
  232.             if ($_.Exception.Message.Contains("The specified object was not found in the store."))
  233.             {
  234.                 Write-Warning "Could not enumerate folders in the mailbox [$mbx]. Are you sure you have access to this mailbox?"
  235.             }
  236.             Log-Line "Error reading folders in mailbox [mbx]. Error type: $($_.Exception.GetType().FullName) Error message: $($_.Exception.Message)"
  237.             Write-Error -ErrorRecord $_
  238.             Continue mailboxLoop
  239.         }
  240.                
  241.  
  242.         # Iterate through each folder
  243.         $FolderCounter = 1
  244.         :folderLoop foreach ($folder in $FoldersToCheck)
  245.             {
  246.                 Log-Line "Processing folder $FolderCounter of $($FoldersToCheck.Count) - Name: [$($folder.DisplayName)] - FolderId: [$($folder.Id)]"
  247.                 Write-Progress -Id 2 -ParentId 1 -Activity "Processing Folders in [$mbx]" -Status "Folder $FolderCounter of $($FoldersToCheck.Count)" -PercentComplete (($FolderCounter/$FoldersToCheck.Count) * 100) -CurrentOperation "[$($folder.DisplayName)]"
  248.  
  249.                 $DeletionSuccess = $false
  250.                
  251.                 try
  252.                 {
  253.                     if ($Delete)
  254.                     {
  255.                         # Deletes to Recoverable Items in case you change your mind
  256.                         $folder.Delete([Microsoft.Exchange.WebServices.Data.DeleteMode]::SoftDelete)
  257.                         $DeletionSuccess = $true
  258.                         $TotalDeleteCounter ++
  259.                     }
  260.                    
  261.                 }
  262.                 catch
  263.                 {
  264.                
  265.                 }
  266.                 finally
  267.                 {    
  268.                     $FolderCounter ++
  269.                     $TotalFolderCounter ++
  270.                     Log-Line "Processing complete for folder [$($folder.DisplayName)] with FolderId [$($folder.Id)]. Deletion attempted: [$Delete] Deletion completed: [$DeletionSuccess]"
  271.                 }
  272.             } # end of folderloop
  273.         $MailboxCounter ++
  274.         Log-Line "Processing complete for mailbox [$mbx]"
  275.     } # end of mailbox loop
  276.  
  277.  
  278. Log-Line "End of script processing"
  279.  
  280.  
  281.  
  282.  
  283. #------------------------#
  284. #   End of main script   #
  285. #------------------------#
  286.  
  287. # Collect end time for metrics
  288. $endtime = Get-Date                
  289. Log-Line "`n`nTotal runtime: $($endtime - $starttime)"
  290. Log-Line "`n`nTotal mailboxes processed: $MailboxCounter"
  291. Log-Line "`n`nTotal folders with name [$FolderName] found: $TotalFolderCounter"
  292. Log-Line "`n`nTotal folders with name [$FolderName] successfully deleted: $TotalDeleteCounter"
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement