How To: Use Find and FindNext methods to retrieve Outlook mail items from a folder (C#, VB.NET)
As you have probably guessed, this article will describe the Find and FindNext methods of the Outlook Items class. But before focusing on the functionality of these methods, I would like to draw an analogy with database programming in the .NET world. In ADO.NET there is the System.Data.SqlClient.SqlDataReader class which provides the Read method. It reads the db records line by line according to the query you specified in the System.Data.SqlClient.SqlCommand class. As you will see a bit later, the Find and FindNext methods in Outlook do the same. Outlook and its object model act like a big wrapper around the Messaging db ;-)
The Find method locates and returns an Outlook item that specifies the provided filter. It accepts a string value reflecting the criteria that a result item should meet. The format of the string depends on the field type that you are going to filter by. Please note that there are some item properties that you can’t use for the filter. You can read more about the properties not allowed in the filter string and string formats used for the search criterion on MSDN.
As soon as the first record is found we need to use the FindNext method of the Items class to continue receiving subsequent records from Outlook according to the filter we specified in the Find method. As you may see, this is the major difference between the ADO.NET and Outlook classes. The FindNext method doesn’t accept any parameters; it just does its job: finds and returns the next Outlook item. Null (Nothing in case of VB.NET) will be returned if there are no more items meeting the search criteria or if FindNext simply fails.
The following sample iterates over all unread e-mails listed in the specified folder (see the folder parameter of the FindAllUnreadEmails method). It just writes unread e-mails’ subjects to the debug window using the System.Diagnostics.Debug class. Please use the DebugView utility to intercept the debug output.
C# and Add-in Express:
using System.Text; using System.Diagnostics; // ... private void FindAllUnreadEmails(Outlook.MAPIFolder folder) { string searchCriteria = "[UnRead] = true"; StringBuilder strBuilder = null; int counter = default(int); Outlook._MailItem mail = null; Outlook.Items folderItems = null; object resultItem = null; try { if (folder.UnReadItemCount > 0) { strBuilder = new StringBuilder(); folderItems = folder.Items; resultItem = folderItems.Find(searchCriteria); while (resultItem != null) { if (resultItem is Outlook._MailItem) { counter++; mail = resultItem as Outlook._MailItem; strBuilder.AppendLine("#" + counter.ToString() + "\tSubject: " + mail.Subject); } Marshal.ReleaseComObject(resultItem); resultItem = folderItems.FindNext(); } if (strBuilder != null) Debug.WriteLine(strBuilder.ToString()); } else Debug.WriteLine("There is no match in the " + folder.Name + " folder."); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (folderItems != null) Marshal.ReleaseComObject(folderItems); } }
VB.NET and Add-in Express:
Imports System.Text Imports System.Diagnostics ' ... Private Sub FindAllUnreadEmails(folder As Outlook.MAPIFolder) Dim searchCriteria As String = "[UnRead] = true" Dim strBuilder As StringBuilder = Nothing Dim counter As Integer = 0 Dim mail As Outlook._MailItem = Nothing Dim folderItems As Outlook.Items = Nothing Dim resultItem As Object = Nothing Try If (folder.UnReadItemCount > 0) Then strBuilder = New StringBuilder() folderItems = folder.Items resultItem = folderItems.Find(searchCriteria) While Not IsNothing(resultItem) If (TypeOf (resultItem) Is Outlook._MailItem) Then counter += 1 mail = resultItem strBuilder.AppendLine("#" + counter.ToString() + _ " - Subject: " + mail.Subject) End If Marshal.ReleaseComObject(resultItem) resultItem = folderItems.FindNext() End While If Not IsNothing(strBuilder) Then Debug.WriteLine(strBuilder.ToString()) End If Else Debug.WriteLine("There is no match in the " + _ folder.Name + " folder.") End If Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(folderItems) Then Marshal.ReleaseComObject(folderItems) End If End Try End Sub
C# and VSTO:
using System.Diagnostics; using System.Runtime.InteropServices; // ... private void FindAllUnreadEmails(Outlook.MAPIFolder folder) { string searchCriteria = "[UnRead] = true"; StringBuilder strBuilder = null; int counter = default(int); Outlook._MailItem mail = null; Outlook.Items folderItems = null; object resultItem = null; try { if (folder.UnReadItemCount > 0) { strBuilder = new StringBuilder(); folderItems = folder.Items; resultItem = folderItems.Find(searchCriteria); while (resultItem != null) { if (resultItem is Outlook._MailItem) { counter++; mail = resultItem as Outlook._MailItem; strBuilder.AppendLine("#" + counter.ToString() + "\tSubject: " + mail.Subject); } Marshal.ReleaseComObject(resultItem); resultItem = folderItems.FindNext(); } if (strBuilder != null) Debug.WriteLine(strBuilder.ToString()); } else Debug.WriteLine("There is no match in the " + folder.Name + " folder."); } catch (Exception ex) { System.Windows.Forms.MessageBox.Show(ex.Message); } finally { if (folderItems != null) Marshal.ReleaseComObject(folderItems); } }
VB.NET and VSTO:
Imports System.Diagnostics Imports System.Runtime.InteropServices ' ... Private Sub FindAllUnreadEmails(folder As Outlook.MAPIFolder) Dim searchCriteria As String = "[UnRead] = true" Dim strBuilder As StringBuilder = Nothing Dim counter As Integer = 0 Dim mail As Outlook._MailItem = Nothing Dim folderItems As Outlook.Items = Nothing Dim resultItem As Object = Nothing Try If (folder.UnReadItemCount > 0) Then strBuilder = New StringBuilder() folderItems = folder.Items resultItem = folderItems.Find(searchCriteria) While Not IsNothing(resultItem) If (TypeOf (resultItem) Is Outlook._MailItem) Then counter += 1 mail = resultItem strBuilder.AppendLine("#" + counter.ToString() + _ " - Subject: " + mail.Subject) End If Marshal.ReleaseComObject(resultItem) resultItem = folderItems.FindNext() End While If Not IsNothing(strBuilder) Then Debug.WriteLine(strBuilder.ToString()) End If Else Debug.WriteLine("There is no match in the " + _ folder.Name + " folder.") End If Catch ex As Exception System.Windows.Forms.MessageBox.Show(ex.Message) Finally If Not IsNothing(folderItems) Then Marshal.ReleaseComObject(folderItems) End If End Try End Sub
See you on our forums and in the e-mail support!
3 Comments
nice.its help me to save my time.
I dont know if you still maintain this blog but I am trying to make a vb.net 2012 program that will check the outlook email every 2 minutes or so for new messages, go through the senders name, searching only for approved senders, parse those emails with very simple formats (A name, A number, A message), put the number and message into a textbox, delete the email, and then repeat as new approved messages come up. Another hurdle I foresee in this program: I have set it up as a SDI rather than MDI so there may need to be two of these programs running at the same time, will this cause a crash of some kind of both try to search through outlook at the same time? I am a beginner with vb.net and would like a thorough explanation of everything Im doing so I can actually understand what is going on. It seems somewhat simple, but I can not get my head around it quite yet.
Hello Brian,
I would suggest tht you check this blog: Outlook NewMail unleashed: writing a working solution (C#), it describes finding out what emails have been received. The project discussed there is written in C#; you can use any online Csharp to VB.NET convertor. As to the other problem, I don’t think there whould be any problem of this kind but the best approach is to debug this scenario. I don’t think MDI or SDI may influence the issue in any way.