Working with vCard (VCF) Files in C#

This article covers the VCardContact class from the Aspose.Email.PersonalInfo.VCard namespace, which reads and writes vCard (VCF) files independently of Outlook and MAPI. To create and manage Outlook MapiContact items — which can also be exported to VCF — see Outlook Contacts Management.

VCardContact vs MapiContact

Aspose.Email exposes contacts through two different classes, and choosing the right one avoids a lot of confusion:

  • VCardContact (namespace Aspose.Email.PersonalInfo.VCard) — a pure vCard object. Use it when your source and target are vCard (VCF) files and you do not need Outlook/MAPI features. It reads and writes VCF directly, supports vCard 2.1/3.0/4.0, multiple contacts per file, and asynchronous loading.
  • MapiContact (namespace Aspose.Email.Mapi) — an Outlook contact. Use it when you work with MSG/PST or need MAPI-specific properties. MapiContact can also import from and export to VCF via its FromVCard and Save methods (see Outlook Contacts Management).

The rest of this article focuses on VCardContact.

Create a vCard and Save It

The VCardContact class has a parameterless constructor and exposes strongly-typed property sets such as IdentificationInfo, Organization, Emails, TelephoneNumbers, and DeliveryAddresses.

The following code snippet shows you how to build a contact from scratch and save it as a vCard (VCF) file.

using Aspose.Email.PersonalInfo.VCard;

var contact = new VCardContact
{
    IdentificationInfo = new VCardIdentificationInfo
    {
        DisplayName = "Bertha Buell",
        FullName = "Bertha A. Buell",
        Nickname = "Bertie",
        Birthday = new DateTime(1980, 5, 20)
    },
    Organization = new VCardOrganization
    {
        Organization = "Awthentikz",
        Title = "Social work assistant"
    },
    Emails = new VCardEmailCollection
    {
        new VCardEmail
        {
            EmailAddress = "BerthaABuell@example.com",
            EmailType = VCardEmailType.INTERNET
        }
    }
};

// Save as a vCard (VCF) file
contact.Save("contact.vcf");

The Contact Property Model

Beyond the name and email shown above, a VCardContact exposes the full vCard data model through strongly-typed property sets. The snippets below extend the contact created earlier. Each collection can be assigned with a collection initializer or appended to with Add.

Postal Addresses

Postal addresses live in the DeliveryAddresses collection as VCardDeliveryAddress items. The AddressType property takes a combination of VCardDeliveryAddressType flags (HOME, WORK, POSTAL, PARCEL, DOM, INTL, PREF).

contact.DeliveryAddresses = new VCardDeliveryAddressCollection
{
    new VCardDeliveryAddress
    {
        AddressType = VCardDeliveryAddressType.WORK | VCardDeliveryAddressType.PREF,
        Street = "4 Darwinia Loop",
        Locality = "Eighty Mile Beach",
        Region = "WA",
        PostalCode = "6725",
        CountryName = "Australia"
    }
};

Telephone Numbers

Phone numbers live in the TelephoneNumbers collection as VCardTelephoneNumber items. The TelephoneType property takes a combination of VCardTelephoneType flags (VOICE, WORK, HOME, CELL, FAX, PAGER, PREF, and more).

contact.TelephoneNumbers = new VCardTelephoneNumberCollection
{
    new VCardTelephoneNumber
    {
        TelephoneNumber = "(08) 9080 1183",
        TelephoneType = VCardTelephoneType.WORK | VCardTelephoneType.VOICE
    },
    new VCardTelephoneNumber
    {
        TelephoneNumber = "(925) 599 3355",
        TelephoneType = VCardTelephoneType.CELL
    }
};

Geographic Position

The Geo property stores a global position as float latitude and longitude.

contact.Geo = new VCardGeo
{
    Latitude = 48.858844f,
    Longitude = 2.294351f
};

Photo

A contact photo is set on IdentificationInfo.Photo as a VCardPhoto. It can be embedded inline from image bytes or referenced by URL. The image format is given by VCardPhotoType and the storage mode by VCardValueLocation.

// Embed the image bytes inline
contact.IdentificationInfo.Photo = new VCardPhoto
{
    Data = File.ReadAllBytes("portrait.jpg"),
    PhotoType = VCardPhotoType.JPEG,
    ValueLocation = VCardValueLocation.INLINE
};

// Or reference an external image by URL
contact.IdentificationInfo.Photo = new VCardPhoto
{
    Uri = "https://example.com/portrait.jpg",
    PhotoType = VCardPhotoType.JPEG,
    ValueLocation = VCardValueLocation.URL
};

Formatted Address Labels

A label is the formatted, ready-to-print text of a delivery address. Labels live in the Labels collection as VCardLabel items, each tagged with an address type.

contact.Labels = new VCardLabelCollection
{
    new VCardLabel
    {
        AddressType = VCardDeliveryAddressType.WORK,
        Address = "4 Darwinia Loop\r\nEighty Mile Beach WA 6725\r\nAustralia"
    }
};

Read the Model Back

After loading a vCard, the same property sets expose the parsed data.

var loaded = VCardContact.Load("contact.vcf");

Console.WriteLine(loaded.IdentificationInfo?.DisplayName);

foreach (var address in loaded.DeliveryAddresses)
{
    Console.WriteLine($"{address.AddressType}: {address.Street}, {address.Locality}");
}

foreach (var phone in loaded.TelephoneNumbers)
{
    Console.WriteLine($"{phone.TelephoneType}: {phone.TelephoneNumber}");
}

if (loaded.Geo != null)
{
    Console.WriteLine($"Geo: {loaded.Geo.Latitude}, {loaded.Geo.Longitude}");
}

Security (Public Key or Certificate)

The Security property exposes the public key or authentication certificate stored in the vCard (the KEY property). Its SaveToPEM method writes that key to a PEM file.

var signed = VCardContact.Load("signed.vcf");

if (signed.Security != null && signed.Security.Key != null)
{
    Console.WriteLine("Key type: " + signed.Security.Type);

    // Export the embedded public key / certificate to a PEM file
    signed.Security.SaveToPEM("public-key.pem");
}

Load a vCard

Use the static VCardContact.Load method to read a vCard from a file or a stream. Once loaded, the contact’s properties are available through the same property sets used when creating it.

// Load from a file
var contact = VCardContact.Load("contact.vcf");
Console.WriteLine(contact.IdentificationInfo.DisplayName);

// Load from a stream
using (var stream = File.OpenRead("contact.vcf"))
{
    var fromStream = VCardContact.Load(stream);
}

Load with a Specific Encoding

To control the text encoding used while reading, pass a VCardLoadOptions object with its PreferredEncoding property set.

var loadOptions = new VCardLoadOptions { PreferredEncoding = Encoding.UTF8 };
var contact = VCardContact.Load("contact.vcf", loadOptions);

Read Multiple Contacts from a Single File

A vCard file may contain more than one contact. Use the static IsMultiContacts method to check whether a file or stream holds multiple contacts, and LoadAsMultiple to read them all into a List<VCardContact>. Both methods have file, stream, and load-options overloads:

  • static bool IsMultiContacts(string filePath) / IsMultiContacts(Stream stream)
  • static List<VCardContact> LoadAsMultiple(string filePath) / LoadAsMultiple(string filePath, VCardLoadOptions options)
  • static List<VCardContact> LoadAsMultiple(Stream stream) / LoadAsMultiple(Stream stream, VCardLoadOptions options)
using (var stream = new FileStream("contacts.vcf", FileMode.Open, FileAccess.Read))
{
    if (VCardContact.IsMultiContacts(stream))
    {
        List<VCardContact> contacts = VCardContact.LoadAsMultiple(stream);

        foreach (var contact in contacts)
        {
            Console.WriteLine(contact.IdentificationInfo.DisplayName);
        }
    }
}

Load Contacts Asynchronously

For large contact lists or I/O-bound applications (desktop, web, or mobile), VCardContact provides asynchronous loading that does not block the calling thread. Use LoadAsync for a single contact and LoadAsMultipleAsync for several. Both accept a CancellationToken.

// A single contact
var contact = await VCardContact.LoadAsync("contact.vcf", CancellationToken.None);
Console.WriteLine(contact.IdentificationInfo.DisplayName);

// Multiple contacts
var contacts = await VCardContact.LoadAsMultipleAsync(
    "contacts.vcf", new VCardLoadOptions(), CancellationToken.None);

foreach (var loaded in contacts)
{
    Console.WriteLine(loaded.IdentificationInfo.DisplayName);
}

Save Options

The VCardSaveOptions class customizes how a contact is written:

  • Version — the output vCard version from the VCardVersion enumeration: V21 (vCard 2.1, the default), V30 (3.0), or V40 (4.0).
  • PreferredTextEncoding — the encoding used when writing the file.
  • UseExtensions — whether extended (X-) properties may be written. Default is true.
  • ProductId — the value written to the PRODID property.
var contact = VCardContact.Load("contact.vcf");

var saveOptions = new VCardSaveOptions
{
    Version = VCardVersion.V30,             // write vCard 3.0 (default is V21)
    PreferredTextEncoding = Encoding.UTF8,  // encoding used when writing
    UseExtensions = true,                   // allow extended (X-) properties
    ProductId = "My Company"                // PRODID value
};

contact.Save("contact_v3.vcf", saveOptions);

See Also