?
Solved

PowerShell Script to Delete Unread Messages

Posted on 2014-08-25
20
Medium Priority
?
1,004 Views
Last Modified: 2014-08-28
I came across this script online that will delete all unread messages out of deleted items folder that are older than 6 months old.

Const olFolderDeletedItems = 6

 Set objOutlook = CreateObject("Outlook.Application")
 Set objNamespace = objOutlook.GetNamespace("MAPI")
 Set objFolder = objNamespace.GetDefaultFolder(olFolderDeletedItems)

 Set colItems = objFolder.Items
 Set colFilteredItems = colItems.Restrict("[UnRead] = True")

 For i = colFilteredItems.Count to 1 Step - 1
     If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
         colFilteredItems(i).Delete
     End If
 Next

However, I get the below error message when I try to run. Seems like a syntax issue but cannot sort it out. Any help would be appreciated.

At line:10 char:5
+  For i = colFilteredItems.Count to 1 Step - 1
+     ~
Missing opening '(' after keyword 'for'.
At line:11 char:8
+      If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
+        ~
Missing '(' after 'If' in if statement.
At line:11 char:22
+      If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
+                      ~
Missing expression after ','.
At line:11 char:23
+      If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
+                       ~~~~~~~~~~~~~~~~
Unexpected token 'colFilteredItems' in expression or statement.
At line:11 char:22
+      If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
+                      ~
Missing closing ')' in expression.
At line:11 char:60
+      If DateDiff("m", colFilteredItems(i).ReceivedTime, Now) > 6 Then
+                                                            ~
Unexpected token ')' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingOpenParenthesisAfterKeyword
0
Comment
Question by:GR JN
  • 9
  • 7
  • 2
18 Comments
 
LVL 71

Expert Comment

by:Qlemo
ID: 40284212
This is VB Script code, no PowerShell ...
0
 
LVL 22

Expert Comment

by:Haresh Nikumbh
ID: 40284226
Agreed with Qlemo,

you need to use cscript to execute this VB script

save it as a .vbs format and run it from command prompt

CScript "C:\Name of the script file vbs"
0
 
LVL 71

Assisted Solution

by:Qlemo
Qlemo earned 1500 total points
ID: 40284232
In PowerShell, it looks like this:
$olFolderDeletedItems = 6

$objOutlook = New-Object -Com Outlook.Application
$colItems = $objOutlook.Session.GetDefaultFolder(olFolderDeletedItems).Items
$colFilteredItems = $colItems.Restrict("[UnRead] = True")

$olddate = (Get-Date).AddMonths(-6)
$colFilteredItems | % {
   if ($_.ReceivedTime -le $olddate)   { $_.Delete()  }
}

Open in new window

0
Get free NFR key for Veeam Availability Suite 9.5

Veeam is happy to provide a free NFR license (1 year, 2 sockets) to all certified IT Pros. The license allows for the non-production use of Veeam Availability Suite v9.5 in your home lab, without any feature limitations. It works for both VMware and Hyper-V environments

 

Author Comment

by:GR JN
ID: 40284282
I am still getting this error message when I try to run.

At line:4 char:50
+ $colItems = $objOutlook.Session.GetDefaultFolder(olFolderDeletedItems).Items
+                                                  ~
Missing ')' in method call.
At line:4 char:50
+ $colItems = $objOutlook.Session.GetDefaultFolder(olFolderDeletedItems).Items
+                                                  ~~~~~~~~~~~~~~~~~~~~
Unexpected token 'olFolderDeletedItems' in expression or statement.
At line:4 char:70
+ $colItems = $objOutlook.Session.GetDefaultFolder(olFolderDeletedItems).Items
+                                                                      ~
Unexpected token ')' in expression or statement.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : MissingEndParenthesisInMethodCall
0
 
LVL 22

Expert Comment

by:Haresh Nikumbh
ID: 40284315
have you tried Powershell script ? which has given by Qlemo?
0
 

Author Comment

by:GR JN
ID: 40284325
yes, I have. It gives me the above error (see attached).
0
 

Author Comment

by:GR JN
ID: 40284333
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 40284337
Small typo, but the script can be improved anyway, so:
$objOutlook = New-Object -Com Outlook.Application
$colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

$olddate = (Get-Date).AddMonths(-6).ToShortDateString()
$colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'") |
  % { $_.Delete() }

Open in new window

0
 

Author Comment

by:GR JN
ID: 40284360
Thanks. This seems to work great. However, I noticed that I had to runt it a few times to delete all of the unread emails older than 6 months. Seems like the script would quit before actually completing.

Also, to take this a step further, how can we execute this on a remote machine on the network or in the domain? I am assuming it would entail using the invoke-command?
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 40284394
The script itself has to run completely on the remote machine - there are no remote commands for any part of the script. So yes, you would have to run the script with Invoke-Command, which again requires you to have set up WinRM on each remote machine to allow connection and execution.
Client OS machines (W7 etc.) do not have WinRM set up by default, server OS do.
The manual way to enable WinRM is to run WinRM quickconfig once on each client.

The script might fail only because of one issue - the sequence of mails. Outlook is very delicate if you try to access moved or deleted mails in an order (that is the reason the VBS code starts with the last mail going towards the first one in the filter list).

This slight variation might help with that, and shows how to execute the code remotely.
Invoke-Command -Computer 'pc1', 'pc2'  -Script {
  $objOutlook = New-Object -Com Outlook.Application
  $colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

  $olddate = (Get-Date).AddMonths(-6).ToShortDateString()
  $filtered = $colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'")
  $filtered |
    % { $_.Delete() }
  }

Open in new window

0
 

Author Comment

by:GR JN
ID: 40284724
Thanks. It still looks like it is taking a few executions to get all of the messages. How can I have the script automatically run 3 or 4 times? Is there a way to loop the job "x" times?
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 40285100
In that case we should make it failsafe, similar to the original.
Invoke-Command -Computer 'pc1', 'pc2'  -Script {
  $objOutlook = New-Object -Com Outlook.Application
  $colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

  $olddate = (Get-Date).AddMonths(-6).ToShortDateString()
  $filtered = $colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'")
  if ($filtered.Count)
  {
     foreach ($i in $filtered.count..1) { $filtered.Item($i).Delete() }
  }
}

Open in new window

This code could also work, as it processes a copy of the collation instead of the (changing) original collation of search results:
Invoke-Command -Computer 'pc1', 'pc2'  -Script {
  $objOutlook = New-Object -Com Outlook.Application
  $colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

  $olddate = (Get-Date).AddMonths(-6).ToShortDateString()
  $filtered = $colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'")
  foreach ($mail in @($filtered) { $mail.Delete() }
}

Open in new window

0
 

Author Comment

by:GR JN
ID: 40286033
Unfortunately neither of these scripts work.

This is the error message that I get

At line:6 char:34
+   foreach ($mail in @($filtered) { $mail.Delete() }
+                                  ~
Unexpected token '{' in expression or statement.
At line:6 char:33
+   foreach ($mail in @($filtered) { $mail.Delete() }
+                                 ~
Missing closing ')' after expression part of foreach loop.
    + CategoryInfo          : ParserError: (:) [], ParentContainsErrorRecordException
    + FullyQualifiedErrorId : UnexpectedToken
0
 

Author Comment

by:GR JN
ID: 40286048
Additionally, is there anyway to do this directly from the Exchange server rather than targeting the Outlook application?
0
 

Author Comment

by:GR JN
ID: 40286827
So I tried executing the below script. It just hangs but does not execute on the remote PC. Any thoughts?

$ComputerName = Read-Host "Type he PC that you want to remove messages from:"
Invoke-Command -ComputerName $ComputerName -Credential (Get-Credential -Credential domain\user) -Script {
$objOutlook = New-Object -Com Outlook.Application
$colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

$olddate = (Get-Date).AddMonths(-1).ToShortDateString()
$colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'") |
  % { $_.Delete() }
  }
0
 

Author Comment

by:GR JN
ID: 40288571
I've requested that this question be closed as follows:

Accepted answer: 0 points for Narvaezj's comment #a40286827

for the following reason:

Closed due to lack of response
0
 
LVL 71

Expert Comment

by:Qlemo
ID: 40288572
Sorry, didn't receive any notice about your posts.
0
 
LVL 71

Accepted Solution

by:
Qlemo earned 1500 total points
ID: 40288615
Re: http:#a40286033
Yes, there is a syntax error in the second script (a closing paren missing), but you didn't show why the first one should not work. I suppose it only doesn't change the issue with not deleting all mails in one go still.

The second script should be:
Invoke-Command -Computer 'pc1', 'pc2'  -Script {
  $objOutlook = New-Object -Com Outlook.Application
  $colItems = $objOutlook.Session.GetDefaultFolder('OlFolderDeletedItems').Items

  $olddate = (Get-Date).AddMonths(-6).ToShortDateString()
  $filtered = $colItems.Restrict("[UnRead] = True AND [ReceivedTime] <= '$olddate'")
  foreach ($mail in @($filtered)) { $mail.Delete() }
}

Open in new window


Re: http:#a40286048
Using Exchange is totally different. Exchange 2010 has own cmdlets. This is certainly out of scope of this question, as working with the server requires different techniques. As a hint: Search-Mailbox will do that.

Re: http:#a40286827
Probably there is an access issue with the respective mail profile. I forgot that you need to have access to the Outlook session of a particular user - your code is using an admin user, which will not have the profile you search for. But honestly, wanting to run the script remotely is a severe twist in the question - and I doubt it is possible, as the remote session isn't interactive nor has it access to the current user session (AFAIK), and hence to the Outlook if running.

I consider this question answered.

Please ask a new one, about how to do it with Exchange 2010 for particular or all user mailboxes. If you want to perform that action for others, it is the only proper way to do. Describe exactly what you want to do from start, to get sound and effective advise.
0

Featured Post

Technology Partners: We Want Your Opinion!

We value your feedback.

Take our survey and automatically be enter to win anyone of the following:
Yeti Cooler, Amazon eGift Card, and Movie eGift Card!

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Transferring FSMO roles is done when an admin wants to split roles between certain Domain Controllers or the Domain Controller holding the Roles has been forcefully demoted using dcpromo / forceremoval
This article will help to fix the below errors for MS Exchange Server 2016 I. Certificate error "name on the security certificate is invalid or does not match the name of the site" II. Out of Office not working III. Make Internal URLs and Externa…
This video shows how to quickly and easily add an email signature for all users on Exchange 2016. The resulting signature is applied on a server level by Exchange Online. The email signature template has been downloaded from: www.mail-signatures…
Screencast - Getting to Know the Pipeline
Suggested Courses
Course of the Month16 days, 22 hours left to enroll

862 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question