Pieter van der Westhuizen

Working with custom Outlook properties: C# code examples

Microsoft Outlook provides a rich interface for developers to add their own custom properties to Outlook Folders and Items. The Outlook Object model provides two objects when working with custom properties:

  • Outlook.UserDefinedProperties
  • Outlook.UserProperties

At first glance these two objects might appear to be the same thing, but the UserDefinedProperties are used to add custom properties to Outlook folders and the UserProperties are used to add custom properties to Outlook items, such as Contacts, Mails and Appointments.

The UserDefinedProperties collection object was introduced in Outlook 2007 that addresses and included an important feature to make the lives of Outlook developers easier. User properties need to be defined on both the item and folder level. The Add method of the UserProperties object contains an optional Boolean parameter called AddToFolderFields. If you set this parameter to True, your custom property will automatically be created on the item as well as in the folder.

It is important that the custom property is also created in the folder, because if it is not created in the folder you won’t be able to use it in Outlook queries when searching data.

In this article, we’ll write an Outlook add-in that will enable a user to view, add, edit and delete custom properties of an e-mail in Outlook. We’ll also add functionality to send the properties as an attachment via an e-mail to another user and display it inside their Outlook.

Creating the Outlook COM add-in project

Start by creating a new ADX COM Add-in project in Visual Studio using Add-in Express for Office and .net.

Creating the Outlook COM add-in project in Visual Studio 2013

Next, select your programming language of choice (C#, VB.NET or C++.NET) and the minimum version of Office that your add-in needs to support.

Selecting your programming language of choice and the minimum version of Office

Finally, select Microsoft Outlook from the list of supported applications:

Selecting Microsoft Outlook from the list of supported applications

Adding and designing the Outlook add-in’s user interface

We’ll use an Advanced Outlook Form to display the e-mail item’s properties and expose the functionality to add, edit and delete the user properties. To do this, we first need to add a new ADX Outlook Form item to the add-in project.

Adding a new ADX Outlook Form item to the add-in project

The design of our custom Outlook form will resemble the following image:

The design of the custom Outlook form

The UI primarily consists of a ListView, which will be used to display the user properties of the mail item, 3 buttons to add, edit or delete the properties. We’ll also add a panel with two text boxes and a save button which will be displayed when the user either adds or edits a user property.

Next, switch back to the AddinModule.cs designer surface and add a new ADXOlFormsManager component by clicking on its button in the designer toolbar.

Adding a new ADXOlFormsManager component

Add a new item to the newly added ADXOlFormsManager component and set the following properties:

  • AlwaysShowHeader: True
  • FormClassName: CustomOutlookProperties.frmCustomProperties (this is the name of the ADX Outlook Form we’ve added earlier)
  • InspectorItemTypes: Mail
  • InspectorLayout: RightSubpane
  • InspectorMode: Read;Compose

That should take care of showing the Advanced Outlook Form in the Outlook Mail Inspector window.

Display, add, edit and delete user properties

Open the Advanced Outlook Form we’ve added earlier and create an event handler for its ADXAfterFormShow event, which will contain the following code:

private void frmCustomProperties_ADXAfterFormShow()
{
    LoadAttachment();
    ShowProperties();
}

The LoadAttachment method will check whether the e-mail has an attachment called userproperties.xml. If it finds this specific attachment, it will save it to a folder on the local disk, read which properties should be added to the e-mail item and add them. The code for the LoadAttachment method follows:

private void LoadAttachment()
{
    Outlook.Inspector currInsp = null;
    Outlook.MailItem mail = null;
    Outlook.UserProperties props = null;
    Outlook.Attachments attachments = null;
    string savePath = string.Format("{0}\\OutlookProperties\\userproperties.xml",
        Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData));
 
    try
    {
        currInsp = this.InspectorObj as Outlook.Inspector;
        if (currInsp.CurrentItem is Outlook.MailItem)
        {
            mail = currInsp.CurrentItem as Outlook.MailItem;
            attachments = mail.Attachments;
            if (attachments.Count > 0)
            {
                props = mail.UserProperties;
                for (int i = 1; i <= attachments.Count; i++)
                {
                    Outlook.Attachment attachment = attachments[i];
                    if (attachment.FileName == "userproperties.xml")
                    {
                        attachment.SaveAsFile(savePath);
                        attachment.Delete();
                    }
                    Marshal.ReleaseComObject(attachment);
                }
                LoadProperties(props, savePath);
                mail.Save();
            }
        }
    }
    finally
    {
        if (mail != null) Marshal.ReleaseComObject(mail);
        if (attachments != null) Marshal.ReleaseComObject(attachments);
        if (props != null) Marshal.ReleaseComObject(props);
    }
}

You’ll notice that we call a method inside LoadAttachment, LoadProperties. This method reads the XML file containing the user properties and adds them to the UserProperties collection that is passed to it as a parameter:

private void LoadProperties(Outlook.UserProperties props, string filePath)
{
    XDocument doc = null;
    doc = XDocument.Load(filePath);
    var xmlProperties = doc.Descendants("UserProperty");
    foreach (var xmlProperty in xmlProperties)
    {
        string value = xmlProperty.Value;
        string name = xmlProperty.Attribute("Name").Value;
        Outlook.UserProperty prop = props.Add(
            xmlProperty.Attribute("Name").Value,
            Outlook.OlUserPropertyType.olText,
            true);
        prop.Value = xmlProperty.Value;
        Marshal.ReleaseComObject(prop);
    }
}

ShowProperties in turn, checks the mail item in the active inspector for custom user properties and loads them into the ListView control.

private void ShowProperties()
{
    Outlook.Inspector currInsp = null;
    Outlook.MailItem mail = null;
    Outlook.UserProperties itemProps = null;
 
    try
    {
        lvProps.Items.Clear();
        currInsp = this.InspectorObj as Outlook.Inspector;
        if (currInsp.CurrentItem is Outlook.MailItem)
        {
            mail = (Outlook.MailItem)currInsp.CurrentItem;
            itemProps = mail.UserProperties;
 
            for (int i = 1; i <= itemProps.Count; i++)
            {
                Outlook.UserProperty property = itemProps[i];
                ListViewItem item = new ListViewItem(property.Name);
                ListViewItem.ListViewSubItem subItem = 
                    new ListViewItem.ListViewSubItem(item, property.Value.ToString());
                item.SubItems.Add(subItem);
                lvProps.Items.Add(item);
                Marshal.ReleaseComObject(property);
            }
        }
    }
    finally
    {
        if (itemProps != null) Marshal.ReleaseComObject(itemProps);
        if (mail != null) Marshal.ReleaseComObject(mail);
    }
}

Next, add event handlers for each of the buttons. The Add button’s Click event will look similar to the following:

private void btnAdd_Click(object sender, EventArgs e)
{
    txtPropertyName.Clear();
    txtPropertyValue.Clear();
    txtPropertyName.ReadOnly = false;
    panelAddNew.Visible = true;
}

The code above simply clears any values that might be in the two textboxes and shows the panel. The Edit button’s Click event gets a reference to the selected item in the ListView and shows its values in the two textboxes:

private void btnEdit_Click(object sender, EventArgs e)
{
    var selectedItem = lvProps.SelectedItems[0];
    if (selectedItem != null)
    {
        var valueItem = selectedItem.SubItems[1];
        txtPropertyName.Text = selectedItem.Text;
        txtPropertyName.ReadOnly = true;
        txtPropertyValue.Text = valueItem.Text;
        panelAddNew.Visible = true;
    }
}

The Delete button’s functionality is a bit more involved, as it first gets a reference to the selected item in the ListView, searches for the corresponding user property on the mail item and deletes it:

private void btnDelete_Click(object sender, EventArgs e)
{
    Outlook.Inspector currInsp = null;
    Outlook.MailItem mail = null;
    Outlook.UserProperties itemProps = null;
 
    try
    {
        currInsp = this.InspectorObj as Outlook.Inspector;
        if (currInsp.CurrentItem is Outlook.MailItem)
        {
            mail = (Outlook.MailItem)currInsp.CurrentItem;
            itemProps = mail.UserProperties;
            foreach (var item in lvProps.SelectedItems)
            {
                ListViewItem selectedItem = item as ListViewItem;
                lvProps.Items.Remove(selectedItem);
 
                Outlook.UserProperty prop = itemProps.Find(selectedItem.Text);
                if (prop != null)
                {
                    prop.Delete();
                    Marshal.ReleaseComObject(prop);
                }
            }
            mail.Save();
        }
    }
    finally
    {
        if (itemProps != null) Marshal.ReleaseComObject(itemProps);
        if (mail != null) Marshal.ReleaseComObject(mail);
    }
}

Last in line with the buttons is the Save button. This code tries and finds the user property by name and once found, updates its value with the value in the textbox. If it does not find it, we assume it is a new property and add it to the UserProperties collection of the mail item.

private void btnSave_Click(object sender, EventArgs e)
{
    Outlook.Inspector currInsp = null;
    Outlook.MailItem mail = null;
    Outlook.UserProperties itemProps = null;
    Outlook.UserProperty newProp = null;
 
    try
    {
        currInsp = this.InspectorObj as Outlook.Inspector;
        if (currInsp.CurrentItem is Outlook.MailItem)
        {
            mail = (Outlook.MailItem)currInsp.CurrentItem;
            itemProps = mail.UserProperties;
            newProp = itemProps.Find(txtPropertyName.Text);
            if (newProp != null)
            {
                newProp.Value = txtPropertyValue.Text;
            }
            else
            {
                newProp = itemProps.Add(txtPropertyName.Text,
                    Outlook.OlUserPropertyType.olText, true);
            }
 
            newProp.Value = txtPropertyValue.Text;
            mail.Save();
            panelAddNew.Visible = false;
            ShowProperties();
        }
    }
    finally
    {
        if (newProp != null) Marshal.ReleaseComObject(newProp);
        if (itemProps != null) Marshal.ReleaseComObject(itemProps);
        if (mail != null) Marshal.ReleaseComObject(mail);
    }
}

Attaching custom user properties to an outgoing e-mail

Lastly, we’ll write some code that will save all the user properties of an outgoing e-mail and attach it to the email as an XML file. To do this, switch back to the AddinModule.cs design surface and add a Microsoft Outlook events component.

Adding a Microsoft Outlook events component

Add an event handler for the ItemSend event by double-clicking next to the event name in the list of events for the Microsoft Outlook event component.

Adding an event handler for the ItemSend event

Add the following code to the ItemSend event handler:

private void adxOutlookEvents_ItemSend(object sender, ADXOlItemSendEventArgs e)
{
    Outlook.MailItem mail = null;
    Outlook.Attachments attachments = null;
    Outlook.UserProperties props = null;
 
    try
    {
        if (e.Item is Outlook.MailItem)
        {
            mail = e.Item as Outlook.MailItem;
            props = mail.UserProperties;
            attachments = mail.Attachments;
            if (props.Count > 0)
            {
                string attachmentPath = PackageProperties(props);
                attachments.Add(attachmentPath);
            }
        }
    }
    finally
    {
        if (props != null) Marshal.ReleaseComObject(props);
        if (attachments != null) Marshal.ReleaseComObject(attachments);
    }
}

The above code will check whether the outgoing mail item contains any user properties and then package those properties in an XML file and attach the file to the outgoing e-mail. The code in our Advanced Outlook form in turn will read this XML file, add the user properties to the e-mail item and will then display it.

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:

Custom Outlook Properties add-in (C#)

You may also be interested in:

7 Comments

Post a comment

Have any questions? Ask us right now!