Mon CV

Kerio Connect et import régulier de VCards

31 mars 2013

Dans la structure dans laquelle je travaille nous disposons d’un outil type CRM développé sur mesure (PHP/SQL). D’un autre côté nous utilisons avec bonheur depuis plusieurs années Kerio Connect comme solution de Groupware (mails, calendriers, carnets d’adresse).

L’intégration de Kerio (via le protocole Exchange) sur les terminaux mobiles est parfaite et nous trouvions dommage de ne pas pouvoir utiliser le répertoire “Public” de Kerio pour pouvoir accéder en consultation aux coordonnées de contacts de notre CRM.

Précisons en plus Kerio est hébergé sur un Mac OS X Server 10.6 et que notre CRM tourne sur un Debian Squeeze.

Pour réaliser cela nous sommes partis sur le principe :

1. D’un script PHP sur le serveur hébergeant le CRM qui réalise un export de la totalité des contacts en VCard v3 (ce script sera appelé périodiquement via curl).

2. D’un script lancé périodiquement sur l’OS X Server hébergeant Kerio Connect. Ce script (appelé via un LaunchDaemons) est chargé :

  • De générer à distance les VCards (via le script PHP appelé par curl évoqué plus haut)
  • De télécharger ce fichier VCards (toujours grace à curl)
  • De traiter ces VCards en les découpant, puis en générant des fichiers .eml contenant les informations de contact (pour cette partie j’ai réutilisé un script trouvé ici http://aplawrence.com/Kerio/webmail_import_contacts.html que j’ai un peu modifié). N’étant pas un as de Perl j’ai choisi d’appeler ce script modifié depuis mon script shell. Je sais, c’est pas ultra propre pour les puristes … mais ça marche.
  • Le tout en enregistrant une liste des modifications et en générant des journaux pour pouvoir débugger le cas échéant …
  • Pour finir, on force la réindexation du répertoire public de Kerio Connect en supprimant le fichier d’index et en redémarrant en ligne de commande Kerio.

Voici donc le script shell qui réalise la majorité du travail (certaines parties sont à adapter évidemment si vous souhaitez le réutiliser ….) :

#!/bin/sh
CURRENT_DIR=$(dirname $0);
INPUT="$CURRENT_DIR/tmp/bdd-vcard-avec-liens.vcf";
INPUT_REVIEW="$CURRENT_DIR/tmp/bdd-vcard-avec-liens2.vcf";
OUTPUT_TEMP_DIR="$CURRENT_DIR/out-temp";
LAST_FILE="$CURRENT_DIR/lastfile.tmp";
LOG="$CURRENT_DIR/current.log";
LOG_CUMUL="/var/log/Kerio_import_vCards.log";
LAST_FILE_LIST="$CURRENT_DIR/lastlist.tmp";
OLD_VCARDS="$CURRENT_DIR/old-vCards";
## Le script qui sera intercalé en Perl
SCRIPT_PERL_EXPORT="$CURRENT_DIR/export.pl";
KERIO_PUBLIC_STORE="/usr/local/kerio/mailserver/store/mail/XXXXXXXXXXX/#public/Contacts";
OUTPUT_DIR="$KERIO_PUBLIC_STORE/#msgs";
MAIL_ADMIN="moi@moi.moi";
DATE_DU_JOUR=$(date);

if [ `whoami` != 'root' ]
then
echo "Ce script doit être utilisé par le compte root. Utilisez SUDO."
exit 1
fi

rm -f $LOG
echo " " >> $LOG
echo "****************************** $DATE_DU_JOUR ******************************" >> $LOG

#testons si une connection internet est ouverte { }
curl -f http://checkip.dyndns.org
ERROR=$(echo $?)

if [ $ERROR -ne 0 ]
then
echo "ERROR checkip.dyndns.org : " $ERROR >> $LOG
echo "Non connecté à internet. Nous quittons le script." >> $LOG
exit 0
else 

# générons le vCard sur le site distant http://XXXXXXXXX.php
cd $CURRENT_DIR;
curl -k https://www.test.fr/bdd-vcard.php?liens; ## adresse du script distant sur le CRM permettant de générer un export au format VCARD. 

# récupérons le fichier généré dans un répertoire temporaire
mkdir $CURRENT_DIR/tmp;
cd $CURRENT_DIR/tmp;
rm -f $INPUT;
rm -f $INPUT_REVIEW;
curl -O -k https://www.test.fr/bdd-vcard-avec-liens.vcf;

# supprimons par sécurité les lignes vierges dans le fichier généré
sed '/^$/d' $INPUT > $INPUT_REVIEW
mv $INPUT_REVIEW $INPUT

# testons si un import a déjà été réalisé
# testons si une liste de fichier existe / return-code = 1 si fichier absent
test -f $LAST_FILE_LIST
RETURN_CODE=$?
PREVIOUS_IMPORT=0
if [ $RETURN_CODE -eq 1 ]
	then 
	echo "Pas de précédent import détecté" >> $LOG
	else
	VAR=`wc -w $LAST_FILE_LIST | awk '{print $1}'`
	if [ "$VAR" -eq 0 ] 
		then
		echo "Pas de précédent import détecté" >> $LOG
		else PREVIOUS_IMPORT=1
		echo "Une précédente importation a été trouvée" >> $LOG
		# récupérons les noms des vCardS importées lors du précédent import
		# déplacons les vCard importées lors du précédent import réussi dans le fichier old
		# par précaution vidons le avant tout 
		rm -R $OUTPUT_TEMP_DIR;
		cd $CURRENT_DIR;
		rm -R $OLD_VCARDS;
		mkdir $OLD_VCARDS;
		cd $OUTPUT_DIR;
		for FILE in $(cat $LAST_FILE_LIST); do mv "$FILE" $OLD_VCARDS/ ; done
	fi
fi	

# comptons et listons les fiches vCard encore présentes et plaçons le dernier nom dans un fichier $LAST_FILE
NBFILE=$(ls -A1 $OUTPUT_DIR/*.eml | wc -l);
echo "Il y a actuellement " $NBFILE " contacts dans le répertoire PUBLIC CONTACTS de Kerio" >> $LOG;
cd $OUTPUT_DIR;
LISTE=$(ls -A1 *.eml);
echo "Liste des fichiers présents (hors dernier import) : " $LISTE >> $LOG;
LAST=${LISTE: -12};
echo "Le dernier contact porte le nom suivant : " $LAST >> $LOG;
LAST_NAME=$(echo $LAST | cut -d"." -f1);

# écriture dans un fichier tmp $LAST_FILE du nom du dernier fichier à ne pas écraser
# par précaution écrasons le fichier de passage avant d'écrire dedans
rm -f $LAST_FILE;
echo $LAST_NAME > $LAST_FILE;

# comptons le nombre de fiches vCard à importer
TEST_GREP=$(grep -c "BEGIN:VCARD" ${INPUT})
TEST_GREP2=$(grep -c "END:VCARD" ${INPUT})
if [ $TEST_GREP -gt $TEST_GREP2 ]
	then NUMBER=$TEST_GREP
	else NUMBER=$TEST_GREP2
fi

# lançons le script Perl qui exporte le vCard en fichiers eml séparés
# préparons le répertoire temp
mkdir -p $OUTPUT_TEMP_DIR;
/usr/bin/perl "$SCRIPT_PERL_EXPORT";
RETURN_CODE_PERL=$?
echo "Code retour PERL : $RETURN_CODE_PERL" >> $LOG;
if [ $RETURN_CODE_PERL -eq 0 ]
	then 
	echo "Pas de problème détecté lors de la création des fichiers vCards en .eml." >> $LOG

	# enregistrons la liste des fichiers importés dans notre fichier $LAST_FILE_LIST
	# par précaution supprimons le avant
	cd $OUTPUT_TEMP_DIR;
	LISTE2=$(ls -A1 *.eml);
	rm -f $LAST_FILE_LIST;
	echo $LISTE2 > $LAST_FILE_LIST;

	# déplaçons les fichiers créés dans le répertoire STORE PUBLIC de KERIO
	cd $OUTPUT_TEMP_DIR
	for FILE in $(cat $LAST_FILE_LIST); do mv "$FILE" $OUTPUT_DIR/ ; done

	# réindexons le répertoire STORE PUBLIC de KERIO
	rm -f $KERIO_PUBLIC_STORE/index.bad
	mv $KERIO_PUBLIC_STORE/index.fld $KERIO_PUBLIC_STORE/index.bad
	/usr/local/kerio/mailserver/KerioMailServer stop
	sleep 60
	/usr/local/kerio/mailserver/KerioMailServer start
	sleep 60

	# enregistrons la trace dans le LOG
	DATE_DU_JOUR=$(date)
	DEBUT_LOG=$(echo "$NUMBER vCards importées avec succès le ")
	echo $DEBUT_LOG $DATE_DU_JOUR
	echo $DEBUT_LOG $DATE_DU_JOUR >> $LOG;
	cat $LOG | mail -s "[OK] Rapport execution script import vCards (${0})" $MAIL_ADMIN 
	cat $LOG >> $LOG_CUMUL
	rm -f $LAST_FILE
	exit 0;

	else
	echo "Problème détecté : l'import des vCards n'est pas effectué correctement." >> $LOG
	if [ $PREVIOUS_IMPORT == "1" ]
		then
			echo "Nous vidons le répertoire temporaire du Script et déplaçons à nouveau les fichiers pour rétablir le STORE PUBLIC de KERIO." >> $LOG
			cd $OLD_VCARDS;
			for FILE in $(cat $LAST_FILE_LIST); do mv "$FILE" $OUTPUT_DIR/ ; done ;
			rm -R $OLD_VCARDS;
	fi

	# gardons une trace de l'erreur dans les logs
	DATE_DU_JOUR=$(date)
	DEBUT_LOG=$(echo "Les $NUMBER vCards n'ont pas été importées correctement le ")
	FIN_LOG=$(echo " - Code d'erreur : ")
	echo $DEBUT_LOG $DATE_DU_JOUR
	echo $DEBUT_LOG $DATE_DU_JOUR $FIN_LOG $RETURN_CODE_PERL >> $LOG;
	cat $LOG | mail -s "[FAILED] Rapport ERREUR script import vCards (${0})" $MAIL_ADMIN 
	cat $LOG >> $LOG_CUMUL

	# petit nettoyage avant de terminer
	rm -R $CURRENT_DIR/tmp;
	rm -R $OUTPUT_TEMP_DIR;
	rm -f $LAST_FILE;
	exit 1;
fi
fi

Côté Perl, le script qui découpe notre VCARD est le suivant :

#!/usr/bin/perl
$CURRENT_DIR="/usr/local/Kerio_import_vCards";
$INPUT="$CURRENT_DIR/tmp/bdd-vcard-avec-liens.vcf";
$OUTPUT_TEMP_DIR="$CURRENT_DIR/out-temp";
$LAST_FILE="$CURRENT_DIR/lastfile.tmp";

my $FILE=$LAST_FILE;
open(FIC,$FILE) or exit(1);
$LIGNE=<FIC>;
chop($LIGNE);
$DECVAL= hex($LIGNE);
$VALEUR = sprintf("%u", $DECVAL);
$X=$VALEUR+1;

open(I,$INPUT);
writefile();

while (<I>) {
 chomp;
 $NOMHEXA=sprintf "%0.8x.eml\n",$X;
 print "Création du fichier contact $X : $NOMHEXA";
  if (/^END:VCARD/) {
   print O "$_\n";
   close O;
   $X++;
   writefile() if not eof(I);
   next;
   }
print O "$_\n";
}

sub writefile {
   $OFILE=sprintf "%0.8x.eml\n",$X;
   open(O,">$OUTPUT_TEMP_DIR/$OFILE");
   print O <<EOF;
Subject: 
Date: Sun, 25 Mar 2012 11:29:38 -0400
Content-Type: text/vcard; charset="utf-8"
Content-Transfer-Encoding: 8bit

EOF
}
exit(0);
Posted in Apple et Macintosh, Unix et LinuxTags: