Click here to Skip to main content
Email Password   helpLost your password?

Introduction

The Microsoft Outlook Connector is written in C# using the .NET 1.1 Framework. It attempts to abstract the data access with Microsoft Outlook and visual components using the data. Data from your Microsoft Outlook application can be exported to an XML file by simply checking the folder options and clicking Export. The source provides a simple example of mapping the COM object properties to a XML-friendly DataSet that could be used in any .NET application.

Background

This component for exporting Outlook objects stemmed from a couple years passively looking for a sync between my database and Outlook. I somehow stumbled on a VBA article on it (http://www.devasp.com/search/res/r9981.html) and decided to make a C# app to do the same.

Using the code

The primary function of the DataExportForm retrieves information from the user's Microsoft Outlook application via a custom connector which translates the Interop COM objects into basic DataSets. We should all be aware of how handy DataSets can be so lets look at how our form gets the information for the datagrid.

private DataSet getCheckedItemSet()
{
    DataSet ds = new DataSet();
    OutlookConnector outlook = new OutlookConnector();

    // setup progress bars and process selected folders

    pgFolderProgress.Value = 0;
    outlook.ItemProcessed += new OutlookItemProcessed(outlook_ItemProcessed);
    pgFolderProgress.Maximum = lstExportObjects.CheckedItems.Count;
    foreach (ListViewItem obj in lstExportObjects.CheckedItems)
    {
        pgFolderProgress.Value++;
        pgItemProgress.Value = 0;

        switch (obj.Index) 
        {
            case 0:
                pgItemProgress.Maximum = outlook.getFolderCount(
                    Outlook.OlDefaultFolders.olFolderCalendar);
                ds.Merge(outlook.getCalendarDataSet());
                break;
            case 1:
                pgItemProgress.Maximum = outlook.getFolderCount(
                    Outlook.OlDefaultFolders.olFolderContacts);
                ds.Merge(outlook.getContactDataSet());
                break;
            case 2:
                pgItemProgress.Maximum = outlook.getFolderCount(
                    Outlook.OlDefaultFolders.olFolderInbox);
                ds.Merge(outlook.getInboxDataSet());
                break;
            case 3:
                pgItemProgress.Maximum = outlook.getFolderCount(
                    Outlook.OlDefaultFolders.olFolderNotes);
                ds.Merge(outlook.getNoteDataSet());
                break;
            case 4:
                pgItemProgress.Maximum = outlook.getFolderCount(
                    Outlook.OlDefaultFolders.olFolderTasks);
                ds.Merge(outlook.getTaskDataSet());
                break;
            default:
                Debug.WriteLine("Unsupported Export: " + obj.Index);
                break;
        }
    }
    outlook.Dispose();
    return ds;
}

Now how exactly does the OutlookConnector get it? You'll have to download the source to see the finer details of handling the Interop connection. Rest assured that it implements the IDisposable interface and works through MAPI to retrieve Outlook folder information. All of the Outlook connectivity is handled on instantiation which makes retrieval pretty easy, as seen here in the OutlookConnector.getContactDataSet() method.

/// <summary>

/// Retrieves a list of all the Outlook Contacts.

/// </summary>

/// <returns>Contact Items DataSet</returns>

public DataSet getContactDataSet()
{
    Outlook.ContactItem item;
    DataSet rv = new DataSet();
    rv.DataSetName = "Contacts";
    rv.Tables.Add("Contact");
    rv.Tables[0].Columns.Add("FirstName");
    rv.Tables[0].Columns.Add("LastName");
    rv.Tables[0].Columns.Add("CompanyName");
    rv.Tables[0].Columns.Add("Email");
    rv.Tables[0].Columns.Add("HomePhone");
    rv.Tables[0].Columns.Add("WorkPhone");

    try
    {
        objFolder = objNamespace.GetDefaultFolder(
            Outlook.OlDefaultFolders.olFolderContacts);
        Debug.WriteLine(objFolder.Items.Count + " Contacts found.");
        foreach (System.Object _item in objFolder.Items) 
        {
            item = (Outlook.ContactItem) _item;
            rv.Tables[0].Rows.Add(new object[] {
                item.FirstName,
                item.LastName,
                item.CompanyName,
                item.Email1Address,
                item.HomeTelephoneNumber,
                item.BusinessTelephoneNumber
            });
            this.ItemProcessed();
        }
        Debug.WriteLine(rv.Tables[0].Rows.Count + " Contacts exported.");
    }
    catch (System.Exception e)
    {
        Console.WriteLine(e);
    }
    return rv;
}

Points of Interest

If your system does not have Microsoft Office Outlook 2003 you may have to change the References used by the "OutlookConnector" project. That is to say, if you received a build error described as "The type of namespace name 'Outlook' could not be found", you probably don't have Office 2003. Simply expand the project references, remove the afflicted items, and add the COM Library appropriate for your system. If someone has a dynamic way to handle this, I'd be curious to see you've done.

History

I wanted to limit this project to a single evening so it currently uses untyped DataSets. The real advantage of this application would come from using strong types and hooking in some DataAdapter(s) to really try to sync with some other system. I will probably end up tying in a MySQL data adapter in the coming weeks as time permits but if someone starts/finishes before I get to it, please let me know.

Version 1.1

Connector looping was switched to an incrementing localized integer since Office 10 does not implement a GetEnumerator() method. We have to use our own counter in a for loop instead. Also, here are some details on fixing your References between Office versions.

You must Sign In to use this message board.
 
 
Per page   
 FirstPrevNext
GeneralI tried to execute this code, it is giving an error "does not contain a definition for 'SenderEmailAddress'"
Member 3979793
20:29 24 Jun '09  
Error Description:
CS0117: 'Microsoft.Office.Interop.Outlook.MailItem' does not contain a definition for 'SenderEmailAddress'

Dipak

QuestionMicrosoft.Outlook11 missing
disire
23:21 8 Dec '08  
Hi ,This is a great article!
But I can't find Microsoft.Outlook11 in my COM Components list.
"Namespace Microsoft.Office.Interop is not exist"
Do you have any advice that will help me ?
QuestionHow can we do this in Asp.Net
SKP24
5:13 25 Mar '08  
Hi
Can You please tell me how to do the same in Asp.Net.
I am using Asp.Net 2.0 with C# and MS Outlook 2007.

Sagar Pattnayak
Software Developer
Sun-Dew Solutions
+91-9831169962

Generalconvert "X.400/X.500 e-mail adress" into "Smtp e-mail adress"
jackyontherock
6:11 10 Aug '07  
Hello,

I am still searching for a method which can convert
the X.400 / X.500 e-mail adress into "smtp e-mail adress".

Is it possible to show the e-mail adress in smtp-Format.

I was not able to find in the net a good solution.

Is there a method for C# existing.

It would be great if someone can help me.

Thanks alot...

Smile


GeneralExtracting/Importing [modified]
ClaudeX
23:57 6 Jun '07  
Any idea how to extract those free timing from microsoft outlook calendar (those timing that is without appointment) using visual basic or C#?

Btw...can it be done without using Microsoft Exchange Server?

Please Help...
Thanks in advance

Best Regards,
ClaudeX


-- modified at 5:31 Thursday 7th June, 2007
GeneralOutlook Namespace missing
MarkChimes2
14:17 2 Feb '07  
Hi Mathias,

This is a great article and I am keen to implement your OutlookCOnnector in my applications.

I have added references to both Microsoft.Office11 and Microsoft.Outlook11 into your code and I am still getting the "Namespace Outlook could not be found" error.

Do you have any further advice that will help me with this?


cheers,
Mark Chimes
GeneralRe: Outlook Namespace missing
MarkChimes2
14:53 2 Feb '07  
Hi All,

I solved this issue by place "Microsoft.Office.Interop." in front of every reference to "Outlook".

I guess this means my solution is not reading the added references properly, butat least it works this way.


cheers,
Mark Chimes
GeneralExisting Outlook window closes !
ccangaroo
4:29 24 Aug '06  
I don't want any existing Outlook window to close after program execution, so i deleted the line:
if (objOutlook != null) objOutlook.Quit();
New problem:
tried exporting my contacts 3 times in a row
first time: all 137 contacts exported
second time: something between 4 and 124 contacts exported
third time: always 0 contacts exported
tried to open outlook -> error message, couldn't open my inbox anymore
had to kill outlook.exe in the task manager to make it work properly again.

so my question is:
isn't it possible to check for an existing outlook instance, and use this one instead of creating a new one ?

Any ideas ?

GeneralA bug
nadav74
10:38 1 Jul '06  
Hi,

While trying this code I encountered into a bug. The following code in OutlookConnector.cs, method getCalendarDataSet:
for (int i=0; i < objFolder.Items.Count; i++)
{
item = (Outlook.AppointmentItem) objFolder.Items.GetNext();
rv.Tables[0].Rows.Add(new object[] {
item.Subject,
item.Location,
item.Start,
item.End,
item.AllDayEvent,
item.Duration,
item.Organizer,
item.Importance,
item.Sensitivity,
item.Body
});
this.ItemProcessed();
}

should be replaced with:
foreach (Outlook.AppointmentItem item in objFolder.Items)
{
rv.Tables[0].Rows.Add(new object[] {
item.Subject,
item.Location,
item.Start,
item.End,
item.AllDayEvent,
item.Duration,
item.Organizer,
item.Importance,
item.Sensitivity,
item.Body
});
this.ItemProcessed();
}
and the definition of item earlier in this method should also be removed.

Cheers, Nadav

GeneralRe: A bug [modified]
robocato
2:19 31 Aug '06  
also 4 contacts imo

/*for (int i=0; i < objFolder.Items.Count; i++)
{
item = (Outlook.ContactItem) objFolder.Items.GetNext();
rv.Tables[0].Rows.Add(new object[] {
item.FirstName,
item.LastName,
item.CompanyName,
item.Email1Address,
item.HomeTelephoneNumber,
item.BusinessTelephoneNumber
});
this.ItemProcessed();
}*/




foreach (Outlook.ContactItem item1 in objFolder.Items)
{
rv.Tables[0].Rows.Add(new object[] {
item1.FirstName,
item1.LastName,
item1.CompanyName,
item1.Email1Address,
item1.HomeTelephoneNumber,
item1.BusinessTelephoneNumber
});
this.ItemProcessed();
}

old one return one value.. you should remove this one and repeate to my modification

my modification gives correct values

you should also correct other functions


-- modified at 7:27 Thursday 31st August, 2006
GeneralPlease Help
Ashisvadada
18:36 14 Jun '06  
Hiya,

I am a bit Novice user here. i am trying to export data from a perticular folder from outlook to an access database or a sql server. Is it possible with this code. If yes i am not able to get my head around it. Can anybody help me.

Thanks

Ash
GeneralProblem ???
Pascal Groulx
13:06 16 May '06  
Hi,

I'm writing a similar application that retrieves contacts and appointments from a database to create them in Outlook 2003.

On some machine, I got an error of COMException when I try to retrieve the folder with the method GetDefaultFolder(OlDefaultFolders);

Example of code :
objNamespace.GetDefaultFolder(OlDefaultFolders.olContacts);

I would like to know if you had experiment this kind of problem with your application and how to solve this.

Thanks
GeneralgoUsing this code with Exchange
DeborahK
10:18 28 Mar '06  
I am using Outlook similar to your example, but pulling in shared folders from Exchange. It is all working except that I cannot cast Items.Item to Contact.Item. I instead need to keep them as Object - which then uses late binding.

Since I am processing over 500,000 entries, I would like the performance boost of early binding.

Any ideas why Exchange won't allow the cast?

(I am also using the exact same code with the default Outlook folder and there the cast works fine. Just not with any shared folders.)
Thanks!
GeneralDrag & Drop outlook contacts
NewbieDude
21:22 16 Mar '06  
hey howzit?

its easy to import contacts from outlook in code...but what i wanna do is be able to drag an outlook contact straight from the running Outlook Application itself into my running C# application...can anyone help?

So far I am able to drop random files into a listbox using this tutorial: http://www.csharphelp.com/archives2/archive365.html but its still doesn't provide me will the ability described above


GeneralProblem
pro_86
12:59 18 Feb '06  
Hi,

When I run the Outlook Connector and I want to export the appointments, I became always one appointment.

Where is the failure?

Greetz
GeneralHow about processing any PST?
Matt Philmon
7:35 14 Feb '06  
Could this be modified to access any PST? I output PST files from kvs enterprise vault but then want to read each PST and parse out the data I need.
GeneralBUG inside OutlookItemBuilder class and resolution.
Preky
22:51 6 Jul '05  
While I was debbuging I found to an ineresting bug and exception that is swolen inside the code Smile

In class methods eg. LoadInboxItems and others where you are going to get next, at the last item objItems.GetNext() returns null value. The result is exception that is written to Console so without carefull looking it wanish and possibly won't be seen Smile

So the resolution is to modify code like this (in all methods working with GetNext() method of Outlook.Items collection of course):



outlookItem = objItems.GetNext();
if (outlookItem ==null)
break;

P.S.
It is wise to show Exception message to the user in such cases, or throw some custom message or handle it in some way that would be obvious to the user or fellow programer.

P.S.S Great work tough!!! Thx for the code!

Preky
GeneralAlways return 1 item
sksandz
2:08 8 Apr '05  
When i try to run the code it is count the number of calendar items as 2 and contacts as 5 etc(and these figures are correct). But when the data is exported to xml both the items are same. That means under contacts there are 5 items but all the 5 are the same record. ie. the first record. Why is this happening like this. Also i did an iteration through the code runtime and i am storing subject and body in a temp variables. But those values are always having the same values (the 1st record). Can anybody tell me what is the change to be made to read record by record in contacts or calendar. Please helpD'Oh! .

for (int i=0; i < objFolder.Items.Count; i++)
{
item = (Outlook.AppointmentItem) objFolder.Items.GetNext();
string sub = item.Subject;
string bd = item.Body;
rv.Tables[0].Rows.Add(new object[] {
item.Subject,
item.Location,
item.Start,
item.Body
});
this.ItemProcessed();
}
GeneralRe: Always return 1 item
CtrAltDel
11:22 30 Apr '05  
I ran into the same problem and changed the code to make it work. Alternately, try getting version 1.0. In the release notes 1.1 he said he stopped using the the Enumerator and changed it to a for loop for compatibility with office 10. However, I think that broke the program for Office 11 (2003) as the GetNext() method on the Items collection doesn't seem to work properly, I kept getting the same item repeated over and over.
This is what I did to get 1.1 to work. It worked for me but YMMV and all the usual disclaimers. Get rid of the For loop in the get*DataSet methods and make them while loops with the IEnumerator like this (this is for the OutlookConnector.GetInboxData() method)
System.Collections.IEnumerator MsgEnum = objFolder.Items.GetEnumerator();
while (MsgEnum.MoveNext())
{
item = (Outlook.MailItem) MsgEnum.Current;
rv.Tables[0].Rows.Add(new object[] { item.SenderName,
item.To,
item.CC,
item.Subject,
item.ReceivedTime,
item.Body
});
this.ItemProcessed();
}

GeneralRe: Always return 1 item
eyop@eyop.co.kr
23:09 14 Sep '05  
It changed the code bold line

for (int i=1; i <= objFolder.Items.Count; i++)
{

item = (Outlook.MailItem) objFolder.Items.Item(i);
rv.Tables[0].Rows.Add(new object[] {
item.SenderName,
item.To,
item.CC,
item.Subject,
item.ReceivedTime,
item.Body
});

this.ItemProcessed();
}
GeneralRe: Always return 1 item
Member 3306402
7:58 1 Jan '08  
The code as written returns the same first item each time.

The reason is that every time GetNext is called
the code retrieves a new instance of the Items object.

Solution: Store the Items object in a local variable to make sure you are always using the same
instance

new code

objFolder = objNamespace.GetDefaultFolder(Outlook.OlDefaultFolders.olFolderInbox);

Outlook.Items Items= objFolder.Items;
item = (Outlook.MailItem) Items.GetFirst();
while (null != item)
{
item = (Outlook.MailItem)Items.GetNext();

rv.Tables[0].Rows.Add(new object[] {
item.SenderName,
item.To,
item.CC,
item.Subject,
item.ReceivedTime,
item.Body
});

this.ItemProcessed();
}

RDerby
GeneralNullReferenceException when running the code
pvsunil
1:32 8 Apr '05  
I tried to execute the getting calendar items and contracts items from the code and i am always getting only the first record. In debug mode i have inserted a a string variable to get the exception and the exception you can see in this screenshot.Frown http://www.guidant-cor.com/tempfiles/exceptionscreen.jpg
Can anybody help me with this. Please reply as when is the cause of the error.
Generalexporting e-mails of additional mailbox
MagicGirL83
17:24 30 Mar '05  
how can i extract the e-mails of an additional profile setup on ms outlook? any idea?
Generaldisplay the exported e-mails on a web page
MagicGirL83
14:38 30 Mar '05  
hi.. i'm fairly new with the .net technology. can i display the exports on a web page using asp.net? is it also possible to "parse" the subject and when it found a "CRITICAL" string, i would have to color code the whole row with red, and if "WARNING" yellow? any idea? thanks
GeneralMS Outlook FAXMaker
Fayeeg
0:41 2 Feb '05  

Could you please help to send fax from my C# application
through FaxMaker for Exchange ( NO SMTP )?

Thanks in advance.

Best Regards,
Fayeez


Last Updated 20 Feb 2004 | Advertise | Privacy | Terms of Use | Copyright © CodeProject, 1999-2010