I found a dated solution attempt in this post:
private static object[] BuildProperty(byte[] rawData)
{
using (MemoryStream ms = new MemoryStream())
{
byte[] headerWithoutLength = { 0x01, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x03, 0x00 };
ms.Write(headerWithoutLength, 0, headerWithoutLength.Length);
byte[] lengthBytes = BitConverter.GetBytes((short)(rawData.Length + 4));
ms.WriteByte(lengthBytes[0]);
ms.WriteByte(lengthBytes[1]);
ms.Write(rawData, 0, rawData.Length);
byte[] footer = { 0x06, 0x00, 0x08, 0x00, 0x01, 0x00, 0x00, 0x00, 0x20, 0x00, 0x08, 0x00,
0x07, 0x00, 0x00, 0x00, 0x02, 0x00, 0x04, 0x00 };
ms.Write(footer, 0, footer.Length);
object[] o = new object[] { ms.ToArray() };
return o;
}
}
private static void Create()
{
OutLook.Application outlookObj = new OutLook.Application();
try
{
X509Certificate2 existingCert = new X509Certificate2(@"[path to my certificate].cer");
byte[] result = existingCert.RawData;
OutLook.MAPIFolder fldContacts = (OutLook.MAPIFolder)outlookObj.Session.GetDefaultFolder(OutLook.OlDefaultFolders.olFolderContacts);
OutLook.ContactItem newContact = (OutLook.ContactItem)fldContacts.Items.Add(OutLook.OlItemType.olContactItem);
newContact.FirstName = "Test Name";
newContact.FileAs = "Test Name";
object[] o = BuildProperty(result);
newContact.PropertyAccessor.SetProperty("http://schemas.microsoft.com/mapi/proptag/0x3A701102", o);
newContact.Save();
}
finally
{
Marshal.ReleaseComObject(outlookObj);
}
}
It creates a new contact and assigns a certificate to it.
To assign a certificate to an existing contact should be similar.
Additional error checking is required to make this snippet useful and trustworthy.