eml to vcf shell script

Convert contacts in eml to vcf

I have been working on a project for a customer who has a large number of contacts. macOS ‘Contacts’ simply crashes and unexpectedly quits when trying to open and/or sync with the upstream server. The contacts are stored on a Kerio Connect server and we have access to the backend.

Note – Apparently, a few other mail servers on the market store contacts in the same way as Kerio Connect, you may be able to use this script for converting .eml files from these other mail servers too. If you do try this, let me know how you fare in the comments!

Contacts in Kerio Connect are stored as individual .eml files, below you cn see the output of tree, showing the structure of the raw files from the Kerio Connect store:

Desktop james$ tree .
Contacts Folder
│   ├── #assoc
│   ├── #msgs
│   │   ├── 00000001.eml
│   │   ├── 00000004.eml
│   │   ├── 00000005.eml
│   │   ├── 00000006.eml
│   │   ├── 00000007.eml
│   │   ├── 00000008.eml
│   │   ├── ...
│   │   ├── ...
│   │   ├── ...
│   │   ├── 00000504.eml

A closer look at one of the .eml files shows that the file is made up of standard email headers and then the vCard content sits between the ‘BEGIN: VCARD’ and ‘END: VCARD’ lines, as shown below. I began searching for ways to convert the .eml files to .vcf format so I could then export the vCards into a standard Comma Separated Values (.csv) format for processing.

eml to vcf shell script
Contents of a vCard in .eml format. Lines 1-4 show the email header, lines 6-14 show the vCard information

I came across a couple of posts with outdated and incorrectly formatted bash and PHP scripts designed to loop through the folder contents and convert the source files into standard .vcf files. I decided to write a small, up-to-date script that does the following (some code from this post https://palatum.org/2014/01/kerio-contacts-export-script-eml-to-vcf/):

  • Asks for the absolute path of the parent folder containing the .eml files.
  • Creates a folder called ’eml-originals’ and moves the original .eml files into it.
  • Backs up the original .eml files and places them in a newly created folder called ’eml-backup’, as a compressed tarball (tar.gz).
  • The script then loops through the folder containing the .eml files and removes the top 4 lines (containing the email headers) and then uses the command ‘iconv’ to convert each .eml from UTF8 to MacRoman file encoding, saving the file into a new folder called ’eml-to-vcf-output’.
  • Finally, the script uses the command ‘cat’ to merge all of the individual .vcf files into one group vCard, saving the group card into a folder called ‘merged-vcfs’.

Due to the number of contacts the end-user had, I couldn’t simply use ‘mv’ and ‘cat’ to move the source files and create the group vCard. Instead, I had to complete these steps by using the ‘-exec’ flag of the ‘find’ command. Whilst this introduces some error handling, it also makes the command slower to run – but converting around 20,000 contacts went from around 20 seconds to roughly one minute, a bit slower, but not too bad.

Anyway, I have pasted and linked the script below (fully commented) – let me know what you think via the comments!

#! /bin/bash
# .eml contact to vcard converter, 2019-12-08 James Spong / FatMac IT Solutions
# Test first, use wisely and remember; with great power, comes great responsibility

# ask user for source folder and assign to var
read -p "Enter the absolute file path of the folder containing the .eml Files": SRC

# assign variables

# make new BACKUP directory
mkdir -p $BACKUP

# make new ORIGINAL directory
mkdir -p $ORIGINAL

# make new DEST directory
mkdir -p $DEST

# make new MERGED directory
mkdir -p $MERGED

# change directory to SRC
cd $SRC

# move SRC emls to ORIGINAL directory
find $SRC -name '*.eml' -exec mv {} $ORIGINAL \;

# backup ORIGINAL directory as tar.gz, save in BACKUP directory
tar --exclude="$BACKUP" --exclude="$DEST" --exclude="$MERGED" -zcvf $BACKUP/eml-files.tar.gz $ORIGINAL

# change directory to ORIGINAL

# echo status and loop through command
for vcard in *.eml
echo "processing $vcard"

# change DOS CR/LF to *nix line endings and strip the header of the message
# then output the „correct“ VCards to the backup directory
sed -e 's/.$// ; 1,/^$/ d' < $vcard | iconv -f UTF8 -t MACROMAN > $DEST/${vcard/%eml/vcf}

# merge all vcards into one .vcf
# cat $DEST/*.vcf > $MERGED/merged-vcards.vcf
find $DEST -name "*.vcf" -exec cat '{}' ';' > $MERGED/merged-vcards.vcf

echo ""
echo "     ___             /  /  /"
echo "\ / |__   /\  |__|  /  /  / "
echo " |  |___ /~~\ |  | .  .  .  "
echo "                            "
echo ""
5 2 votes
Article Rating

Notify of

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

1 Comment
Oldest Most Voted
Inline Feedbacks
View all comments
Holger Bartsch

your script is awesome! it saved my life today!!

Would love your thoughts, please comment.x