Author Posts

March 1, 2017 at 5:27 pm

Hi friends, relative beginner here. I'm looking to automate some Outlook functionality, but running in to a strange problem I cannot diagnose despite Googling all morning. Perhaps you would be so kind as to explain what I am obviously doing wrong.

I am trying to filter emails based on conditions so I can move or delete them.

Add-Type -AssemblyName "Microsoft.Office.Interop.Outlook"
$outlook = New-Object -ComObject Outlook.Application
$namespace = $outlook.GetNamespace("MAPI")
$inbox = ($namespace.Folders.Item("MyInbox).Folders.Item("Inbox"))
$emails = $inbox.Items

Here is where it breaks down. I want to filter the mailitems by subject so I can foreach move them.

$movemails = ($emails | Where-Object {$_.Subject -contains "Subject"} )

The command runs for a bit, then displays no output. I run:

$movemails | Get-Member

And the output is this error message:

gm : You must specify an object for the Get-Member cmdlet.
At line:1 char:13
+ $iconmail | gm
+ ~~
+ CategoryInfo : CloseError: (:) [Get-Member], InvalidOperationException
+ FullyQualifiedErrorId : NoObjectInGetMember,Microsoft.PowerShell.Commands.GetMemberCommand

For whatever reason Where is not returning the mailitem Com-Objects and I do not know why. I also tried using an out-variable but the same error occurred when checking the output.

March 1, 2017 at 9:51 pm

Ugh. I hate that COM object.

Anyway, I think you're using the wrong operator. See if this helps: https://devopscollective.gitbooks.io/the-big-book-of-powershell-gotchas/content/manuscript/contains-isnt-like.html.

March 1, 2017 at 11:11 pm

Hi Don. Thank you for the link. Using -Like solved the problem... except I do not know why since I used the "TEST" subject line and the value was "TEST". Oh well. Thanks!

March 2, 2017 at 12:34 am

Not sure if I should post here or start a different thread, but I have a related question.

First, I hate this COM Object too.

I want to understand why I cannot select an object from a collection with indexing. For example I have $emails = $inbox.Items which returns a collection of mail items, but $emails[1] returns an error. You need to use $emails.Item(), and I just am curious as to why. I guess not all collections are immediately indexed?

Lastly, I'm having some trouble interacting with them and I hope that by strongly typing my variables I can solve the problem. However if I do:

#Set email object to variable
$email = $emails.GetFirst() 
[Microsoft.Office.Interop.Outlook.MailItem]$mailitem = $email

I encounter this odd error

Cannot convert the "System.__ComObject" value of type
"System.__ComObject#{00063006-0000-0000-c000-000000000046}" to type
"Microsoft.Office.Interop.Outlook.MailItem".

March 2, 2017 at 1:02 am

>I want to understand why I cannot select an object from a collection with indexing. For example I have $emails = $inbox.Items which returns a collection of mail items, but $emails[1] returns an error. You need to use $emails.Item(), and I just am curious as to why. I guess not all collections are immediately indexed?

Because it isn't a collection type that supports indexing. Likely because it's lazy-retrieved to save memory. Also, COM.

>Lastly, I'm having some trouble interacting with them and I hope that by strongly typing my variables I can solve the problem.

Actually, your trouble is that you're using an old COM object via Interop and that often sucks. It's just too many layers and too many abstractions trying to make it work. GetFirst() isn't returning a strongly-typed object, and it never will. You're just exceeding what the designers of Outlook's COM object ever imagined.

March 2, 2017 at 12:13 pm

Thanks Don! Is there a better way to do this or am I SOL?

March 2, 2017 at 2:42 pm

You might see if you can do this server-side. At least those components are newer and more up to date.