Pieter van der Westhuizen

How to create and modify Outlook-specific files

Microsoft Outlook produces and uses a variety of file types. The most common and well known fields are either .pst or .ost files. These two file types are known as Outlook Data Files, the .pst file is known as the Personal Outlook Data file and stores you messages and other Outlook items. PST files are commonly used for either POP3 or IMAP accounts whereas .ost or Offline Outlook Data Files are used when connecting Outlook to a Microsoft Exchange Server account.

Other files formats produced by Outlook include:

File Type Description
.msg Contains information about a saved Outlook e-mail message
.ics Contains information about calendar entries and meeting requests
.vcf vCard format, contains contact name and address information
.nk2 Used by Outlook to store autocomplete email addresses

Adding and removing an Outlook Store (.pst)

Adding a .pst file to Outlook is easily done using the AddStore method of the Outlook Namespace object. Removing the store takes some more work, because the Namespace object’s RemoveStore method expects an Outlook Folder object as parameter. In the following code, we create a new Outlook Store, add it to Outlook and then remove it again. Removing it, does not physically delete the .pst file from the file system.

private void addRemovePSTRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook.NameSpace ns = null;
    Outlook.Stores stores = null;
    Outlook.Folder rootFolder = null;
    string storePath = string.Empty;
 
    try
    {
        storePath = @"C:\Temp\NewStore.pst";
        ns = this.OutlookApp.Session;
        ns.AddStore(storePath);
        stores = ns.Stores;
        for (int i = 1; i <= stores.Count; i++)
        {
            Outlook.Store currStore = stores[i];
            if (currStore.FilePath == storePath)
            {
                if (MessageBox.Show(
                  "Remove newly added Store?", "Confirm", 
                  MessageBoxButtons.YesNo) == DialogResult.Yes)
                {
                    rootFolder = (Outlook.Folder)currStore.GetRootFolder();
                    ns.RemoveStore(rootFolder);
                }
            }
            if (currStore != null) Marshal.ReleaseComObject(currStore);
        }
    }
    finally
    {
        if (ns != null) Marshal.ReleaseComObject(ns);
        if (stores != null) Marshal.ReleaseComObject(stores);
        if (rootFolder != null) Marshal.ReleaseComObject(rootFolder);
    }
}

Creating and opening an .msg file

The easiest way to create an .msg file is to use the Outlook COM interop assemblies or by creating an add-in using Add-in Express. We’ll look at the last mentioned option. After creating a new ADX COM Add-in and finishing the New Microsoft Office COM Add-in project wizard, open the AddinModule design surface and add a new ADXRibbonTab component to it.

Add a new Ribbon Tab component to the Add-in module.

Next, add a ribbon group with two ribbon buttons to the newly added Outlook ribbon tab. The final design should resemble the following image:

The final design of the custom Outlook ribbon tab

Set the ribbon tab’s Ribbons property to OutlookExplorer and add the following code to the “Create Email and save to MSG" button’s OnClick event handler:

private void saveToMSGRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook._MailItem newMail = null;
 
    try
    {
        newMail = 
            (Outlook._MailItem)this.OutlookApp.CreateItem(Outlook.OlItemType.olMailItem);
        newMail.Subject = "Lorem Ipsum";
        newMail.HTMLBody = "<h1>Hello World</h1><br/> This is the email body";
        newMail.SaveAs(@"C:\Temp\SaveMessage.msg", Outlook.OlSaveAsType.olMSG);
    }
    finally
    {
        if (newMail != null) Marshal.ReleaseComObject(newMail);
    }
}

The code above will create a new Outlook mail message and save it as an .msg file.

Opening an .msg file

Next, we’ll add code to open the .msg file we’ve just created. Add the following code to the “Open Saved MSG” button’s OnClick event handler:

private void openMSGRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook._NameSpace ns = null;
    Outlook._MailItem mailMessage = null;
 
    try
    {
        ns = this.OutlookApp.Session;
        mailMessage = (Outlook._MailItem)ns.OpenSharedItem(@"C:\Temp\SaveMessage.msg");
        mailMessage.Display();
    }
    finally
    {
        if (ns != null) Marshal.ReleaseComObject(ns);
        if (mailMessage != null) Marshal.ReleaseComObject(mailMessage);
    }
}

The above code will use the OpenSharedItem method of the Namespace object to load the .msg file and display it. When clicking the button it should show the saved e-mail message.

The saved e-mail message is displayed in Outlook 2013.

Working with .ics files

Creating an .ics file

Creating an .ics file using the Outlook object model is similar to creating an .msg file. We’ll add two additional buttons to the ribbon tab created previously.

Add two additional buttons to the ribbon tab created previously.

Add the following code to the “Create Appointment and save to ICS” button’s OnClick event handler:

private void saveToICSRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook._AppointmentItem newAppointment = null;
    try
    {
        newAppointment = 
(Outlook._AppointmentItem)this.OutlookApp.CreateItem(Outlook.OlItemType.olAppointmentItem);
        newAppointment.Start = DateTime.Now;
        newAppointment.End = DateTime.Now.AddHours(1);
        newAppointment.Subject = "New Appointment";
        newAppointment.Location = "ADX HQ";
        newAppointment.Body = "Appointment Body";
        newAppointment.SaveAs(
            @"C:\Temp\SavedAppointment.ics", Outlook.OlSaveAsType.olICal);
    }
    finally
    {
        if (newAppointment != null) Marshal.ReleaseComObject(newAppointment);
    }
}

The above code works in a similar fashion as creating an .msg file. You will notice that we passed an additional parameter to the SaveAs method that specified the type of file we’re saving.

Opening an .ics file

To open and display an .ics file we’ll also use the OpenSharedItem method of the Namespace object. In the OnClick event handler for the “Open Saved ICS” button, add the following code:

private void openICSRibbonButton_OnClick(object sender, 
IRibbonControl control, bool pressed)
{
    Outlook._NameSpace ns = null;
    Outlook._AppointmentItem appointment = null;
 
    try
    {
        ns = this.OutlookApp.Session;
        appointment = 
            (Outlook._AppointmentItem)ns.OpenSharedItem(@"C:\Temp\SavedAppointment.ics");
        appointment.Display();
    }
    finally
    {
        if (ns != null) Marshal.ReleaseComObject(ns);
        if (appointment != null) Marshal.ReleaseComObject(appointment);
    }
}

This will display the saved .ics file, as illustrated below:

The saved appointment is displayed in Outlook 2013.

Creating an .ics file using the DDay library

You can create .ics files without using the Outlook object model by using the DDay C# library. The following code will create an .ics file and save it to the disk:

static void CreateICS()
{
    var iCal = new iCalendar();
    var evnt = iCal.Create();
    evnt.Start = iCalDateTime.Today.AddHours(1);
    evnt.End = evnt.Start.AddHours(2);
    evnt.Description = "A C# created event";
    evnt.Location = "ADX HQ";
    evnt.Summary = "An event created with the DDay library.";
 
    ISerializationContext context = new SerializationContext();
    ISerializerFactory factory =
        new DDay.iCal.Serialization.iCalendar.SerializerFactory();
    var serializer = factory.Build(iCal.GetType(), context) as IStringSerializer;
 
    var output = serializer.SerializeToString(iCal);
    var bytes = Encoding.UTF8.GetBytes(output);
 
    var fileStream = new System.IO.FileStream(
        @"C:\Temp\DDayEvent.ics", System.IO.FileMode.Create, System.IO.FileAccess.Write);
    fileStream.Write(bytes, 0, bytes.Length);
    fileStream.Close();
}

Reading an .ics file using the DDay library

The DDay library also makes it easy to read event information from .ics files without using the Outlook object model when utilizing the following code:

static void ReadICS()
{
    IICalendarCollection calendarCollection = 
        iCalendar.LoadFromFile(@"C:\Temp\DDayEvent.ics");
    IICalendar cal = calendarCollection[0];
 
    foreach (var evnt in cal.Events)
    {
        System.Console.WriteLine("Event Start: " + evnt.Start);
        System.Console.WriteLine("Event End: " + evnt.End);
        System.Console.WriteLine("Event Location: " + evnt.Location);
        System.Console.WriteLine("Event Description: " + evnt.Description);
        System.Console.WriteLine("Event Summary: " + evnt.Summary);
    }
    System.Console.Read();
}

Working with .vcf/vCard files

Creating an .vcf/vCard file

Creating a vCard for using the Outlook object model is similar to the way we’ve created the iCal and Msg files. In this case, we’ll set the Type parameter of the SaveAs method to Outlook.OlSaveAsType.olVCard, as detailed below:

private void saveToVcfRibbonButton_OnClick(object sender, 
IRibbonControl control, bool pressed)
{
    Outlook._ContactItem newContact = null;
    try
    {
        newContact = (Outlook._ContactItem)this.OutlookApp.CreateItem(Outlook.OlItemType.olContactItem);
        newContact.FirstName = "George";
        newContact.LastName = "Smith";
        newContact.CompanyName = "G. Smith Accounting";
        newContact.Email1Address = "george@gsmithacc.com";
        newContact.BusinessTelephoneNumber = "555-12345";
        newContact.SaveAs(@"C:\Temp\SavedContact.vcf", Outlook.OlSaveAsType.olVCard);
    }
    finally
    {
        if (newContact != null) Marshal.ReleaseComObject(newContact);
    }
}

Reading an .vcf/vCard file

Reading and displaying a .vcf/vCard file is also achieved by using the OpenShareItem method as illustrated below:

private void openVcfRibbonButton_OnClick(object sender, 
    IRibbonControl control, bool pressed)
{
    Outlook._NameSpace ns = null;
    Outlook._ContactItem contact = null;
 
    try
    {
        ns = this.OutlookApp.Session;
        contact = (Outlook._ContactItem)ns.OpenSharedItem(@"C:\Temp\SavedContact.vcf");
        contact.Display();
    }
    finally
    {
        if (ns != null) Marshal.ReleaseComObject(ns);
        if (contact != null) Marshal.ReleaseComObject(contact);
    }
}

Creating and reading vCard/.vcf files using C#

The vCard format is actually very straight forward and simple to create. When you open the vCard we’ve created earlier, you’ll notice that it has a flat structure:

BEGIN:VCARD
VERSION:2.1
N;LANGUAGE=en-us:Smith;George
FN:George Smith
ORG:G. Smith Accounting
TEL;WORK;VOICE:555-12345
X-MS-OL-DEFAULT-POSTAL-ADDRESS:0
EMAIL;PREF;INTERNET:george@gsmithacc.com
END:VCARD

Using C# you would only need to create a simple flat text file and save the contact information in the above mentioned format.

Reading a vCard file can also be achieved by simply reading the text file line-by-line and parsing the data or you can use the open source class available on CodeProject.

Using this class, we can easily open the vCard file and parse its contents as illustrated below:

static void ReadvCard()
{
    string vcardContent = File.ReadAllText(@"C:\Temp\SavedContact.vcf");
    vCardReader reader =  new vCardReader();
    reader.ParseLines(vcardContent);
    System.Console.WriteLine("Name:" + reader.FormattedName);
    System.Console.WriteLine("Company:" + reader.Org);
    for (int i = 0; i < reader.Emails.Length; i++)
    {
        System.Console.WriteLine("E-mail: " + reader.Emails[i].address);
    }
    for (int i = 0; i < reader.Phones.Length; i++)
    {
        System.Console.WriteLine("Phone: " + reader.Phones[i].number);
    }
}

Thank you for reading. Until next time, keep coding!

Available downloads:

This sample Outlook add-in was developed using Add-in Express for Office and .net:
Create Outlook Files add-in (C#)

You may also be interested in:

6 Comments

  • Manoj says:

    Nice article!!Is it possible to convert an ics(icalendar format) file to a DataSet in c#?

  • Pieter van der Westhuizen says:

    Hi Manoj,

    It should not be too difficult to accomplish. Have a look at this StackOverflow question discussing parsers for ics files.

    Hope this helps. Good luck!

  • Pie says:

    Hello, about the .msg file extension, is it possible to add custom properties to it? If I add custom properties to a MailItem instance, save it in msg format, get back a MailItem instance from the .msg file and than go to read its custom properties all values are NULL!!!
    Thanks!

  • Pieter van der Westhuizen says:

    Hi Pie,

    Unfortunately, it is not possible to do that.

  • Francisco says:

    I was wondering if it is possible to check what type of data file is set by default. On new account I’ve noticed that the extension is OST but if I a datafile is it created as PST, is there a way to know if Outlook is using an OST or PST file?

  • Andrei Smolin (Add-in Express Team) says:

    Hello Francisco,

    See the Store.ExchangeStoreType property; https://docs.microsoft.com/en-us/office/vba/api/outlook.store.exchangestoretype. Also, you may want to use Store.IsDataFileStore and, probable Store.IsCachedExchange.

Post a comment

Have any questions? Ask us right now!