Skip to content

Instantly share code, notes, and snippets.

@bussiere
Created April 11, 2026 18:24
Show Gist options
  • Select an option

  • Save bussiere/de9446fbd71c16938f70c260f8e7259d to your computer and use it in GitHub Desktop.

Select an option

Save bussiere/de9446fbd71c16938f70c260f8e7259d to your computer and use it in GitHub Desktop.
norme ical vcard
# Normes vCard & iCalendar — gestcontact
Documentation de référence des formats d'échange utilisés par gestcontact pour l'import et l'export des données de contact et d'événement.
---
## 1. vCard 3.0 — RFC 2426
### Qu'est-ce que vCard ?
vCard est un format de fichier texte standard (extension `.vcf`) pour l'échange de données de contact entre applications (carnets d'adresses, clients mail, smartphones).
gestcontact utilise **vCard 3.0** (RFC 2426, 1998), la version la plus largement supportée (Apple Contacts, Google Contacts, Thunderbird, Android, iOS).
La version 4.0 (RFC 6350, 2011) apporte quelques améliorations mineures mais est moins supportée.
### Structure d'un fichier vCard
```
BEGIN:VCARD
VERSION:3.0
[propriétés]
END:VCARD
```
Chaque ligne est une **propriété** de la forme :
```
NOM[;PARAMÈTRE=VALEUR...]:valeur
```
### Propriétés reconnues par gestcontact
#### Identité
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `FN` | `FN:Jean Dupont` | `first_name` + `last_name` | Nom complet, requis |
| `N` | `N:Dupont;Jean;;;` | `last_name` ; `first_name` | Nom structuré — prioritaire sur `FN` si présent |
| `ORG` | `ORG:Acme Corp` | `name` (Organisation) | Nom d'organisation |
Format du champ `N` : `Nom de famille;Prénom;Deuxième prénom;Titre;Suffixe`
#### Contact
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `EMAIL;TYPE=INTERNET` | `EMAIL;TYPE=INTERNET:a@b.fr` | `email` | Email personnel (nullable) |
| `EMAIL;TYPE=WORK` | `EMAIL;TYPE=WORK:pro@b.fr` | `email_pro` | Email professionnel |
| `TEL;TYPE=CELL` | `TEL;TYPE=CELL:+33612345678` | `phone_number` | Mobile |
| `TEL;TYPE=WORK` | `TEL;TYPE=WORK:+33145001122` | `phone_number_pro` | Téléphone pro |
Si un seul email est présent (sans type `WORK`), il est affecté à `email`.
#### Adresse
| Propriété | Format | Notes |
|-----------|--------|-------|
| `ADR;TYPE=HOME` | Voir ci-dessous | Adresse personnelle (Personnes) |
| `ADR;TYPE=WORK` | Voir ci-dessous | Adresse professionnelle (Organisations, Lieux) |
Format du champ `ADR` : `Boite postale;Complément;Rue;Ville;Région;Code postal;Pays`
Exemple :
```
ADR;TYPE=HOME:;;15 rue de Charonne;Paris;;75011;France
```
L'adresse est automatiquement **géocodée** via [api-adresse.data.gouv.fr](https://adresse.data.gouv.fr/) pour créer la hiérarchie géographique (Country → State → City → ZipCode → Street → Address) avec coordonnées GPS.
#### Date de naissance
| Propriété | Format | Champ gestcontact |
|-----------|--------|-------------------|
| `BDAY` | `BDAY:1985-04-23` | `birthday` |
Format accepté : ISO 8601 (`YYYY-MM-DD`). Les 10 premiers caractères sont lus.
#### Métadonnées
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `CATEGORIES` | `CATEGORIES:ami,client,tech` | `tags` (M2M) | Valeurs séparées par virgule — crée les tags manquants |
| `NOTE` | `NOTE:Rencontré en 2024.` | `note.content` | Crée une `Note` attachée à l'entité |
| `GEO` | `GEO:48.853;2.349` | `address.lat;address.lon` | Export uniquement (LocalisationIRL) |
#### Site web — propriété standard
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `URL` | `URL:https://example.com` | `SocialNetworks` (WB) | Propriété standard RFC 2426 §3.6.8 |
#### Réseaux sociaux — extension X-SOCIALPROFILE
vCard 3.0 ne comporte pas de propriété native pour les réseaux sociaux. gestcontact utilise l'extension **`X-SOCIALPROFILE`**, compatible avec Apple iOS / macOS Contacts, Thunderbird et de nombreuses applications tierces.
**Format :**
```
X-SOCIALPROFILE;TYPE=<réseau>:<url>
X-SOCIALPROFILE;TYPE=<réseau>;X-USER=<nom d'utilisateur>:<url>
```
Les propriétés `X-` sont autorisées par la RFC 2426 §3.8 (non-standard properties).
**Table de correspondance :**
| `TYPE=` | Réseau | Code interne | Exemple d'URL |
|---------|--------|--------------|---------------|
| `instagram` | Instagram | IG | `https://instagram.com/username` |
| `twitter` | Twitter/X | TW | `https://twitter.com/username` |
| `facebook` | Facebook | FB | `https://facebook.com/username` |
| `linkedin` | LinkedIn | LN | `https://linkedin.com/in/username` |
| `tiktok` | TikTok | TK | `https://tiktok.com/@username` |
| `youtube` | YouTube | YT | `https://youtube.com/@channel` |
| `bluesky` | Bluesky | BS | `https://bsky.app/profile/handle.bsky.social` |
| `discord` | Discord | DC | `https://discord.gg/server` |
| `reddit` | Reddit | RD | `https://reddit.com/u/username` |
| `tripadvisor` | TripAdvisor | TA | `https://tripadvisor.fr/Restaurant_Review-...` |
| `googlemaps` | Google Maps | GM | `https://maps.google.com/?cid=...` |
| *(URL standard)* | Website | WB | `URL:https://example.com` |
### Exemple vCard complet — Personne
```vcf
BEGIN:VCARD
VERSION:3.0
N:Dupont;Jean;;;
FN:Jean Dupont
EMAIL;TYPE=INTERNET:jean.dupont@example.com
EMAIL;TYPE=WORK:j.dupont@societe.fr
TEL;TYPE=CELL:+33612345678
TEL;TYPE=WORK:+33145678900
ADR;TYPE=HOME:;;15 rue de Charonne;Paris;;75011;France
BDAY:1985-04-23
CATEGORIES:ami,client
NOTE:Rencontré lors de la conférence 2024.
URL:https://jeandupont.fr
X-SOCIALPROFILE;TYPE=twitter;X-USER=jdupont:https://twitter.com/jdupont
X-SOCIALPROFILE;TYPE=instagram;X-USER=jean.dupont:https://instagram.com/jean.dupont
X-SOCIALPROFILE;TYPE=linkedin:https://linkedin.com/in/jeandupont
X-SOCIALPROFILE;TYPE=bluesky;X-USER=jdupont.bsky.social:https://bsky.app/profile/jdupont.bsky.social
END:VCARD
```
### Exemple vCard complet — Organisation
```vcf
BEGIN:VCARD
VERSION:3.0
FN:Acme Corporation
ORG:Acme Corporation
EMAIL;TYPE=WORK:contact@acme.fr
TEL;TYPE=WORK:+33145001122
ADR;TYPE=WORK:;;10 avenue de l'Opéra;Paris;;75001;France
CATEGORIES:client,partenaire
NOTE:Fournisseur principal depuis 2020.
URL:https://acme.fr
X-SOCIALPROFILE;TYPE=instagram:https://instagram.com/acme_corp
X-SOCIALPROFILE;TYPE=facebook:https://facebook.com/acmecorp
X-SOCIALPROFILE;TYPE=linkedin:https://linkedin.com/company/acme
END:VCARD
```
### Comportement de l'import vCard
| Situation | Comportement |
|-----------|-------------|
| Email déjà présent (People) | Erreur — contact existant retourné |
| Nom d'organisation déjà présent | Erreur — déduplication par nom (insensible à la casse) |
| Organisation à la même adresse | Warning — l'import continue |
| Adresse non géocodable | Warning — champ adresse laissé vide |
| Email absent | Warning — champ email = `NULL` |
| Réseaux sociaux importés | Warning informatif avec le nombre de réseaux |
| URL déjà existante en base | Réutilise le `SocialNetwork` existant (dédupliqué par URL) |
---
## 2. iCalendar 2.0 — RFC 5545
### Qu'est-ce que iCalendar ?
iCalendar est un format de fichier texte standard (extension `.ics`) pour l'échange de données d'événements, de tâches et de disponibilités entre applications de calendrier (Google Calendar, Apple Calendar, Outlook, Thunderbird).
gestcontact utilise **iCalendar 2.0** (RFC 5545, 2009), supporté universellement.
### Structure d'un fichier iCalendar
```
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//gestcontact//gestcontact//FR
BEGIN:VEVENT
[propriétés de l'événement]
END:VEVENT
END:VCALENDAR
```
Un fichier `.ics` peut contenir plusieurs `VEVENT`. gestcontact importe uniquement le **premier VEVENT** trouvé.
### Propriétés VEVENT reconnues par gestcontact
#### Obligatoires à l'import
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `SUMMARY` | `SUMMARY:Titre de l'événement` | `title` | Requis — erreur si absent |
| `DTSTART` | Voir formats ci-dessous | `date` | Requis — erreur si absent |
| `LOCATION` | `LOCATION:15 rue de Charonne, Paris, 75011` | `address` | Requis — géocodé automatiquement |
#### Optionnelles
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `DTEND` | Idem DTSTART | *(non stocké)* | Export auto : DTSTART + 1h |
| `DESCRIPTION` | `DESCRIPTION:Texte libre` | `description` | |
| `CATEGORIES` | `CATEGORIES:conférence,tech` | `tags` (M2M) | Valeurs séparées par virgule |
| `COMMENT` | `COMMENT:Note interne` | `note.content` | Crée une `Note` attachée |
| `UID` | `UID:abc@gestcontact` | *(ignoré à l'import)* | Export : `<id>@gestcontact` |
#### Site web — propriété standard
| Propriété | Format | Champ gestcontact | Notes |
|-----------|--------|-------------------|-------|
| `URL` | `URL:https://example.com` | `SocialNetworks` (WB) | RFC 5545 §3.8.4.6 — un seul URL exporté |
#### Réseaux sociaux — extension X-SOCIALPROFILE
Même convention que pour les vCards. iCalendar autorise les extensions `X-` (RFC 5545 §3.8.8.2).
```
X-SOCIALPROFILE;TYPE=<réseau>:<url>
X-SOCIALPROFILE;TYPE=<réseau>;X-USER=<nom d'utilisateur>:<url>
```
La table des types est identique à celle de vCard (voir section 1).
### Formats de date DTSTART / DTEND
| Format | Exemple | Interprétation |
|--------|---------|----------------|
| Date+heure locale | `DTSTART:20241015T140000` | 15 oct. 2024 à 14:00 (naïf) |
| Date+heure UTC | `DTSTART:20241015T140000Z` | 15 oct. 2024 à 14:00 UTC |
| Date+heure avec timezone | `DTSTART;TZID=Europe/Paris:20241015T140000` | 15 oct. 2024 à 14:00 heure Paris |
| Date seule | `DTSTART;VALUE=DATE:20241015` | 15 oct. 2024 à 00:00 |
> **Note** : gestcontact stocke les dates sans timezone (naïves). Les dates UTC et timezone-aware sont converties en naïf à l'import.
### Exemple iCalendar complet
```ics
BEGIN:VCALENDAR
VERSION:2.0
PRODID:-//gestcontact//gestcontact//FR
BEGIN:VEVENT
UID:exemple-2024@gestcontact
SUMMARY:Conférence Django Paris 2024
DTSTART:20241015T140000
DTEND:20241015T180000
LOCATION:15 rue de Charonne, Paris, 75011, France
DESCRIPTION:Conférence annuelle de la communauté Django francophone.
CATEGORIES:conférence,django,tech
COMMENT:À confirmer avec les organisateurs.
URL:https://djangocon.fr
X-SOCIALPROFILE;TYPE=twitter;X-USER=djangoparis:https://twitter.com/djangoparis
X-SOCIALPROFILE;TYPE=instagram:https://instagram.com/djangoparis
X-SOCIALPROFILE;TYPE=bluesky;X-USER=djangoparis.bsky.social:https://bsky.app/profile/djangoparis.bsky.social
END:VEVENT
END:VCALENDAR
```
### Comportement de l'import iCalendar
| Situation | Comportement |
|-----------|-------------|
| SUMMARY absent | Erreur |
| DTSTART absent | Erreur |
| LOCATION absent | Erreur — l'adresse est obligatoire (FK PROTECT) |
| LOCATION non géocodable | Erreur avec message explicite |
| Seul le premier VEVENT | Warning si fichier multi-événements |
| URL déjà existante en base | Réutilise le `SocialNetwork` existant |
### Export iCalendar
L'export produit un fichier `.ics` avec les champs suivants :
```
PRODID:-//gestcontact//gestcontact//FR
UID:<event.id>@gestcontact
SUMMARY:<title>
DTSTART:<date>
DTEND:<date + 1h>
LOCATION:<address.get_full_address()>
DESCRIPTION:<description> [si présente]
CATEGORIES:<tag1>,<tag2> [si tags]
URL:<url> [premier site web]
X-SOCIALPROFILE;TYPE=<net>[;X-USER=<username>]:<url> [par réseau]
```
---
## 3. Géocodage automatique
gestcontact géocode automatiquement les adresses lors de l'import vCard (champ `ADR`) et iCalendar (champ `LOCATION`).
**API utilisée** : [api-adresse.data.gouv.fr](https://adresse.data.gouv.fr/) (gouvernement français, gratuite, sans authentification)
**Couverture** : France uniquement. Les adresses étrangères sont acceptées mais sans coordonnées GPS.
**Déduplication** :
1. Par identifiant API (`id_apidatagouv`) — si disponible
2. Par coordonnées GPS (± 1 μ° ≈ 11 cm)
3. Par (numéro, rue) — fallback
**Hiérarchie créée** : Country → State → City → ZipCode → Street → Address
---
## 4. Déduplication des réseaux sociaux
À l'import (vCard et iCalendar), gestcontact déduplique les `SocialNetwork` par URL :
1. Cherche un `SocialNetwork` existant avec la même URL
2. Si trouvé → réutilise l'objet existant (pas de doublon)
3. Si non trouvé → crée un nouveau `SocialNetwork` avec `name=<code>`, `url=<url>`, `social_data_username=<X-USER si présent>`
---
## 5. Références RFC
| Standard | RFC | Année | Lien |
|----------|-----|-------|------|
| vCard 3.0 | RFC 2426 | 1998 | https://tools.ietf.org/html/rfc2426 |
| vCard 4.0 | RFC 6350 | 2011 | https://tools.ietf.org/html/rfc6350 |
| iCalendar 2.0 | RFC 5545 | 2009 | https://tools.ietf.org/html/rfc5545 |
| iCalendar updates | RFC 7986 | 2016 | https://tools.ietf.org/html/rfc7986 |
La convention `X-SOCIALPROFILE` est une extension propriétaire popularisée par Apple/iOS, compatible avec de nombreuses applications (Thunderbird, Google Contacts, etc.). Elle n'est définie dans aucune RFC mais son usage est standardisé de facto.
---
## 6. URLs gestcontact
| Action | URL |
|--------|-----|
| Import vCard → Personne | `/people/import-vcard/` |
| Import vCard → Organisation | `/organisations/import-vcard/` |
| Import vCard → Localisation | `/localisations/import-vcard/` |
| Import iCal → Événement | `/events/import-ical/` |
| Export vCard Personne | `/export/people/<id>/vcf/` |
| Export vCard Organisation | `/export/organisation/<id>/vcf/` |
| Export vCard Localisation | `/export/localisation/<id>/vcf/` |
| Export iCal Événement | `/export/event/<id>/ical/` |
| Documentation normes (web) | `/norms/` |
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment