Recherche sur le blog

mardi 13 mai 2014

[WD19] Utiliser l’API Exchange Web Services

Plutôt que d’utiliser les fonctions natives pour l’accès à Exchange, nous avons essayé d’accéder à un compte e-mail par l’intermédiaire de l’API “Exchange Web Services” version 2.0. Les bibliothèques sont proposées par Microsoft et peuvent être téléchargées sur le site web. Dans cet article, nous verrons comment nous connecter à Exchange, comment récupérer dix éléments de la boite de réception, et comment enregistrer une pièce jointe sur le disque dur, dans un répertoire temporaire. Les documentations MSDN et PC SOFT, ainsi que les différents sujets retrouvés sur de nombreux forums, ont permis d’aboutir à un résultat intéressant.

Télécharger les bibliothèques

Cette API est fournie par Microsoft et peut être téléchargée via le lien suivant : http://www.microsoft.com/e...s.aspx?id=35371. Le site vous proposera de télécharger le fichier adéquat en fonction de la version du système d’exploitation que vous utilisez (32 ou 64 bits).

Une fois l’API installée sur votre machine, deux bibliothèques DLL sont disponibles dans le dossier suivant : %ProgramFiles%\Microsoft\Exchange\Web Services\2.0. Ces assemblys pourront être importés dans le projet Windev de votre choix. Les deux fichiers “.dll” devront également être copiés ou installés sur la machine cliente.

Utiliser les assemblages

Dans votre projet Windev, ouvrez l’explorateur de projets, puis descendez jusqu’à l’arborescence “Assemblages .NET”. Effectuez ensuite un clic droit sur le titre de la catégorie, puis choisissez l’option “Utiliser un assemblage (…)”. Une nouvelle fenêtre s’ouvre alors.

WD_Assemblages_NET

Cliquez sur “Parcourir” puis sélectionnez “Microsoft.Exchange.WebServices.Auth” et “Microsoft.Exchange.WebServices” depuis le répertoire d’installation de l’API. Cliquez sur OK : l’arborescence est mise à jour et on voit alors apparaitre l’ensemble des objets qui peuvent être utilisés. On retrouve toutes les classes, tous les membres et les méthodes de celles-ci.

Se connecter à Exchange

A l’aide de l’outil de connectivité, on peut éventuellement s’assurer que l’accès est autorisé et que le service “autodiscover” est activé. Si ce n’est pas le cas, il est possible que vous rencontriez l’une ou l’autre erreur de connexion. Cela peut se traduire par des exceptions.

WD_Code_Connexion

Voyons quelles sont les étapes à réaliser :

  • La première chose que l’on doit faire est d’instancier un objet de type “ExchangeService”. Le paramètre du constructeur devra être l’une des constantes qui indique la version utilisée (ex : 2010 SP1).
  • Ensuite, pour se connecter, on va instancier un objet de type “WebCredentials” et le lier au service. Cet objet est utilisé pour les authentifications basées sur les mots de passe, comme NTLM ou Kerberos. Les trois paramètres du constructeur sont donc le nom d’utilisateur, le mot de passe et le domaine.
  • Enfin, il faut récupérer et valider l’URL du service “autodiscover”. La validation sera réalisée par l’intermédiaire d’un délégué. En Windev, il faut donc alors créer la procédure correspondante (“validateRedirectionUrl” dans notre exemple) qui possède un seul paramètre de type “chaine”.

Une fois que toutes ces opérations sont réalisées, si aucune exception n’a été déclenchée, c’est que la connexion a bien été effectuée. Dans ce cas, on peut essayer de récupérer le contenu de la boite de réception.

Analyse des éléments de la boite de réception

Nous allons maintenant récupérer dix objets de la boite de réception et afficher le sujet de chacun d’eux dans une fenêtre de trace de Windev. Pour commencer, il faudra déclarer une instance d’un objet de type “Folder”.

WD_Code_Inbox

Voyons quelles sont les étapes à réaliser :

  • Nous allons accéder au dossier en le liant au service par l’intermédiaire de la fonction “Bind” de la classe “Folder”. Pour éviter les erreurs liées aux types, nous créons les objets en deux temps.
  • Nous allons ensuite instancier un objet “FindResults” qui représente le résultat d’une recherche (fonction “FindItems”). Dans notre cas, nous souhaitons récupérer 10 éléments dans la boite de réception.

Notre instance de l’objet “FindResults” contient un membre qui se nomme “Items” et qui est du type “IEnumerable”, de ce fait il sera possible d’effectuer une boucle “POUR TOUT” (il s’agit en fait de l’équivalent du “foreach” en C#).

Lecture du sujet du mail

Dans la fameuse boucle que nous créons, nous allons faire en sorte de récupérer le contenu du sujet afin de l’afficher. Il faut donc charger l’e-mail en spécifiant son identifiant. On va aussi prévoir de charger l’ensemble des pièces jointes en le spécifiant clairement par l’intermédiaire d’une propriété, comme l’explique la documentation Microsoft.

WD_Code_Analyze

Voyons quelles sont les étapes à réaliser :

  • Avant la boucle, nous créons une variable de type “EmailMessage” en utilisant le constructeur qui prend en paramètre l’objet “ExchangeService”, que l’on a initialisé plus haut. Pour éviter les problèmes éventuels de conversion, nous avons réalisé les étapes en bouts de code séparés.
  • Dans la boucle, nous devons déclarer une collection de type “PropertyDefinitionBase” dans laquelle on stockera la constante “ItemSchema.Attachments”. Nous avons tenté d’écrire l’appel à la fonction “Bind” comme dans la documentation mais cela a généré une erreur de conversion.
  • Enfin, avec la fonction “Trace” ou “Info” (fonction Windev), nous pouvons afficher le sujet.

trace

Dans la trace précédente, nous avons également ajouté un petit compteur, juste dans un but de debugging. Le contenu des sujets mentionnés ci-dessus a été masqué pour une question de confidentialité.

Récupération d’une pièce jointe texte ou compressée

Dans notre e-mail, supposons qu’il existe une pièce jointe de type texte ou bien même une archive ZIP. Pour récupérer le fichier, nous avons dû adapter la proposition de la documentation MSDN pour que le code soit fonctionnel. Après plusieurs essais et quelques recherches sur la toile, nous avons enfin trouvé la méthode pour pouvoir récupérer le fichier et l’enregistrer dans un répertoire.

Dans la boucle où nous affichons le sujet de l’e-mail, nous avons effectué une seconde boucle pour analyser chaque pièce jointe. Certaines limitations nous empêchant d’effectuer des conversions, nous avons dû adapter l’une ou l’autre partie pour distinguer les fichiers des autres pièces jointes.

WD_Code_Attachment

Voyons quelles sont les étapes à réaliser :

  • Tout d’abord, nous allons déclarer un objet dynamique de type “FileAttachment”, si et seulement si nous retrouvons l’extension “.txt” ou “.zip” dans le nom. Si ce n’est pas le cas, nous ne traitons pas la pièce jointe. Bien sûr il aurait été préférable de comparer les types !
  • Ensuite, nous stockons l’objet issu de la boucle dans cet objet dynamique. Il ne nous reste plus qu’à le charger dans un fichier du même nom et ce dans le répertoire de notre choix (ici il est renseigné en “dur”).
  • Il ne faut bien sûr pas oublier de détruire les objets dynamiques qui ont été alloués (ce qui permet de libérer la mémoire utilisée par ceux-ci). Cela se fait grâce au mot-clé “libérer” du WLangage.

Le fichier sera alors automatiquement enregistré dans le répertoire indiqué, avec le nom qui a été attribué à la pièce jointe. Après il ne nous restera plus qu’à utiliser l’une ou l’autre fonction Windev pour effectuer le traitement de notre choix.

Interagir avec les e-mails

Sachez qu’il est également possible d’effectuer d’autres opérations, comme déplacer un message dans un autre dossier, voire le supprimer définitivement. Pour cela nous vous invitons à regarder de plus près la documentation MSDN qui est plutôt bien fournie.

10 commentaires:

Savi Pirl a dit…

Bonjour,

Tout dabord, grand merci pour ce tuto.

J'ai essayé votre code, mais j'obtiens un message d'erreur.

Pourriez vous y regarder et me dire si vous auriez une idée pour solutionner mon problème?
Note: j'ajoute bien les assemblage.net dans mon projet : System,Microsoft.exchange.webservices et Microsoft.exchange.webservices.aut

Voici l'erreur (voir post de savinien): http://forum.pcsoft.fr/fr-FR/pcsoft.fr.windev/140468-wd16-utilisation-assemblae-net-microsoft-exchange-webservices-181381/read.awp?hl=exchange

Vincent a dit…

1) Essayez également d'intégrer l'assemblage .NET 'System' depuis la liste des assemblages dans Windev.
2) Fermez WD, ouvrez à nouveau le projet, recompilez et regénérez l'Exe.

Savi Pirl a dit…

Bonjour,
Merci pour votre réponse.

j'avais déja intégré l'assemblage system.

En controlant, je me suis apercu que j'en avais plusieurs.

Pourriez vous me préciser le quel prendre exactement?

Merci

Mercier Loic a dit…

Bonjour

J'ai essayer et j'obtient la même erreur que Savi Pirl.
J'ai également essayer de rajouter la classe system mais j'obtient la même erreur.
Une autre piste?

Cordialement

Vincent a dit…

J'ai utilisé le fichier suivant :

System
Version=2.0.0.0
Culture=neutral
PublicKeyToken=b77a5c561934e089

ch'ren The Faz a dit…

Bonjour,

Bravo pour votre tuto sur EWS, je suis en Windev 20 et j'ai implémenté vos 3 premiers volets.
Tout est fonctionnel (encore bravo).
Par contre, je sèche lamentablement sur l'opération suivante: déplacer un ou des mails vers un autre dossier.
J'ai compris que cela fonctionne par le folderID, mais je suis bloqué.
Pouvez vous m'aider sur ce point.

Merci par avance

Vincent a dit…

On peut travailler avec les ID des dossiers.

Avec une chaine, on peut créer une variable de type Folder. Exemple lorsqu'on initialise une recherche :

clDrFindResults <- :m_wsExchange.FindItems(new FolderId(sFolderId), vi)

On peut aussi travailler avec des variables Folder dans une procédure :

GF_clEws.getPageSearchFolders(WellKnownFolderName.Inbox,200,"lproc_addTableFolder")

La procédure "getPageSearchFolders" prend en paramètre une variable de type Folder ; on peut lui passer un nom de dossier connu (voir exemple ci-dessus).

Selon moi la première méthode devrait aider à réaliser le déplacement d'un dossier à l'autre. Il faut juste penser à récupérer l'ID des autres dossiers (voir le tutorial sur la récupération des noms de dossiers).

Anonyme a dit…

Je suis en Windev 20 en ce moment et c’est vraiment inspirant de voir votre tutoriel. Pour moi, j’ai été aidé par des vidéos sur http://www.alphorm.com/tutoriel/formation-en-ligne-windev-20-avance pour le maîtriser. En tout cas, merci pour ce partage.

Denis Boutet a dit…

Bonjour,

j'ai essayé votre code et j'ai ce message:Vous avez appelé la fonction DotNetDélégué.
L'objet de type (assemblage <>) n'a pas pu être créé

Je suis en webdev 21, merci d'avance pour votre aide

Nicolas Voorons a dit…

Bonjour,
Avez-vous trouvé une solution à votre problème ? Si c'est le cas, comment l'avez-vous résolu ?

Merci beaucoup !