Hey, Scripting Guy! With Windows PowerShell Can I Get a List of E-Mail I Have Marked for Follow-Up?

Hey, Scripting Guy! With Windows PowerShell Can I Get a List of E-Mail I Have Marked for Follow-Up?

  • Comments 1
  • Likes

Bookmark and Share

Hey, Scripting Guy! Question

Hey, Scripting Guy! I don’t know about you, but I get a ton of e-mail every day. Of course, I use inbox rules to filter my e-mail, but one thing that I seem to miss is e-mail that has been marked for follow-up. I would love to see a Windows PowerShell script that will troll my inbox and display a list of e-mail messages that have been marked for follow-up. Is this something that can be done?

-- MS

Hey, Scripting Guy! AnswerHello MS,

Microsoft Scripting Guy Ed Wilson here. Today has been an awesome day. I downloaded Exchange 2010 from the Microsoft TechNet site (I got a free subscription earlier in the year when I attended TechEd 2009 in Los Angeles) and burned it to DVD. I am now in the process of building an Exchange Server 2010 on my Windows Server 2008 R2 Hyper-V box. Over the Thanksgiving holidays, I built a couple of Windows XP virtual machines and installed Office 2007 on them. I need the machines because I am running Windows 7 with the latest build of Office 2010 beta, and I like to have something against which to test.

Because I used to do a lot of networking before I joined Microsoft, I really enjoying building machines, and setting up various test scenarios. Before virtual machines, my test lab consisted of 12 physical computers—it was fun, but expensive and noisy. With virtualization, I can have as many computers as I wish, as long as I have the disk space and software licenses (and between my MSDN subscription and my TechNet subscription, I can get quite a few software licenses). Of course, if I am not going to use a machine permanently, I do not activate it, which allows me even more flexibility.

Let's whip up a new Windows PowerShell script to christen my bright and shiny new Exchange server on a Hyper-V box and a couple of new clients with fresh installs of Microsoft Outlook 2007.

MS, I totally sympathize with you regarding the follow-up flag. Items flagged for follow-up show up in my Outlook task list, but there is no easy way to filter them out. If your inbox runs to several thousand e-mails, like mine routinely does, scrolling up and down through the e-mail can be a bit problematic.

Just a second while I crank up the Alan Parsons Project (great music for writing Outlook scripts) on my Zune HD, roll up my sleeves, fire up the Windows PowerShell 2.0 ISE, and get started.

Okay, okay, if you only want the script, the complete ListFollowUpEmail.ps1 script is seen here.

ListFollowUpEmail.ps1

#Requires -version 2.0
Add-Type -AssemblyName Microsoft.Office.Interop.Outlook
$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]
$outlook = New-Object -ComObject outlook.application
$namespace  = $Outlook.GetNameSpace("mapi")
$folder = $namespace.getDefaultFolder($olFolders::olFolderInbox)
$items = $folder.Items
"The following items are marked for followup:"
foreach($item in $items)
{
 if($item.flagStatus -eq 2)
   { $item.subject }
}

The ListFollowUpEmail.ps1 script begins by loading the Microsoft.Office.Interop.Outlook .NET Framework assembly. You do not have to load the interop assembly, but if you do, it gives you direct access to the Microsoft Outlook enumerations such as the OlDefaultFolders enumeration. The OlDefaultFolders enumeration is used by the GetDefaultFolder method from the NameSpace object. To load the Microsoft.Office.Interop.Outlook interop assembly in Windows PowerShell 1.0, you could use the LoadWithPartialName static method from the Reflections.Assembly .NET Framework class. But the LoadWithPartialName static method is now obsolete (although it still works), and you should use the Load static method instead. The problem is that the Load static method from Reflections.Assembly requires the full name to the assembly. This is especially problematic because MSDN does not list the full name of the assembly. To determine the full name, you can use the GetAssembly method to retrieve the currently loaded assembly in which the specified class is defined. As seen here, we use the $olFolders enumeration class after we have loaded the Outlook interop assembly.

PS C:\> [reflection.assembly]::GetAssembly($olFolders)

GAC    Version        Location
---    -------        --------
True   v2.0.50727     C:\Windows\assembly\GAC_MSIL\Microsoft.Office.Interop.Outlook\14.0.0.0__71e9bce111e9429c\Micro...

PS C:\> [reflection.assembly]::GetAssembly($olFolders) | Format-List *

CodeBase            : file:///C:/Windows/assembly/GAC_MSIL/Microsoft.Office.Interop.Outlook/14.0.0.0__71e9bce111e9429c/
                      Microsoft.Office.Interop.Outlook.dll
EscapedCodeBase     : file:///C:/Windows/assembly/GAC_MSIL/Microsoft.Office.Interop.Outlook/14.0.0.0__71e9bce111e9429c/
                      Microsoft.Office.Interop.Outlook.dll
FullName            : Microsoft.Office.Interop.Outlook, Version=14.0.0.0, Culture=neutral, PublicKeyToken=71e9bce111e9429c

It would be silly to use an obsolete method to load an assembly and then use a different method to retrieve the full name of the assembly. However, that is what you would need to do in order to be able to use the Load method. Luckily, the Add-Type cmdlet was added to Windows PowerShell 2.0. This cmdlet will accept the partial assembly name, and therefore you do not need to worry about using an obsolete method. Because the Add-Type cmdlet only exists on Windows PowerShell 2.0, make sure to use the #Requires –Version 2.0 tag to prevent errors with Windows PowerShell 1.0:

#Requires -version 2.0
Add-Type -AssemblyName Microsoft.Office.Interop.Outlook

After you have loaded the Outlook interop assembly, you can load the OlDefaultFolders enumeration as a type so that you will be able to directly address the enumeration value. This is seen here where the OlDefaultFolders enumeration is stored in the $olFolders variable:

$olFolders = "Microsoft.Office.Interop.Outlook.OlDefaultFolders" -as [type]

Now it is time to create an instance of the Outlook.Application COM object. The application object is the basic object to use when working with automating Microsoft Outlook. It will be included in nearly all of the scripts you write that work with Microsoft Outlook. To create the outlook.application object, you use the New-Object cmdlet and specify the –comobject parameter. The return application object is stored in the $outlook variable. This is seen here:

$outlook = New-Object -ComObject outlook.application

Next, you need to create a namespace object. To do this, use the GetNameSpace method from the application object. The GetNameSpace method requires a single parameter that is always “mapi.” This is shown here:

$namespace  = $Outlook.GetNameSpace("mapi")

After you have a namespace object, you can use the GetDefaultFolder method to return a specific folder. You use the OlDefaultFolders enumeration to specify the folder you wish to return. To connect to the inbox, use the olFoderInbox. Other folders are listed in the MSDN article that discusses the OlDefaultFolders enumeration. The returned folder is stored in the $folder variable as shown here:

$folder = $namespace.getDefaultFolder($olFolders::olFolderInbox)

The items property of the folder object has the items property that returns an items collection object that represents all the items in the specified folder. In our script, because we are connected to the inbox, the items collection returns instances of Outlook MailItem objects. It is important to know which types of objects are returned by the Items property because it will determine which properties are available for filtering, and which methods are available for processing the items in the collection. MailItem object properties and methods are documented on MSDN. The collection of MailItem objects are stored in the $items variable, as shown here:

$items = $folder.Items

A single string is displayed on the Windows PowerShell console to indicate which results are being shown:

"The following items are marked for followup:"

To work through the collection of MailItem objects, the foreach statement is used. The $item variable is used as enumerator as the script works through the collection of objects. If the flagStatus is equal to 2, it means that the mail item has been flagged for follow up:

foreach($item in $items)
{
 if($item.flagStatus -eq 2)
   { $item.subject }
}

When the script runs, the results shown in the following image are displayed in the Windows PowerShell 2.0 ISE:

Image of the results of running the script


MS, that is all there is to using Windows PowerShell to retrieve follow-up e-mail messages. Microsoft Outlook Week will continue tomorrow.

If you want to know exactly what we will be looking at tomorrow, follow us on Twitter or Facebook. If you have any questions, send e-mail to us at scripter@microsoft.com or post your questions on the Official Scripting Guys Forum. See you tomorrow. Until then, peace.

 

Ed Wilson and Craig Liebendorfer, Scripting Guys

 

Your comment has been posted.   Close
Thank you, your comment requires moderation so it may take a while to appear.   Close
Leave a Comment