Outlook and C# - Gather Addresses

Posted Monday, March 15, 2004 1:49 PM by CumpsD
For this article I decided to work with Outlook from C#.

I get way too much spam, and not only the commercial kind of spam. But also the jokes crap that 'friends' send you with 40 CC's in.

So here's my idea: We'll write an email gatherer. It'll take a folder and will go trough every mail in it, extract email addresses and save them as a comma delimited file.

Where can we find email adresses in a mail? Well, first of all, the sender. That's one already. Then the recipients ofcourse, all those CC addresses. And lastly the mail itself, all those forwards caused the body to have plenty of addresses as well.

Real usage for this tool? Probably nothing, but you learn to work with Outlook from C# and you can have fun with collecting things, email addresses in this case.

Let's begin. All of this is in a Console App called GatherAddresses.

First we need a reference to Outlook. So add a reference to 'Microsoft Outlook 11.0 Object Library' (or 10.0, if you use 10.0 leave a comment if this source worked for you!)



When you did this you'll have two new reference, just remove the Office Core... so that you have something like this:



Our application has a very simple logic, where the Main controls it all.

using System;

using System.Text.RegularExpressions;

using System.Collections;

using System.IO;

using Outlook = Microsoft.Office.Interop.Outlook;

 

namespace GatherAddresses {

      class GatherAddresses {

            static void Main(string[] args) {

                  // TODO

            }

      } /* GatherAddresses */

} /* GatherAddresses */


Our goal is to collect all addresses, and we don't know how many there will be, so we store them in an ArrayList.

private static ArrayList emailCollection = new ArrayList();


First we ask for a folder. This folder is in the form of a path. Starting from Outlook Today (the root in Outlook) to the folder you want. Example: CumpsD\Inbox would give you my Inbox.

Console.Write("Path to mailfolder: ");

string mailFolder = Console.ReadLine();


Now we create our Outlook 'connection'.

Outlook._Application appOutlook = new Outlook.Application();

                       

Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");

olNS.Logon("", null, null, null);


We navigate to the given folder with the GetFolder method, we will write later on in this article. This method will return a MAPIFolder which we need to read the Items from.

Console.WriteLine("Searching Folder...");

Outlook.MAPIFolder olMailFolder = GetFolder(mailFolder);

Outlook.Items olMailItems = olMailFolder.Items;


Next is the real collecting part of our application. We take each MailItem in our folder and save the addresses. To get the addresses from the body we use the GetAddresses method we'll also write later on.

Console.WriteLine("Gathering Addresses...");

foreach(Outlook.MailItem olMail in olMailItems) {

      AddAddress(olMail.SenderEmailAddress);

      foreach(Outlook.Recipient olRecipient in olMail.Recipients) {

            AddAddress(olRecipient.Address);

      }

      string[] emailAddresses = GetAddresses(olMail.Body);

      foreach (string emailAddress in emailAddresses) {

            AddAddress(emailAddress);

      }

}


After we have done everything we wanted with Outlook we close it and throw it away.

 

olNS.Logoff();

     

olMailItems = null;

olMailFolder = null;

olNS = null;

appOutlook = null;


And lastly we save the collected addresses.

Console.WriteLine("Sorting & Outputting Addresses...");

SaveAddresses();


Now onto our private methods:

First the GetFolder method. This will get us our folder we specified with a path.

Again we open Outlook. Then we split the path into the corresponding folders and we look for the root folder.

Outlook._Application appOutlook = new Outlook.Application();

Outlook.NameSpace olNS = appOutlook.GetNamespace("MAPI");

olNS.Logon("", null, null, null);

 

Outlook.MAPIFolder olFolder = null;            

folderPath.Replace("/", @"\");

string[] arrFolders = folderPath.Split('\\');

 

foreach (Outlook.MAPIFolder olTmpFolder in olNS.Folders) {

      if (olTmpFolder.Name == arrFolders[0]) {

            olFolder = olTmpFolder;

            break;

      }

}


When we have found our root folder, we will look for our first folder and when we find it, we replace our parent object by that folder and go looking for the next folder.

if (olFolder != null) {

      for (int i = 1; i < arrFolders.Length; i++) {

            Outlook.Folders olFolders = olFolder.Folders;

            olFolder = null;

                 

            foreach (Outlook.MAPIFolder olTmpFolder in olFolders) {

                  if (olTmpFolder.Name == arrFolders[i]) {

                        olFolder = olTmpFolder;

                        break;

                  }

            }

            olFolders = null;

      }          

}


And in the end we return our found folder after cleaning up.

arrFolders = null;

olNS = null;

appOutlook = null;

return olFolder;


Next is the GetAddresses method. This method has been created by Rob Windsor in VB.NET and posted here. Permission was granted to convert it to C# and use it for this article. Thanks!

This method uses a regular expression to extract the email addresses out of a string after which they are returned as a string array.

// Converted from http://www.codeproject.com/vb/net/extractemail.asp

private static string[] GetAddresses(string bodyText) {

      // Regex expression garnered from www.regexlib.com - thanks guys!

      MatchCollection mcEmail = Regex.Matches(bodyText, @"([a-zA-Z0-9_\-\.]+)@([a-zA-Z0-9_\-\.]+)\.([a-zA-Z]{2,5})");

      string[] emailAddresses = new string[mcEmail.Count];

      for (int i = 0; i < mcEmail.Count; i++) {

            emailAddresses[i] = mcEmail[i].Value;

      }

      return emailAddresses;

} /* GetAddresses */


Adding our addresses is as simple as checking if the ArrayList already Contains it and add it if it doesn't.

private static void AddAddress(string emailAddress) {

      emailAddress = emailAddress.Trim();

      emailAddress = emailAddress.ToLower();

      if (!emailCollection.Contains(emailAddress)) {

            emailCollection.Add(emailAddress);

      }

} /* AddAddress */


And to close this article, the SaveAddresses method asks for a filename to write to and writes the addresses there as a delimited list which you can import in other applications.

private static void SaveAddresses() {

      Console.Write("Path to save to: ");

      string savePath = Console.ReadLine();

      if (savePath != "") {

            emailCollection.Sort();

            using (StreamWriter sw = new StreamWriter(savePath)) {

                  foreach (string emailAddress in emailCollection) {

                        sw.WriteLine(String.Format("{0};", emailAddress));

                  }

            }

      }

} /* SaveAddresses */


I tested this on 29 'fun' mails I received, and guess how many addresses came out of there? 1473!! I imported them in a small Access table to test the saved format ;)

As always, I've uploaded the project for you.
Filed under:

Comments

# re: Outlook and C# - Gather Addresses

Friday, March 26, 2004 6:21 AM by Enrique

Hi, interesting article, thanks.

Only a question, please.
I need access email addresses of an Distribution List, in Public Folders/All Public Folders/COMPANY Contacts/MyDistributionList.

I use Outlook 2003, but I have many problems. Some suggestion ?

Thanks.

Greetings.

ekiquenet@yahoo.es

# re: Outlook and C# - Gather Addresses

Friday, March 26, 2004 8:04 AM by David Cumps

Check this for info on distrubution lists:
http://support.microsoft.com/?kbid=313797

It provides VB.NET code thou

# re: Outlook and C# - Gather Addresses

Wednesday, June 16, 2004 6:05 AM by Dave

I'm not running Office 2003, so I dont have msoutl.olb, can someone email it to me or tell me where I can get it?

van240sx@yahoo.ca

thanks

# re: Outlook and C# - Gather Addresses

Friday, July 09, 2004 7:07 AM by Y a h o o

Hi,
I add reference to 'Microsoft Outlook 11.0 Object Library'
but i didn't get the Interop.Outlook namespace

any help?

# re: Outlook and C# - Gather Addresses

Friday, July 09, 2004 7:12 AM by David Cumps

Did you get any new references? Check the Object Browser for the exact namespace if there are any Office references

# re: Outlook and C# - Gather Addresses

Saturday, July 10, 2004 1:51 PM by Y a h o o

Yes I get 3 new references:
1.microsoft.office.core
2.outlook
3.stdole

# re: Outlook and C# - Gather Addresses

Saturday, July 10, 2004 4:32 PM by Y a h o o

p.s
if you can help me - i need to import data form outlook to dataset
any help?

# re: Outlook and C# - Gather Addresses

Sunday, July 11, 2004 6:49 AM by David Cumps

Well then, press F2 to get the object browser and find the exact namespace for the Interop namespace.

--
You could create a dataset and fill it up with a foreach adding a row each time. It's all the same for emails, contacts, calendar items

# re: Outlook and C# - Gather Addresses

Wednesday, August 04, 2004 1:55 AM by zhuhuafeng

good

# re: Outlook and C# - Gather Addresses

Wednesday, August 04, 2004 2:07 AM by zhuhuafeng

How Open *.pst file ???

# re: Outlook and C# - Gather Addresses

Monday, February 05, 2007 1:49 PM by Chun

Thanks for the article. I have a quick question: if I have both outlook and outlook express running on the machine, how do I tell the program to use outlook express instead of outlook?

Thanks,

Chun

# re: Outlook and C# - Gather Addresses

Monday, February 05, 2007 2:39 PM by CumpsD

Wouldn't you need a reference to some Outlook Express dlls? If those exist.

# re: Outlook and C# - Gather Addresses

Saturday, August 25, 2007 1:22 PM by Gary Prior

Thank you for your article, your work and posting the solution for download. It met a very specific need I had at my work on 8-24-07 and with a few tweaks was able to use it very nicely to gather all email subjects and body text from a specific sender. Thank you!