I wrote a script to delete the emails from the Deleted Items folder in Outlook, however the script is acting very strange, it does work but it does not delete every single email in that folder, I was trying to debug and it appears that it does not go through all objects in the loop, I saw that adding a Write-Host in the loop, however when I run the script one more time, it does delete another portion of the emails but not all of them, I need to run it some times to get it do delete everything.
$olApp = New-Object -ComObject outlook.application
$namespace = $olApp.GetNamespace("MAPI")
#Get the name space and the Deleted Items folder(the number 3)
$Folder = $namespace.GetDefaultFolder(3)
#Remove the \\ in the string name
$FolderPath = ($Folder.FolderPath).Substring(2,39)
Write-Host ("The items in the mailbox\folder: [$FolderPath] will be deleted.")
#Get all items(emails) from the Deleted Items folder
$Items = ($Folder.Items)
#Display how many items(emails) will be deleted
$Count = $Items.Count
Write-Host ("$Count emails will be deleted.")
#Delete everything
$Items | ForEach-Object {$_.Delete()}
$olApp.Quit | Out-Null
[GC]::Collect()
I’m not sure what scenario this is (unattended mailbox etc) but why not just turn on the feature in Outlook to empty the deleted items on exit, or if this is an O365 account you can set a retention policy that does the same thing
Hi @neemobeer, I am replying to this again since I actually see the use case better now.
That option that you mentioned only works when I click the “X” to close the Outlook application at the GUI, then I get a pop up to confirm if I’d like to delete all items in the deleted item folder.
However, I created a script to shut everything down on my machine with the flag -Force, if I close the Outlook process by a PowerShell console, that option does not apply and does NOT delete those items.
I tested with Outlook and saw the message to confirm if I wanted to confirm the deletion of the items, now I need to see if there is a way for PowerShell to automatically say Yes on that popup.
Since Stop-Process does not return any output by default there is nothing for Foreach-Object to process.
And even if you use the parameter -PassThru you will only get an object representing the already stopped process. So nothing you can do about the process anymore.
Fair enough Olaf, but that still does not answer my initial question on the post on why the loop is not going through all items:
$Items | ForEach-Object {$_.Delete()}
I needed to make a “workaround” to run the script few times to get everything deleted at once.
<# For some reason that I could not figure it out yet, if I don't use the loop for the script to run multiple times
the loop seems to be stopped in the middle and it does not go through all items in the "$Items | ForEach-Object {$_.Delete()}"
However for now I worked around it using the loop.
#>
$i = 0
while ($i -le 9){
$i++
$olApp = New-Object -ComObject outlook.application
$namespace = $olApp.GetNamespace("MAPI")
#Get the name space and the Deleted Items folder(the number 3)
$Folder = $namespace.GetDefaultFolder(3)
#Remove the \\ in the string name
$FolderPath = ($Folder.FolderPath).Substring(2,39)
Write-Host ("The items in the mailbox\folder: [$FolderPath] will be deleted.")
#Get all items(emails) from the Deleted Items folder
$Items = ($Folder.Items)
#Display how many items(emails) will be deleted
$Count = $Items.Count
Write-Host ("$Count emails will be deleted.")
#Delete everything
$Items | ForEach-Object {$_.Delete()}
#Times script was processed
Write-Host ("Script was processed $i time(s)")
$olApp.Quit | Out-Null
[GC]::Collect()
}
I actually don’t get why you need to empty your recycle bin that urgently in the first place. Outlook or Exchange will empty it automatically after the time you set up. … but that’s my issue.
It might be for an older version but this could help:
The reason you need to loop seems to be that the objects gets deleted from the $items list too which leads to the list index being wrong. Looping backwards should work:
for ($i=$Count; $i -gt 0; $i--) {
$Items[$i].Delete()
}
or actually even
for ($i=$Count; $i -gt 0; $i--) {
$Items[0].Delete()
}