Load VCF

Hello,
In the past I’ve been instructed with 2 different ways to load vcf files:
Email.PersonalInfo.VCard.VCardContact.Load
vs
MapiContact.FromVCard
I’ve compared them both to load a vcf and save it as different formats, many bugs and malfunctions here, please kindly run my sample, it will load the vcf and save it as different formats.
Files numbered 1.* are loaded using VCardContact.Load
Files numbered 2.* are loaded using MapiMessage.Load

WindowsApplication4.zip (18.0 KB)

Let’s compare the results:

1.eml : No body is added to the message
2.eml : Invalid html body! Html tags inserted into the Html body!
I’ve seen this html issue before in another function, wise to do a project wide search to find similar issues!
And both 1.eml and 2,eml do not have attachments when loaded back using Aspose! Strange the Windows Live Mail 2012 will show their attachments although different in size!

1.emlx vs 2.emlx : same as the above .eml issues!

1.htm vs 2.htm: Seems 1.htm has one more field rendered: Business Address:office
I wonder why their underlying field generator/extractor is not the same!

1.mht vs 2.mht: Same as the above Htm issue!

1.msg vs 2.msg: Here 1.msg has a different field missing rendered: Full Name:First Last
And the most important, if you load this vcf contact:
contact.zip (60.4 KB)
And use it in my sample to save as different formats, you’ll see that 2.msg does not have email1 , email2 , email3 fields.

And saving as msg/vcf using any of those 2 methods, will remove the attached cer certificate from target :frowning:

All targets are missing the contact attachment!
I hope it helps.

Hello, 3 more things :slight_smile:

  1. MyCardContact.Save(My.Application.Info.DirectoryPath + “\0.vcf”, ContactSaveFormat.WebDav)
    the specified save format is not supported
    Same error when using:
    MyCardContact.Save(My.Application.Info.DirectoryPath + “\0.vcf”, ContactSaveFormat.Msg)

  2. When using VCardContact or MapiContact how to use VCardVersion:
    Enum VCardVersion | Aspose.Email for .NET API Reference

  3. MapiContact has no .Mailer while VCardContact has no .Subject
    Both useful :slight_smile:

contact.png (22.8 KB)

As seen in Outlook 2021, a cer is added to the contact, this .cer file is at least expected to be added as attachment when saving contact in any email format
I see it’s there is vcf:
KEY;X509;ENCODING=BASE64:

contact.zip (60.4 KB)

@australian.dev.nerds
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): EMAILNET-40961

You can obtain Paid Support services if you need support on a priority basis, along with the direct access to our Paid Support management team.

1 Like

Hello and thanks for your attention, while waiting for them, generally which way to go is recommended?
VCardContact.Load or MapiContact.FromVCard

@australian.dev.nerds,

VCardContact.Load.
This method reads vcf directly without any additional conversion to MAPI format.

Thanks.

1 Like

Hi,
Few quick questions, if you don’t mind please :slight_smile:

Since VCardContact.ExplanatoryInfo.ProdId is read-only, when saving a contact as vcf, how to set it to be saved?

And what’s its difference with VCardContact.Mailer?
Is .Mailer equivalent to XMailer in Eml?

Happily VCardContact.Security.Key exists and works! But can’t add it as attachment using any of these 2 methods:
Email.Attachment.CreateAttachmentFromString(VCardContact.Security.Key, contentType, contentEncoding, mediaType)
don’t know what to enter for contentType, contentEncoding, mediaType
or also:
VCardContact.Security.SaveToPEM(MyMemoryStream)
MailMessage.AddAttachment(New Email.Attachment(MyMemoryStream, “smime.cer”))

And finally, the usual question, when any type of vcf files (different encodings) are expected to be loaded (.Load), shall we set the Encoding or not, if yes, UTF-8?
Thanks

Hi @australian.dev.nerds

We will add this feature

Yes
https://www.rfc-editor.org/rfc/rfc2426#section-3.3.3
https://www.techwalla.com/articles/what-is-a-x-mailer-header

You can try Email.Attachment.CreateAttachmentFromString(VCardContact.Security.Key,“smime.cer”)

If you do not know what encoding was used at creating stream(or file) , it is better to set UTF-8.

1 Like

Hello and thanks so much for your valuable help.
Unlike MapiContact.FromVCard, VCardContact.Load will not automatically add the contact photo as attachment to the target msg file when saved:
VCardContact.Save (MemoryStream ,ContactSaveFormat.Msg)
Please kindly share the code to add contact photo as attachment to the target msg?

        VCardContact contact = VCardContact.Load(fileName);
        MailMessage msg = new MailMessage();
        string type = "image/jpeg";//can be figure out by contact.IdentificationInfo.Photo.PhotoType
        ContentType ct = new ContentType(type);
        ct.Name = "my photo";
        msg.AddAttachment(new Attachment(new MemoryStream(contact.IdentificationInfo.Photo.Data), ct));
        MemoryStream ms = new MemoryStream();
        contact.Save(ms);
        msg.AddAlternateView(new AlternateView(ms, new ContentType("text/vcard")));
        msg.Subject = contact.IdentificationInfo.DisplayName;

Hello,
A big problem is that when we load a .vcf file to VCardContact, we have:
VCardContact.Security.Key
But when the same message is saved as .msg using Outlook, or parsed from Pst, and loaded via MapiContact.FromVCard, how can we get the attached public key?
Please kindly advise :slight_smile:

@australian.dev.nerds,

Thank you, I have added this to the ticket, so developers are able to check it out.

1 Like

Hi,
I was able to get it using:

MapiContact…Save(MyMemoryStream, ContactSaveFormat.VCard)
Dim MyCardContact As VCardContact = VCardContact.Load(MyMemoryStream)
MyCardContact.Security.Key…

However, MapiContact.Security for MapiContact is missing, possible to add it, like what we have in VCardContact? :slight_smile:

Hello, @australian.dev.nerds,

Thank you for additional info. I think it will be added in the upcomming release.

1 Like

@australian.dev.nerds
We have opened the following new ticket(s) in our internal issue tracking system and will deliver their fixes according to the terms mentioned in Free Support Policies.

Issue ID(s): EMAILNET-40965,EMAILNET-40966

You can obtain Paid Support Services if you need support on a priority basis, along with the direct access to our Paid Support management team.

Hi @australian.dev.nerds

The eml(emlx) and vcf formats are different, there are no conversion standards for them to convert, so we use the vcf addition as an alternative view.

It was fixed, fix will be available in 23.02 version.

This feature was added, it will be available in 23.02 version.

I could not find in documentation any corresponded MAPI property for Mailer , so it not make sense to add Mailer in MapiContact which is a set of MAPI properties.

In object model VCardVersion not present, but you can save in file or stream current contact with appropriate version by set VCardSaveOptions.Version

It was fixed, fix will be available in 23.02 version.

It was fixed, fix will be available in 23.02 version.
Note. The .cer file is not added as an attachment, instead it is stored in the PR_USER_X509_CERTIFICATE special MAPI property, as Outlook does.

It was fixed, fix will be available in 23.02 version.

1 Like

Hi,
Of course should not be added as attachment, my bad, misunderstanding, but what if we save as mht with all parameters? There might be wise to have it as attachment…
Anyhow:

Dim MyMapiProperty As MapiProperty = MyContact.Properties(MapiPropertyTag.PR_USER_X509_CERTIFICATE)
If MyMapiProperty IsNot Nothing Then
MyMemoryStream = New MemoryStream(MyMapiProperty.Data, False)
Dim Myattach As New Email.Attachment(“smime.cer”, “application/x-x509-ca-cert”)
Myattach.ContentStream = MyMemoryStream
MyMailMessage.Attachments.Add(Myattach)
End If

is correct? seems not, it’s not adding a new attachment but trying to load one from my app’s path!

  • Since contacts are saved as Msg first, I’d be more happy if I can add that .cer directly to the MapiMessage:

Dim MyMapiProperty As MapiProperty = MyContact.Properties(MapiPropertyTag.PR_USER_X509_CERTIFICATE)
If MyMapiProperty IsNot Nothing Then
MyMapiMessage.Attachments.Add(“smime.cer”, MyMapiProperty.Data)
,
A file named smime.cer is added to the message with the size of 1 byte (just one single space inside)

@australian.dev.nerds,

just need some time to deal with this. Thanks.

1 Like

Thanks, just plz confirm if I am getting the property correctly? Seems the error is there?

Dim MyMapiProperty As MapiProperty = MapiContact.Properties(MapiPropertyTag.PR_USER_X509_CERTIFICATE) 'Properties vs NamedProperties?

If MyMapiProperty IsNot Nothing Then … MyMapiProperty.Data

@australian.dev.nerds,

Code sample to extract cert data:

var certProperty = mapiContact.Properties[MapiPropertyTag.PR_USER_X509_CERTIFICATE];
            
byte[] data = null; //cert data
            
if (certProperty != null && certProperty.MVEntries.Count > 0)
{
    foreach (byte[] entry in certProperty.MVEntries)
    {
        int offset = 0;

        while (offset < entry.Length - 4)
        {
            ushort tag = BitConverter.ToUInt16(entry, offset);
            ushort dataLength = BitConverter.ToUInt16(entry, offset + 2);
                        
            if (tag == 0x0003)
            {
                data = new byte[dataLength - 4];
                Buffer.BlockCopy(entry, offset + 4, data, 0, dataLength - 4);
                break;
            }

            offset += dataLength;
        }
     }
}

if (data != null)
{
    // do something with cert data
}

Thanks.

1 Like