Import Contacts Vcards Into Nextcloud
In this post, we’re going to export our contacts from
Google in vCard version 3 format, split the
contacts file and use cadaver
to upload all files individually to your address
book.
The struggle
Last week, I did a fresh install of Lingeage OS 14.1 on my OnePlus X and decided not to install any GApps. I have been slowly moving away from using Google services and, having found replacements in the form of open-source apps or web interfaces, I felt confident I would be able to use my phone without a Google Play Store or Play Services. (F-Droid is now my sole source of apps.)
To tackle the problem of storing contacts and a calendar that could be synced, I installed a Nextcloud instance on a Raspberry Pi 3. Having installed DAVdroid, I got my phone to sync contacts with Nextcloud, but not all of them: it would stop synchronizing after some 120 contacts, while I had more than 400.
I decided to try a different approach, so I exported the contacts on my phone in vCard format and tried to upload them to Nextcloud using the aptly named application “contacts” for this. However, this also failed unexpectedly. I’m using Nextcloud version 12.0.3 and version 2.0.1 of the contact app, but it refuses to accept vCard version 2.1 (HTTP response code 415: Unsupported media type). This, naturally, is the version Android 6 uses to export contacts.
After some searching, I found out that if you go to contacts.google.com, you can download your contacts in vCards version 3. Problem fixed? Well, not so fast: importing 400+ contacts into Nextcloud using the web interface on a Raspberry Pi 3 with an SD card for storage will take a long time. In fact, it never finished over the course of a couple of hours (!), so I needed yet another approach.
Fortunately, you can approach your Nextcloud instance through the WebDAV
protocol using tools such as
cadaver
:
$ cadaver https://192.168.1.14/nextcloud/remote.php/dav
Storing your credentials in a .netrc
file in your home directory will
enable cadaver
to verify your identity without prompting, making it
suitable for scripting:
machine 192.168.1.14
login foo
password correcthorsebatterystaple
cadaver
allows you to traverse the directories of the remote file
system over WebDAV. To put a single local contacts file (from your
working machine) to the remote Raspberry Pi, you could tell it to:
dav:/nextcloud/remote.php/dav/> cd addressbooks/users/{username}/{addressbookname}
dav:/nextcloud/remote.php/dav/addressbooks/users/foo/Contacts/> put /home/foo/all.vcf all.vcf
I had a single vcf
file with 400+ contacts in them, but after
uploading it this way, only a single contact was being displayed.
Apparently, the Nextcloud’s contacts app assumes a single vcf
file
contains only a single contact. New challenge: we need to split this
single vcf
file containing multiple contacts into separate files that
we can then upload to Nextcloud.
To split the contacts, we can use awk
:
BEGIN {
RS="END:VCARD\r?\n"
FS="\n"
}
{
command = "echo -n $(pwgen 20 1).vcf"
command | getline filename
close(command)
print $0 "END:VCARD" > filename
}
This separates the contacts on the record separator END:VCARD
and
generates a random filename to store the individual contact in. (I also
wrote a Java program to do the same
thing, which is faster when
splitting large files).
Obviously, it would be convenient now if we could upload all these files
in one go. cadaver
does provides the mput
action to do so, but I did
not get it to work with wildcards. So instead, I created a file with
put
commands:
for file in *.vcf; do
echo "put $(pwd)/$file addressbooks/users/foo/Contacts/$file" >> commands
done
And then provided this as input to cadaver:
$ cadaver http://192.168.1.14/nextcloud/remote.php/dav <<< $(cat commands)
This may take a while (it took around an hour for 400+ contacts), but at least you get to see the progress as each request is made and processed. And voilà, all the contacts are displayed correctly in Nextcloud.