Summary
SupportedAddressData::default() (crates/carddav/src/addressbook/prop.rs) advertises text/vcard 3.0 and 4.0, hardcoded.
Two consequences:
- DAVx5 android app writes vCard 4.0 whenever the server advertises it with no user override.
- 🤯 macOS Contacts' CardDAV client does not accept vCard 4.0 at all. It drops the card and marks the whole address-book sync as failed, then retries every few minutes forever.
This results in any contact created or edited on Android never appearing on the Mac, with no visible error in either client. Every server I've seen macOS Contacts work with (Nextcloud/sabre, Radicale, iCloud) ends up serving 3.0 to it.
Reproduce
- rustical 0.14.1, one address book, principal used by both DAVx5 (4.5.19-ose) and
macOS 15.5 Contacts.
- Create a contact on Android. DAVx5 PUTs:
BEGIN:VCARD
VERSION:4.0
PRODID:+//IDN bitfire.at//DAVx5/4.5.19-ose ez-vcard/0.12.1
UID:…
FN:…
N:…;;;;
TEL;TYPE=cell:+…
REV:…
END:VCARD
-
On the Mac, /usr/bin/log show --info --debug --predicate 'process == "AddressBookSourceSync"':
CardInfoFromVCardData(): Ignored vCard at <private> because it is an unsupported vCard version: "<private>"
-_handleAddsOrModifies: could not parse vCard in <private>
### ERRORS REMAIN in sync. Not setting lastSyncDate. …
"/carddav/principal/…/…/" = "Error Domain=CDXManager Code=7 \"Some server contacts could not be copied to this address book.\""
The count of "Ignored vCard" lines equals the count of VERSION:4.0 rows in
addressobjects; every 3.0 card syncs fine.
Proposal
A config option, default unchanged:
[carddav]
advertise_vcard4 = true # set false when Apple clients share the address book
that drops the 4.0 entry from supported-address-data. RFC 6352 §6.2.2 only requires the
server to accept what it advertises, so 4.0 PUTs keep working; DAVx5 simply switches to
3.0 for new writes. It is a one-line change in SupportedAddressData plus config plumbing.
A fuller fix would be content negotiation — convert stored 4.0 to 3.0 when the client's
Accept asks for 3.0 (what sabre/dav does) — but that is a larger change and the flag
covers the common case.
Workaround used meanwhile
UPDATE addressobjects SET vcf = replace(vcf, 'VERSION:4.0', 'VERSION:3.0') WHERE deleted_at IS NULL AND vcf LIKE '%VERSION:4.0%';
unblocks the Mac (etag is sha256 of the vcf, so it refetches), but recurs on the next
Android write. Happy to send a PR for the flag if you'd take it.
Summary
SupportedAddressData::default()(crates/carddav/src/addressbook/prop.rs) advertisestext/vcard3.0 and 4.0, hardcoded.Two consequences:
This results in any contact created or edited on Android never appearing on the Mac, with no visible error in either client. Every server I've seen macOS Contacts work with (Nextcloud/sabre, Radicale, iCloud) ends up serving 3.0 to it.
Reproduce
macOS 15.5 Contacts.
On the Mac,
/usr/bin/log show --info --debug --predicate 'process == "AddressBookSourceSync"':The count of "Ignored vCard" lines equals the count of
VERSION:4.0rows inaddressobjects; every 3.0 card syncs fine.Proposal
A config option, default unchanged:
that drops the 4.0 entry from
supported-address-data. RFC 6352 §6.2.2 only requires theserver to accept what it advertises, so 4.0 PUTs keep working; DAVx5 simply switches to
3.0 for new writes. It is a one-line change in
SupportedAddressDataplus config plumbing.A fuller fix would be content negotiation — convert stored 4.0 to 3.0 when the client's
Acceptasks for 3.0 (what sabre/dav does) — but that is a larger change and the flagcovers the common case.
Workaround used meanwhile
UPDATE addressobjects SET vcf = replace(vcf, 'VERSION:4.0', 'VERSION:3.0') WHERE deleted_at IS NULL AND vcf LIKE '%VERSION:4.0%';unblocks the Mac (etag is sha256 of the vcf, so it refetches), but recurs on the next
Android write. Happy to send a PR for the flag if you'd take it.