get unread mail on outlook and set it to read

Selecting email in outlook:

$OL=New-Object -ComObject OUTLOOK.APPLICATION
$ns =$OL.GETNAMESPACE("MAPI")
$folder=$ns.pickfolder()
$mail=$folder.Items.Restrict('[UnRead] = True') 

Retrieving 8 mails, checked the $mail. There all in there.
(restrict is very nice here, tried getting all the mail and then loop though them so see if there unread, but is takes forever)

    ForEach ($Item in $mail) { $item.unread }  

I only does 4, repeating is a few times is setting more mails on unread=false.
But is should work in 1 go, anyone knows whats happening?

No one ?

This is odd behaviour.

I found this post which inspired the code below. It works but it feels wrong.

$OL = New-Object -ComObject OUTLOOK.APPLICATION
$ns = $OL.GETNAMESPACE("MAPI")
$folder = $ns.pickfolder()

$mail = $folder.Items.Restrict('[UnRead] = True') 

while ($mail.count -gt 0) {

    foreach ($item in $mail) {
      
        $item.UnRead = $false

    }

    $mail = $folder.Items.Restrict('[UnRead] = True') 

}

Thanks.

$mail = $folder.Items.Restrict('[UnRead] = True') 

This is geeting the mail again and again until everything is processed.
Just like i said, if you keep getting the mail, finaly it works.
Only i did i manualy, still dont understand what is happening.

I’ve done a bit more digging. It looks like the $mail collection is dynamic: when you mark an item as read it’s removed from the collection. This is affecting the indexing of the collection.

You can work around this by working backwards through the collection:

$OL = New-Object -ComObject OUTLOOK.APPLICATION
$ns = $OL.GETNAMESPACE("MAPI")
$folder = $ns.pickfolder()

$mail = $folder.Items.Restrict('[UnRead] = True')

for ($i = $mail.count; $i -gt 0; $i--) {

    $mail.Item($i).UnRead = $false

}

Thanks! That works like a charm.