vCard 3.0 validator and parser

Did you know that even the vCards listed in the official RFC are not valid? It clearly says The vCard object MUST contain the FN, N and VERSION types. Still, the example vCards are both clearly missing the N type. As somebody else remarked, releasing a format spec without some reference validator is bound to result in all sorts of invalid implementations.

After searching for a vCard validator without success, I’ve therefore started my own vCard module in Python. It tries to create an object with all the information from a vCard string, and returns what I hope are useful error and warning messages if there’s anything wrong.

Update: Added file validation – Now you can validate files with several vCards from the command line.

Install / upgrade:
sudo pip install --upgrade vcard

Validate vCard files:
vcard *.vcf

34 thoughts on “vCard 3.0 validator and parser

  1. Pingback: HOWTO: Synchronizing vCard address books with Nokia 6300 via Bluetooth on Ubuntu Linux « Paperless

  2. Have you considered using the Python vobject library? It can parse vCards as well as generate them.

    • I had a look at it before developing this, and as far as I can see from the documentation it supports a much smaller subset of vCards. I remain open to convincing though, especially since I’ve yet to find a generator that creates valid vCards.

  3. I just installed this to test out the vcard I was programmatically generating, and I get the error message:

    “Could not process entire joe-blow.vcf – 214 lines remain”

    Even with the verbose flag, this is all I get. Any chance of getting some more useful info?

    • This means that the file doesn’t contain anything that could be validated – In other words, it contains no vCards. The simplest reason for this is if the line endings are wrong – The standard mandates that each line be terminated with carriage return followed by newline (aka. \r\n or CRLF).

  4. I don’t suppose you could be convinced to make your validator available as a web service?

    • Sorry, there’s just way too many interesting projects in the pipeline to promise any such interfaces. But you or anyone you know are of course free to do so – It’s open source.

  5. I also got the “Could not process entire joe-blow.vcf – 214 lines remain” message, except that my file did have carriage returns and linefeeds ending each line (this is simple to achieve with vim, just set fileformat=dos with ‘:set ff=dos’). However, I was still getting the message until I noticed that each of your testcases end with a blank line. So I added the blank line at the end of my file and it worked. Now I am not sure if the blank line is required or whether it is just a quirk of your program.

    • That is actually a requirement of the RFC – Each vCard (i.e., including the last one) must end with an empty line.

    • Yes, and thank you for the interest, but I don’t think I’ll be the best (or even the third best) person to do it. First, this project is my first validator, and as such the code is not very good. There’s a lot of duplication, and the validator usually just stops at the first sign of trouble rather than trying to find as many issues as possible in each run (like the excellent W3C validator). Second, vCard 3 is serving me well (warts included), and I don’t think there’s much benefit in moving to Yet Another Standard (but I’m open to arguments). And last, the curse of any developer, there are just too many interesting things to work on!

      tl;dr I probably won’t, but anyone is welcome to.

  6. Hi,

    i have a v3.0 but become always this msg:

    > vcard -v ./3.vcf
    Could not process entire ./3.vcf – 12 lines remain

    I have checked the file for CRLF and a free line at the end.
    All looks good.

    the verbose switch brings no more infos.

    here an example vcf, where i become an error.
    Whats wrong here?

    3.vcf:
    BEGIN:VCARD
    VERSION:3.0
    PRODID:-//Apple Inc.//Mac OS X 10.8.4//EN
    N:Doe;John;;;
    FN:John Doe
    ORG:Stiftung Soundso für Soundso e. V.;
    TEL;type=WORK;type=VOICE;type=pref:+49 (0 89) 87 65 43 – 21
    TEL;type=WORK;type=FAX:+49 (0 89) 12 34 56 78
    ADR;type=WORK;type=pref:;;Hauptstr. 123;München;;;Deutschland
    REV:2013-06-26T10:37:31Z
    UID:ed6aa1aa-2aaa-47aa-a4aa-95aac16785aa
    END:VCARD

    Best regards,
    Daniel.

    • I copied and pasted the contents into a file, and I don’t get the same error. I would need the original file to debug this.

      • hi,

        here is the original file:

        [link removed]

        best regards,
        daniel

  7. I’m sorry, but this wrong. Here is the formal grammar that defines what a vCard is:
    vcard = [group “.”] “BEGIN” “:” “VCARD” 1*CRLF
    1*(contentline)
    ;A vCard object MUST include the VERSION, FN and N types.
    [group “.”] “END” “:” “VCARD” 1*CRLF
    It allows for blank lines after the END:VCARD line, but does not require them. Look at the examples from the CardDAV RFC for verification.

    • You’re absolutely correct. Looking through the RFC again, I cannot find what caused me to think that vCards need to be separated by two CRLFs. Thank you for the heads up! Would you create a bug report, or should I do it?

  8. I’m glad that I found this. I’m (perhaps stupidly) trying to teach myself Python through creating an actual application. I’ve decided to use vcards as the record format for people, but haven’t been able to find much. VObjects seems to be more calendar focused.

    I’ve played around for a couple of years with Python, and have just decided to sink or swim with 3.4. It strikes me that the model for a vcard is pretty straightforward, so I might as well define it myself according to standard.

    I’ll read through what you have and hopefully that way, I’ll have a decent model structure as well as a validation tool.

    Thanks for sharing this.

  9. Having a VCF-file starting with a UTF8 BOM causes the validator to reject the entire file.

    The current RFC for vcards (6350) states that the charset for vcard is utf-8. Not a complaint, just an observation. I have not found any other useful tool for validating vcards.

  10. You said “vCard 3 is not UTF-8.”
    https://tools.ietf.org/html/rfc6350
    3.1. Charset

    The charset (see [RFC3536] for internationalization terminology) for
    vCard is UTF-8 as defined in [RFC3629]. There is no way to override
    this. It is invalid to specify a value other than “UTF-8” in the
    “charset” MIME parameter (see Section 10.1).

    It is saying the charset is UTF-8 period.

    My testing is showing that if I include non asci characters (>127) in any of the fields
    some applications reading them show it as an invalid vcard.

    If I add a charset on EVERY field that has a UTF-8 character (>127) it seems to work.

    1) You say vcard 3.0 is not utf-8
    2) the rfc says they are only utf-8
    3) testing shows I need a charset for all data that isn’t asci.

    For example
    FN;CHAR SET=UTF-8:MarkÜ

    Help!

    • My mistake. I am referring the vCard 4.0 specs.
      The 4.0 specs say 4.0 is always UTF-8. (RFC3629)

      1) For verson 3.0 vCards,
      should I add a charset as part of the header or add it to every line with a char >127
      or both?

      2) what is the correct header for 3.0 vCards with international (UTF-8) characters?
      text/directory; charset=”utf-8″;

      Thanks.

  11. I came across this site when looking for a discussion group about vCards, and at the risk of going off-topic, I would ask the following question:
    What happens when John Doe gets married?
    FN: Mr & Mrs John and Jane Doe ? (Mr & Mrs John Doe is preferable)
    N:Doe;John; and Jane;Mr & Mrs;; ? (using wife’s given name as “Additional Name”
    I also want to find some way of extracting LABEL data to print my address labels in (preferably) a Linux environment

    • Graeme, vCards are meant to be one per person, so you would have two vCards for a couple. You can use a custom X-WHATEVER property to for example refer to people’s significant other; X-SPOUSE is a common such property.

      Questions about manipulating vCard files in Linux are probably better directed to Unix & Linux Stack Exchange.

  12. Thanks for a prompt and informative reply. I had hoped to use vCards as a common base to maintain contacts in Linux, Android and Windows environments, including the usual Christmas card label print, but clearly a bit of programmatic intervention would be required. I presume X-SPOUSE and X-PARTNER would cover all the usual pairings!

    • I use vCards as a reference, and it’s a nice way to make sure you keep your contacts in sync and under control. You can find the commands I use regularly in my Bash history file.

  13. Pingback: Why I’m not working on vCard validators | Paperless

  14. I tried vcard and it is choking on space inside N: fields like these:

    N:Last;First;Middle1 Middle2;;

    I know,it is not allowed, but I expected report, not a crash:

    Traceback (most recent call last):
    File “/usr/local/bin/vcard”, line 8, in
    sys.exit(main())
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard.py”, line 21, in main
    result = VcardValidator(filename, arguments.verbose).result
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 45, in __init__
    self.result = self.validate()
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 48, in validate
    return validate_file(self.path, self.verbose)
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 75, in validate_file
    vcard = VCard(vcard_text, filename)
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 121, in __init__
    self.properties = get_vcard_properties(lines)
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 225, in get_vcard_properties
    properties.append(get_vcard_property(property_line))
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validator.py”, line 273, in get_vcard_property
    vcard_validators.validate_vcard_property(property_)
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_validators.py”, line 512, in validate_vcard_property
    warnings.warn(“{0}: {1}”.format(WARN_MULTIPLE_NAMES, name.encode(“utf-8”)))
    File “/usr/lib/python3.8/warnings.py”, line 109, in _showwarnmsg
    sw(msg.message, msg.category, msg.filename, msg.lineno,
    File “/usr/local/lib/python3.8/dist-packages/vcard/vcard_errors.py”, line 66, in show_warning
    file.write(“{0}\n”.format(message))
    AttributeError: ‘NoneType’ object has no attribute ‘write’

    Anyway, android phones export such a garbage … (PRODID:ez-vcard 0.10.5), how hard it is to replace space with comma on export and vice versa… at least sed -e “/^N:/s/ /,/g” is helps.

    • on the other hand, RFC clearly allows for space in text fields, so it not even incorectt, yet vcard crashes.

      • I’m sorry, but the vCard validator is no longer maintained. I’ve tried several times to reboot the project, but I simply don’t have the time.

Leave a reply to l0b0 Cancel reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.