Générer un fichier .MAB (Mozilla Adresse Book) avec un script PHP

Article purement technique. Lecteurs habituels du blog et profanes, veuillez passer votre chemin et nous laisser entre nous, merci :)

Je me suis mis dans l'idée hier de permettre à Mozilla Thunderbird d'utiliser un annuaire d'entreprise non basé sur LDAP, mais sur une base Mysql.
Cet article me permet de faire le point sur le sujet et de livrer le fruit de mes recherches à la Communauté du Libre gourmande de moulinettes en tout genre qui relèguent la pierre philosophale au rang des inventions inutiles et idiotes.

Mozilla Thunderbird peut rechercher des adresses mails dans différentes sources :
- Dans un annuaire LDAP (Outils - Options - Rédaction - Adressage - Serveur D'annuaire)
- Dans le carnet d'adresses "par défaut" (abook.mab dans le profil de Thunderbird)
- Dans les adresses collectées automatiquement (les gens qui vous écrivent et ceux à qui vous écrivez : history.mab dans le profil de Thunderbird)
- Dans tout autre carnet d'adresses personnel, créé par l'utilisateur et figurant en *.mab dans le profil de Thunderbird

Jusqu'ici, nous étions sous Exchange, qui malgré ses défauts, propose une entrée LDAP dans son annuaire, je n'avais donc pas à me soucier de l'intégration de l'annuaire d'entreprise dans Thunderbird.
Aujourd'hui, nous avons migré vers une solution de messagerie et travail collaboratif basée sur des briques libres, et notamment sur Mysql qui renferme le carnet d'adresses et les utilisateurs dans une base à laquelle Postfix fait appel. Plus d'annuaire LDAP, donc plus d'annuaire d'entreprise sous Thunderbird, et donc : problème.

Je vous passe les détails qui m'ont fait arriver à la conclusion suivante : il faut que j'arrive à partager un carnet d'adresses Thunderbird qui sera généré régulièrement par un script PHP qui attaque la base Mysql. Et à partir de là, le problème se scinde en deux :

1. Partager un carnet d'adresses avec Thunderbird

Fort heureusement, d'autres se sont posés la question avant moi et je n'ai eu qu'à tester et approuver leur solution : utiliser l'extension AddressBooksSynchronizer qui permet au démarrage et à la fermeture de Thunderbird, ainsi qu'à n'importe quel moment en le forçant, de récupérer un carnet d'adresses distant (sur un lecteur réseau, via ftp, http, https ou même IMAP), ou au contraire de publier un carnet d'adresses de Thunderbird.

Il s'agit d'une bête copie de fichier .MAB sans intelligence aucune (pas de synchronisation différentielle, ni de détection des manquants ou des nouveaux : on écrase la cible avec la source, un point c'est tout). Et c'est précisément ce qu'il me fallait pour mon annuaire d'entreprise : un carnet d'adresses généré quelque part par "quelque chose" et que tous les utilisateurs vont piocher au démarrage de leur Thunderbird.
Restait à trouver ou à fabriquer le "quelque chose" en question.

2. Générer un .MAB à partir de Mysql

Là, ce fut plus compliqué, car à part un logiciel (certes gratuit, mais dont le code n'est pas fourni) intitulé Dawn qui sait transformer toute sorte de choses en .MAB, je n'ai pas réussi à mettre la main sur un script qui sache produire du .MAB (en fait, le format d'un fichier .MAB s'appelle Mork).
Innocent que j'étais encore hier, je me disait qu'un format de fichier utilisé par un logiciel libre à succès comme Thunderbird ne pouvait être que clair, efficace et fort bien documenté. Je suis donc parti à la recherche d'une description dudit format .MAB , et là, je n'ai pas été déçu !
C'est apparemment de notoriété public un truc purement incompréhensible.
Pourtant, le format est utilisé dans Thunderbird et Firefox, pour stocker des carnet d'adresses, mais aussi des historiques de navigation. C'est un ingénieur de feu-Netscape, David McCusker, qui, à l'époque, avait pondu ce ... truc censé être un "generic textual database file format "loosely inspired by LISP"... Ça fait froid dans le dos...

Evidemment la grammaire du langage utilisé ne nous aide pas beaucoup, tout juste on s'assure que la chose est vraiment imbitable, illisible par un humain et parfaitement ignoble à décrypter, même avec un logiciel dédié.
Jamie Zawinski, qui semble être le seul à avoir pondu un parser mork en perl qui permet de lire le contenu d'un fichier mork, n'y va d'ailleurs pas par quatre chemins, je le cite (en traduisant) :
Deux espaces de noms numériques qui se chevauchent, encodage des caractères spéciaux tantôt par anti-slash, tantôt par encodage hexadécimal avec un "$", "//" utilisé tantôt comme déclaration de commentaires (comme en c++), tantôt dans les adresses URL (NdT : ben oui : http://), compression des données désastreuses (*3 ou *6 !), non lisible par un humain, non éditable à la main, le seul avantage est qu'il utilise des lignes courtes et aucun caractères binaires, ce qui a pour effet d'augmenter sensiblement la taille des fichiers !

Malheureusement, moi, ce n'était pas d'un parser, dont j'avais besoin, mais d'un code qui produit du mork, à partir d'une base Mysql. Et je dois dire qu'à la lecture de tout ceci, j'ai failli abandonner.
J'ai quand même tenté la bonne vieille méthode de reverse-engineering, en créant un carnet d'adresses basique avec un seul nom à l'intérieur, pour voir à quoi ressemblait alors le .MAB. Cela mérite un petit copier-coller, voici donc un carnet d'adresses avec une seule adresse à l'intérieur, tel qu'il est généré par Thunderbird :



Je vous ai mis des couleurs pour que vous compreniez tout au premier coup d'oeil. C'est clair, hein ?!

Nous avons donc en rouge la description du fichier et des colonnes qui sont gérées par la base de données qu'il représente. Il suffit de faire un bête copier-coller de cette partie là, qui ne change pas d'un .MAB à l'autre.
La zone en bleue semble décrire les informations qui vont suivre. Là encore, quand on ne sait pas, on se contente de copier-coller.
En vert, vous retrouvez les données réelles, Nom, Prénom et Adresse mail du contact que j'ai saisi, ainsi que le numéro de téléphone. Ces données sont mises dans des cellules, qui sont numérotées de 81 à 88, en commençant par 88, pour faire un genre. Notez aussi le codage rigolo avec des "$" pour les caractères accentués.
En dessous, en violet, l'affectation des cellules aux colonnes décrites au-dessus. (^84^82) signifie naturellement, que dans la colonne numérotée 84 ("LastName"), vous allez mettre la donnée numérotée 82 ("Nom"). Comme j'ai saisi très peu de renseignement pour ce contact, la plupart des colonnes sont remplies de vide : (^AB=) signifie par exemple que cet enregistrement n'a pas de "Anniversary Month"
Je vous passe les petits mots de liaison qui sont restés en noir ci-dessus, tellement j'ai été incapable de résumer leur utilité.

Quand on saisi un second contact, la structure du fichier change un peu, ce qui montre toute l'absurdité, toute la souplesse du code mork généré par Thunderbird. Une fois que j'ai trouvé une structure qui me plaisait, je me suis fixé dessus, et j'ai tenté d'écrire un code PHP qui produit un fichier mork soluble dans Thunderbird. Et chose incroyable, j'ai réussi. Cliquez ici pour voir le code source commenté.

Le tour était joué, il ne me restait plus qu'à poser un cron sur mon script PHP pour qu'il génère régulièrement un annuaire d'entreprise à jour, à partir de la base Mysql, et à paramétrer l'extension de Thunderbird pour qu'elle aille chercher le .MAB généré à chaque ouverture du courrielleur. La synchronisation dans l'autre sens ne m'intéresse pas pour l'instant (heureusement : c'est encore un autre casse-tête !).



Y a pas à dire, quand on joue avec des logiciels libres, on finit toujours par arriver à nos fins et comme c'est en général très compliqué, on est encore plus fiers de nous au final. Ben oui : avec Exchange et Outlook, tout ceci est immédiatement fonctionnel, c'est même pas drôle...

Commentaires

1. Le jeudi, 28 décembre 2006, 19:07 par Bob

Eh ben. À tes souhaits. Moi je viens d'installer une carte Wifi dans le PC du bureau, et heureusement c'était bien plus facile :)

2. Le jeudi, 28 décembre 2006, 21:32 par bencandas

mal de tête merci merome ...


Sinon ben gg encore une fois ^^

3. Le jeudi, 28 décembre 2006, 21:34 par Stef

Et dire que certains disent que Wargang est compliqué...

4. Le jeudi, 28 décembre 2006, 21:36 par Goran!

T'as d'la chance Bob, moi j'ai même pas réussi lol!

5. Le vendredi, 29 décembre 2006, 12:05 par Filou

Le pavé rose on dirait presque une partie de bataille navale ! :-D

6. Le mercredi, 3 janvier 2007, 13:42 par Eric

Vous auriez pu utiliser la base LDAP de Active Directory ... Mais tu y as déjà probablement pensé, Ô grand Mérome.
LDAP > SQL
... à vrai dire je suis probablement la seule personne qui connait mieux LDAP que SQL et pour ceux qui m'ont vu travailler avec SQL, vous comprendrez qu'il n'en faut pas beaucoup pour surpasser mes connaissances.

7. Le jeudi, 1 février 2007, 09:54 par Kaïros

J'ai une colle qui semble de ton niveau :
Après que j'ai créé un nouveau compte, les fichiers .mab n'ont pas été repris dans le nouveau carnet d'adresse. La fonction d'inportation du carnet d'adresse ne comprend pas l'extension ".mab". Les fichiers apparaissent sur l'interface Thunderbird mais je ne parviens pas à les réintroduire dans le carnet d'adresse. As-tu un conseil ?

8. Le vendredi, 13 avril 2007, 08:35 par Dom21fr

Argh, merci. Je veux faire exactement la même chose. Voilà qui va booster mon projet !

9. Le vendredi, 13 avril 2007, 11:18 par Dom21fr

Oups, j'ai parlé trop vite. Ca ne marche pas. Mes .mab n'ont pas tout à fait la même structure et le .mab généré par le script méromien (adapté à ma base MySql) n'est pas lisible par TBird.
Comme dit Wikipedia : "Mork is generally regarded as unintelligible to humans"
Confirmé !
Snif.

10. Le lundi, 18 juin 2007, 17:36 par mimochasam


Bonjour

Avant de me lancer dans l'aventure à mon tour ! est-ce que cela fonctionne vraimant !? car je n'ai pas la même structure de fichier mab. Mais je suis T2+.

Merci


<(8D=3)(81=)(82=Michel Test)(83=Michel.Test6666@isped.fr)(84
=michel.test55@isped.fr)(80=0)(85=1)(86=Michel Test0000 2)(87
=Michel.Test2@isped.fr)(88=michel.test2@is0000ped.fr)(89=2)(8A
=Michel Test 3)(8B=Michel.Test3@is99999ped.fr)(8C=michel.test3@isped.fr)>
{1:^80 {(k^C0:c)(s=9)}

11. Le mardi, 19 juin 2007, 09:38 par Merome
mimochasam : c'est en production chez moi depuis le mois de décembre en tout cas. Le fichier MAB prend des formes parfois bizarres. Il semble que la forme générée par mon script soit bien tolérée par Thunderbird (version 2.0.0.4 (20070604)).
12. Le mardi, 19 juin 2007, 17:16 par mimochasam


Merci
Ma molinette sera en VB je pense !

13. Le samedi, 23 juin 2007, 11:37 par mimochasam


un collègue programmeur à trouvé cette solution
XML >- (avec xslt)-> LDIF >- (avec Dawn en ligne de commande) -> MAB
juste pour Full name et email pour les commentaires is to hard

14. Le vendredi, 19 octobre 2007, 17:07 par matthieu

très très intéressant, merci beaucoup, je m'en servirai

mais là j'ai le problème inverse à résoudre rapidement : 121 fichiers MAB à intégrer dans ma base de données MySQL, je ne vois pas comment faire (en plus, je dois récupérer à chaque fois le nom du fichier MAB dans un champs MySQL)

vous auriez une idée, un programme à conseiller ?

dawn ne le fait que un à un, et sans mettre le nom du fichier dans un champs bien sûr...

15. Le lundi, 12 novembre 2007, 14:00 par Guillaume

Apparement, il existe un parseur perl pour le format mork, en le modifiant, on doit pouvoir en sortir du code SQL.

16. Le lundi, 25 février 2008, 14:49 par fastrvb

Je cherche a le faire en vbs.
Quelqu'un aurait-il avancé sur ce sujet ?

17. Le mardi, 24 juin 2008, 17:11 par Guimo

Super intéressant. J'en ai justement besoin pour gérer mon carnet partager Horde/Turba (mysql) et thunderbird.

Il va falloir que je fasse quelques modifs, tu ne gères pas les listes de distribution

18. Le mercredi, 13 août 2008, 13:03 par Matt

Merci, tu me sauves non pas la vie, mais quelques heures de creusage de tete ^^

19. Le samedi, 19 septembre 2009, 15:14 par zelda4

Bonjour,

Article fort intéressant qui pourrait m'être très utile...
Mais, je ne sais pas si j'arrive un peu tard, la page "Cliquez ici pour voir le code source commenté." n'existe plus ....

Est-ce que quelqu'un peut me montrer ce fameux code source commenté???

Merci d'avance.

Zelda4

20. Le samedi, 19 septembre 2009, 17:21 par Merome

J'ai corrigé le lien foireux.

21. Le dimanche, 20 septembre 2009, 08:58 par zelda4

Merci beaucoup, je vais étudier tout ça!!!!

22. Le mardi, 1 décembre 2009, 09:35 par bmg

Super point de départ pour articuler notre base de données contacts mysql et thunderbird sans passer par un server ldap. Dans notre cas, nous avions des contacts individuels et des listes de contacts individuels, j'ai généralisé le code pour qu'il génère aussi les listes d'email.

Enjoy.

<?php
// this code produces a .mab address book for use in thunderbird. it features individual contact emails
//(the original code from merome.net) and email lists
// thanks to Merome - postmaster@merome.net for the initial retroengineering
// fell free to reuse & abuse. if you make substantial enhancements, please let me know ! webmaster at fishbonelive dot org
// 2009-12-01

function list_group_members_2($idgrp,$list=array("cont"=>array(),"group"=>array())){
// adapt to your own architecture (in this case contacts and groups can be members of groups)
// returns an array of the following structure
//array("cont"=>array(contact_id=>contact_data),
// "group"=>array(group_id=>group_data))
return $list;
}

function wordwrap_other($str, $width = 75, $linedelimiter="\n", $break = "\n",$limit=" "){
// adds $break if line > $width after character $limit (php wordwrap() breaks lines only at spaces)

       $lines =  explode($linedelimiter, $str);

foreach($lines as $line){
if(mb_strlen($line)>=$width){
$str = explode($limit, $line);
$len = 0;
foreach ($str as $val){
$val .= $limit;
$tmp = mb_strlen($val);
$len += $tmp;
if ($len >= $width){
$return .= $break . $val;
$len = $tmp;
} else $return .= $val;
}
$return=substr($return,0,mb_strlen($return)-1);
} else $return.=$line;
$return.="\n";
}

       return $return;

}

//this is the mork dictionnary in the form (id=field)
//all ids are hexadecimal
// the mork dictionnary is later completed with (id=address_i) fields made necessary for lists
$dict= <<< END
// <! <mdb:mork:z v="1.4"/> >
< <(a=c)> // (f=iso-8859-1)
(B8=Custom2)(B9=Custom3)(BA=Custom4)(BB=Notes)(BC=LastModifiedDate)
(BD=RecordKey)(BE=AddrCharSet)(BF=LastRecordKey)
(C0=ns:addrbk:db:table:kind:pab)(C1=ListName)(C2=ListNickName)
(C3=ListDescription)(C4=ListTotalAddresses)(C5=LowercaseListName)
(C6=ns:addrbk:db:table:kind:deleted)
(80=ns:addrbk:db:row:scope:card:all)
(81=ns:addrbk:db:row:scope:list:all)
(82=ns:addrbk:db:row:scope:data:all)(83=FirstName)(84=LastName)
(85=PhoneticFirstName)(86=PhoneticLastName)(87=DisplayName)
(88=NickName)(89=PrimaryEmail)(8A=LowercasePrimaryEmail)
(8B=SecondEmail)(8C=DefaultEmail)(8D=CardType)(8E=PreferMailFormat)
(8F=PopularityIndex)(90=AllowRemoteContent)(91=WorkPhone)
(92=HomePhone)(93=FaxNumber)(94=PagerNumber)(95=CellularNumber)
(96=WorkPhoneType)(97=HomePhoneType)(98=FaxNumberType)
(99=PagerNumberType)(9A=CellularNumberType)(9B=HomeAddress)
(9C=HomeAddress2)(9D=HomeCity)(9E=HomeState)(9F=HomeZipCode)
(A0=HomeCountry)(A1=WorkAddress)(A2=WorkAddress2)(A3=WorkCity)
(A4=WorkState)(A5=WorkZipCode)(A6=WorkCountry)(A7=JobTitle)
(A8=Department)(A9=Company)(AA=_AimScreenName)(AB=AnniversaryYear)
(AC=AnniversaryMonth)(AD=AnniversaryDay)(AE=SpouseName)(AF=FamilyName)
(B0=DefaultAddress)(B1=Category)(B2=WebPage1)(B3=WebPage2)
(B4=BirthYear)(B5=BirthMonth)(B6=BirthDay)(B7=Custom1)
END;

$groupsize=70;// limit size of list, for instance for use with gmail's smtp server that limits emails to 70 recipients. set to 0 to disable group splitting. groups are split as groupname_i
$cpt=512; // $cpt: start id of data fields dec512=hex200
$id=0; // $id: record ids
$maxsize=0; // largest list
$count_80=0; // number of ^80 fields - card
$count_81=0; // number of ^81 fields - lists
$count_82=1; // number of ^82 fields - data
// build the contact data & contact mork records
$contacts=mysql_query("select id,fname,lname,email from contact order by id asc");
while($p=mysql_fetch_assoc($contacts)){
$id80$p[id]=++$count_80; // feed array associating contact_ids from the DB and mork^80 record_ids
// build the mork contact data ($data_p) and the mork ^80 records ($affect_80 format:"(^dict_id^data_id)")
$affect_80.="\n[".dechex($count_80).":^80";
$data_p.="(".dechex(++$cpt)."=".$p"fname".")"; // first name
$affect_80.="(^83^".dechex($cpt).")"; // ^83 : FirstName
$data_p.="(".dechex(++$cpt)."=".$p"lname".")"; // last name
$affect_80.="(^84^".dechex($cpt).")"; // ^84 : LastName
$data_p.="(".dechex(++$cpt)."=".$p"lname"." ".$p"fname".")"; // display name
$affect_80.="(^87^".dechex($cpt).")"; // ^87 : DisplayName
$data_p.="(".dechex(++$cpt)."=".strtolower($p"EmailP").")"; // email address
$affect_80.="(^89^".dechex($cpt).")"; // ^89 : PrimaryEmail
$affect_80.="(^8A^".dechex($cpt).")"; // ^8A : LowercasePrimaryEmail (!)
// add more data here to the mork record
// $data_p.="(".dechex(++$cpt)."=".$p"data".")";
// $affect_80.="(^XX^".dechex($cpt).")"; // ^XX : data
// close the data by a unique id
$data_p.="(".dechex($cpt)."=".dechex($id).")"; // some identifier
$affect_80.="(^BD=".dechex($id).")]";
}
// build the list data & list mork records
// /!\ if a list references as member a mork contact record (^80) whose id is larger than hex B33 / dec 2867
// this code will fail. so basically, you cannot have export more than 2867 contacts to a mab file with lists.
$groups=mysql_query("select group_id,group_name from group");
while($group=mysql_fetch_array($groups)){

	$datag=list_group_members_2($group["group_id"]);

$size=count($datag"cont");
unset($group_safe);
// slice up groups so that they do not contain more than $groupsize members
if($groupsize>0) for($j=0;$j<=intval($size/$groupsize);$j++) $group_safe$j=array_slice($datag"cont",$j*$groupsize,$groupsize,true);
else $group_safe=$datag"cont";
for($j=0;$j<count($group_safe);$j++){
$k=198; // the start id of the (id=Address_i) dictionnary part
unset($affect_81_temp);
$size_sub=count($group_safe$j);
if($size_sub>$maxsize) $maxsize=$size_sub;
foreach($group_safe$j as $key=>$pers) $affect_81_temp.="(^".dechex(++$k)."=".dechex($id80$key).")";
if($size>$groupsize) $data_g.="(".dechex(++$cpt).'='.$group"group_name"."_".($j+1).')';
else $data_g.="(".dechex(++$cpt).'='.$group"group_name".')';
$affect_81.="\n[".dechex(++$count_81).':^81'; //the mork^81 list id
$affect_81.='(^C1^'.dechex($cpt).')'; //C1 list name
$affect_81.='(^C5^'.dechex($cpt).')'; //C5 lowercaselistname
$data_g.="(".dechex($cpt).'='.dechex($id).')';
$affect_81.="(^C4=".$size_sub.")"; //C4 list size
$affect_81.=$affect_81_temp; // the list members mork^80 ids
$affect_81.=."(^BD=".dechex($id).")";
$affect_81.="]";
}
}
//list addresses dictionnary
for($i=1;$i<=$maxsize;$i++) {
$dict.='('.dechex($i+198).'=Address'.($i).')';
}
//putting the mork file together
$data="\n<(".dechex(512)."=0)".$data_p."\n".$data_g."\n>";
$affect_82="\n1:^82(^BF=".dechex($id).")";
$mork=$dict.">\n".$data."\n{1:^80 {(k^C0:c)(s=9)}".$affect_82.$affect_80.$affect_81."\n }";
$specialchars1 = array('é','è','ç','à','â','ê','û','î','ô','ù','ë','ü');
$specialchars2 = array('$C3$A9','$C3$A8','$C3$A7','$C3$A0','$C3$A2','$C3$AA','$C3$BB','$C3$AE','$C3$B4','$C3$B9','$C3$AB','$C3$BC');
$mork = str_replace($specialchars1, $specialchars, $mork);
//word wrap the long lines at 72 chars, break the lines at closing parenthesis
$mork=wordwrap_other($mork,72,"\n","\n",")");
// do whatever you want with $mork => send to browser, save to file,...
?>
/code

23. Le mercredi, 7 avril 2010, 17:01 par astrancia

Le code est excellent, cependant les "crochets" d'index des tableaux ne sont pas passés dans le texte.
Pour utiliser le $mork directement dans le flux, pour utilisation avec AdressBookSync il ne faut pas omettre de transmettre le header last-modified :

exemple :
header('Content-type: application/octetstream');
header("Last-Modified: " . gmdate("D, d M Y H:i:s") . " GMT");
echo $mork;
die()

Utiliser, conjointement avec apache, les RewriteRules et .htaccess pour générer directement des ".mab"
Options +FollowSymlinks
RewriteEngine on
RewriteRule .mab$ script.php [L]

Récuperer le nom demandé, pour générer des requêtes SQL
$service=str_replace("%20"," ",trim(strtoupper(basename($_SERVER["REQUEST_URI"],".mab"))));
....
SELECT FROM table WHERE service=$service
....

24. Le lundi, 2 août 2010, 00:48 par tropcontent

Je ne suis qu'un petit bidouilleur qui n'a qu'un but satisfaire c'est petit délire DONC JE DIS MERCI A MEROME.

Je voulais juste dire que tout fonctionne avec son script il faut juste penser à retirer tout les <br> et les remplacer par des \n ou par un retour chariot.
Et là magie tout fonctionne. je ne sais pas si cela à déjà été dit car je n'ai pas lu tout les commentaires.

Donc on obtient pour l'exemple (ici j'ai enlever les <br> car le retour chariot pour ceux qui ne connaisse pas cela signfie la touche entrer suffit):
Avant :

 (80=ns:addrbk:db:row:scope:card:all)<br>
 (81=ns:addrbk:db:row:scope:list:all)<br>

Après :

 (80=ns:addrbk:db:row:scope:card:all)
 (81=ns:addrbk:db:row:scope:list:all)

Autre exemple important car c'est cette partie qui provoque un problème de création d'une entrée vide avec thunderbird :

Avant :

$affect="{1:^80 {(k^BF:c)(s=9)}<br> 1:^82(^BE=".$adresse["id".")]";
Après :
$affect="{1:^80 {(k^BF:c)(s=9)}\n 1:^82(^BE=".$adresse["id".")]";

25. Le vendredi, 17 septembre 2010, 14:36 par chrystalide

Bonjour,

Je suis également occupé sur des fichiers mab contenant plusieurs listes.

J'ai repris le code de bmg, mais j'ai des erreurs.
Deux tables mais comment réaliser la liaison entre l'utilisateur et une liste ?
Serait'il possible d'avoir le code dans un zip. Ce blog le modifie..

J'ai compris comment rajouter des utilisateurs dans une liste, j'ai deux listes mais pas moyen d'en rajouter une troisième.

Je peux fournir le fichier .mab si besoin.
Dans mon deuxième groupe j'ai
{-1:^80 {(k^BC:c)(s=9)}
1:^82(^BB=6)
2(^B8^8C)1:^81

J'utilise quelque chose dans le genre pour le troisième
{-1:^80 {(k^BC:c)(s=9)}
1:^82(^BB=7)1
2(^B8^8C)1:^81]
3(^B8^92)2:^89]

Mais la ligne avec le [3 ne passe pas :-(

Merci pour votre aide...

26. Le jeudi, 14 janvier 2016, 14:44 par Gloops

Ah, autant pour moi, la question semble ne plus être tellement d'actualité puisqu'à présent Thunderbird réalise l'import de fichiers CSV. Si on en croit l'interface il reconnaît aussi le format LDIF, mais ça il vaut mieux ne pas trop compter dessus pour le moment il me semble.

Pour l'import au format CSV voir là :
http://sites.estvideo.net/riccat63/...

Attention après avoir sélectionné le fichier de bien regarder en haut de la boîte de dialogue, et de vérifier si la case doit être cochée ou non.

Un champ qui contient une virgule doit être entouré de guillemets, mais ça on aurait peut-être deviné.

Ajouter un commentaire

Les commentaires peuvent être formatés en utilisant une syntaxe wiki simplifiée.

La discussion continue ailleurs

URL de rétrolien : https://merome.net/blog/index.php?trackback/291