Microsoft Exchange – EWS: Propriétés personnalisées – Récupération et suppression

Dans le cas où votre application dépend beaucoup des propriétés personnalisées apposées sur vos précieux emails, vous vous êtes peut être déjà posé la question : Comment suis-je sensé les récupérer… toutes ?

Pour récupérer la valeur d’un champ personnalisé d’un email il faut… savoir que ce champ existe ! Impossible donc de demander à l’API « renvoi moi toutes les propriétés perso de ce message et leur valeur »

Impossible ? Pas vraiment, en contournant l’API et en passant par le webservice, nous pouvons utiliser la méthode « ExportItem » qui permet de récupérer des propriétés inédites.

Pour cela, il suffit de récupérer l’uniqueId de l’email et de le passer dans une instance de ExportItemsType, puis d’appeler la méthode ExportItems via le web service (et pas l’API !)

(Rappel : configurer le web service)

string sItemID = item.Id.UniqueId;
 
ExportItemsType exExportItems = new ExportItemsType();
 
exExportItems.ItemIds = new ItemIdType[2];
 
exExportItems.ItemIds[0] = new ItemIdType();
 
exExportItems.ItemIds[0].Id = sItemID;
 
ExportItemsResponseType exResponse = m_exchangeServerBinding.ExportItems(exExportItems);
 
ExportItemsResponseMessageType rmResponse = (ExportItemsResponseMessageType)exResponse.ResponseMessages.Items[0];
 
Byte[] messageBytes = rmResponse.Data;
 
ProcessFile(messageBytes);
 
private void ProcessFile(String fnFileName)
 
{
 
Byte[] fsfileBytes = ReadByteArrayFromFile(fnFileName);
 
EWSFTParser ipItemParser = new EWSFTParser();
 
MapiItem mpMapiItem = ipItemParser.ParseItem(fsfileBytes);
 
ViewEmailProperties fEmailProperties = new ViewEmailProperties(mpMapiItem);
 
fEmailProperties.ShowDialog();
 
}

Le EWSFTParser ainsi qu’un projet Visual studio 2010 peuvent être récupérés ici (merci à Glen Scales, MVP microsoft)

J’ai fait fonctionner son parser/browser en moins de 5minutes donc vous devriez vous en sortir aussi.

Supprimer une propriété personnalisée

Pour supprimer la propriété personnalisée, utilisez la méthode RemoveExtendedProperty

ExtendedPropertyDefinition extendedPropertyDefinition =    new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, sFieldToRemove, MapiPropertyType.String);
 
if (item.RemoveExtendedProperty(extendedPropertyDefinition))
 
{
 
item.Update(ConflictResolutionMode.AlwaysOverwrite);
 
AddText("Custom property removed!");
 
return;
 
}

Microsoft Exchange – EWS: Ecrire un nouvel email avec toutes les options

Après avoir vu comment récupérer les emails, voyons comment créer un nouvel email et l’envoyer à un compte email Exchange.

Création d’un nouveau message et envoi

string sDestinataire = m_edDestinataire.Text;
 
/* Création d'email et envoi */
 
EmailMessage message = new EmailMessage(m_service);
 
message.Subject = m_edSubject.Text;
 
message.Body = m_rtbBody.Text;
 
message.Body.BodyType = BodyType.HTML;
 
message.Importance = Importance.Normal;
 
//Ajout d’une propriété personnalisée appelé “MaProprietePerso” avec pour valeur //« Mavaleur »
 
string sPropertyName = “MaProprietePerso”;
 
ExtendedPropertyDefinition extendedPropertyDefinition =
 
new ExtendedPropertyDefinition(DefaultExtendedPropertySet.PublicStrings, sPropertyName, MapiPropertyType.String);
 
message.SetExtendedProperty(extendedPropertyDefinition, “MaValeur”);
 
//Avec ou sans pièces jointes:
 
if (sFilename != string.Empty)
 
message.Attachments.AddFileAttachment(sFilename);
 
//Destinataire :
 
message.ToRecipients.Add(sDestinataire);
 
//Accusé de reception :
 
if (m_ckDelivery.Checked)
 
message.IsDeliveryReceiptRequested = true;
 
//Sauvegarde et envoi de l’email :
 
message.SendAndSaveCopy();

Ce code vous permet de créer un nouveau message et de spécifier : son titre(sujet), le corps du message, son importance, des propriétés personnalisées, des pièces jointes, des destinataires et un accusé de réception.

Envoi différé

Un point rarement mentionné porte sur l’envoi différé, pour utiliser cette fonctionnalité, ajouter la classe suivante :

public static class ExchangeExtensions
 
{
 
public static ExtendedPropertyDefinition PR_DEFERRED_SEND_TIME = new ExtendedPropertyDefinition(16367, MapiPropertyType.SystemTime);
 
public static ExtendedPropertyDefinition PR_DEFERRED_DELIVERY_TIME = new ExtendedPropertyDefinition(15, MapiPropertyType.SystemTime);
 
/// 
 
/// Sets Delayed Delivery
 
///
 
///
<span> </span>
 
///
<span> </span>Do Not Send Before This Date and Time
 
public static void SetDelayedDelivery(Microsoft.Exchange.WebServices.Data.EmailMessage email, DateTime deliveryDate)
 
{
 
string ut = deliveryDate.ToUniversalTime().ToString();
 
email.SetExtendedProperty(PR_DEFERRED_SEND_TIME, ut);
 
email.SetExtendedProperty(PR_DEFERRED_DELIVERY_TIME, ut);
 
}
 
}

Et sur le message, avant de l’envoyer :

ExchangeExtensions.SetDelayedDelivery(message, dateTimePicker1.Value);
 
//Sauvegarde et envoi de l’email :
 
message.SendAndSaveCopy();

Vous savez désormais récupérer les messages stockées sur le serveur Exchange et écrire de nouveaux emails en spécifiant de nombreuses options différentes.

Microsoft Exchange – EWS: FindItems et récupération d’emails

Commençons par une fonction basique qui permettra de tester l’installation et la bonne configuration de votre service : La récupération d’email.

Introduction

La récupération des emails se fait en 2 temps généralement. D’abord nous avons le FindItems qui permet de renvoyer les objets correspondants à la requête. Ensuite il est possible d’appeler une 2ème méthode pour charger des propriétés spéciales, qui ne sont pas récupérées par défaut, dans les emails préalablement récupérés.

Exemple

ItemView itemView = new ItemView(iElementNb);
 
itemView.OrderBy.Add(EmailMessageSchema.DateTimeReceived, SortDirection.Descending);
 
FindItemsResults findResults = m_service.FindItems(WellKnownFolderName.Inbox, itemView);
 
//Ici, on récupère le MIME content (qui n'est pas chargé par le simple appel à la méthode FindItems)
 
PropertySet ps = new PropertySet();
 
ps.Add(ItemSchema.MimeContent);
 
m_service.LoadPropertiesForItems(findResults, ps);

L’objet ItemView permet de spécifier le nombre d’éléments à récupérer ainsi que l’ordre dans lequel ils seront retournés

La méthode FindItems possède plusieurs prototypes :

Il est possible de spécifier le dossier de recherche via son FolderID (nous y reviendrons un peu plus loin) afin de pouvoir parcourir des dossiers autres que ceux basiques (les « WellKnownFolderName »)

Il est aussi possible d’ajouter un critère de recherche, afin de récupérer seulement les emails ayant pour envoyeur Mr X, ou ceux envoyé à une date donnée…

Exemple

Récupération de tous les emails situés dans la boite de réception contenant le motif X(appelé ici sTextPattern) dans le sujet ou dans le corps de l’email

ItemView itemView = new ItemView(iElementNb);
 
itemView.OrderBy.Add(EmailMessageSchema.DateTimeReceived, SortDirection.Descending);
 
SearchFilter.SearchFilterCollection searchFilterCollection =
 
new SearchFilter.SearchFilterCollection(LogicalOperator.Or);
 
searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.Body, sTextPattern));
 
searchFilterCollection.Add(new SearchFilter.ContainsSubstring(ItemSchema.Subject, sTextPattern));
 
findResults = m_service.FindItems(WellKnownFolderName.Inbox, searchFilterCollection, itemView);

Mise à jour:

Seulement voila, le fait d’utiliser FindItems avec un SearchFilterCollection (ou SearchFilter) créer une indexation des résultats de recherches sur le serveur Exchange. En gros, les prochaines recherches exactement similaires seront bien plus rapides, mais l’indexation fait perdre des perfs et prends de la place sur le serveur Exchange.

Pour éviter cela, il est possible d’utiliser une autre sémantique qui est la recherche Exchange Search. Pour cela, il faut utiliser les mots clés d’Advanced Query Syntax (introductionliste de mots clés)

Le seul exemple que je donnerai ici sera l’utilisation de la propriété System.FullText qui permet de récupérer tous les emails contenant un certain motif dans:

Le corps, le titre, le contenu des pièces jointes (test sur un .txt), le nom des pièces jointes etc

À utiliser simplement comme cela:

string sRequest = "System.FullText:" + sMotifARechercher;
findResults = m_service.FindItems(WellKnownFolderName.Inbox, sRequest, itemView);

Source additionnelle: http://msdn.microsoft.com/en-us/library/hh148195(v=EXCHG.140).aspx

Voir Chapitre suivant : Ecrire et envoyer un email avec EWS API managed

Introduction à Exchange EWS API

Aujourd’hui je vais expliquer brièvement les deux manières les plus communes afin d’interagir avec son serveur Exchange. Grâce à cela, nous pourrons ensuite effectuer des opérations du type réception et envoi d’email et bien plus encore…

Mais commençons par le début :

Partie I: Configuration et initialisation de la connexion avec le serveur Exchange

Introduction

Il y a plusieurs façons de se connecter et de communiquer avec le serveur Exchange, du plus simple (en utilisant la nouvelle API conçu récemment par Microsoft) jusqu’au plus compliqué (envoyer des requêtes XML/ SOAP).  Dans cet article je parlerai uniquement de l’API managée et du Webservice EWS offert par le serveur Exchange

Utilisation de l’API EWS Managed 1.1

Etape 0 : Que fait cette API ?

Elle permet de rendre plus facile l’utilisation des services offerts par le serveur exchange en encapsulant les fonctionnalités dans des méthodes bien pensées.

Etape 1 : Téléchargement de l’API

La DLL dont nous avons besoin (Microsoft.Exchange.WebServices.dll) se place par défaut dans le dossier C:\Program Files\Microsoft\Exchange\Web Services\1.1\

Etape 2 : Création d’un projet C# et ajout de la référence

Ouvrir Visual Studio, créer un nouveau projet Windows Forms Application et ajouter cette DLL dans références.

Etape 3 : Code basique nécessaire à l’initialisation du service

Copier ce qui suit dans votre code :

using Microsoft.Exchange.WebServices.Data; //Permet d'utiliser les fonctionnalités de l'API

Et ce qui suit dans le corps d’une méthode :

ExchangeService service = new ExchangeService(ExchangeVersion.Exchange2010_SP1);
m_service.Credentials = new WebCredentials(sUser, sPwd, sDomain);
m_service.Url = new Uri("https://SERVER/EWS/Exchange.asmx");

Dans le cas d’une où le certificat de sécurité n’est pas signé, vous pourriez voir vos requêtes refusées, dans ce cas ajoutez ceci :

using System.Security.Cryptography.X509Certificates;
private static bool RemoteCertificateValidationCallback(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors sslPolicyErrors){      return true;}

Et ce qui suit dans votre code :

ServicePointManager.ServerCertificateValidationCallback = RemoteCertificateValidationCallback;

Voilà, votre service est prêt à être utiliser. Voir chapitre suivant

Utilisation directe du Web Service EWS

L’utilisation du web service n’est pas conseillée par Microsoft, même si elle fournit quelques fonctionnalités poussées supplémentaires (pour le moment) par rapport à l’API(ExportItem par exemple, j’y reviendrais dans un prochain article)

Etape 1 : Création d’un projet C# et ajout de la web référence

Ouvrir Visual Studio, créer un nouveau projet Windows Form Application et ajouter dans une référence à un service. Taper ensuite l’adresse de votre service (https://SERVER/EWS/Exchange.asmx) et rechercher le service. Ajouter le  en spécifiant un namespace approprié (ici, je le nomme ExchangeWebRef)

Etape 2 : Code basique nécessaire à l’initialisation du service

using TestExchangeBasicFeatures.ExchangeWebRef;
//Connection directement avec le webservice:
m_exchangeServerBinding = new ExchangeServiceBinding();
ICredentials creds = new NetworkCredential(sUser, sPwd, sDomain);
m_exchangeServerBinding.Credentials = creds;
m_exchangeServerBinding.Url = @"https://SERVER/EWS/Exchange.asmx";
m_exchangeServerBinding.RequestServerVersionValue = new RequestServerVersion();
m_exchangeServerBinding.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2010_SP1;

Voilà, votre WebService est prêt à être utilisé. Voir chapitre suivant

FAQ

Question : Dans le cas de l’utilisation du Web Service, je ne parviens pas à trouver la classe ExchangeServiceBinding dans la référence de service que j’ai ajouté.

Réponse : Ajouter le web service en passant par avancé>ajouter une référence web