📜 ⬆️ ⬇️

Work with mail on MS Exchange server via EWS. Part 1



Hello, readers Habrahabr!

As part of a series of these posts, I want to talk about technology such as EWS and how to use it to work with mail stored on MS Exchange 2007 - 2010 servers. I will try to show how easy and convenient it is to use EWS.
')
We will begin from the very beginning, from acquaintance to this technology and creation of the first project, and we will finish with more complex mail manipulations.

This post is introductory and it will most likely be of no interest to those who are already familiar with EWS.

Introduction


Exchange Web Services ( EWS ) is a special protocol developed by MS and designed to manage mail and other components that make up MS Exchange. The protocol is based on XML. Description of supported operations and examples can be found here .

EWS is a relatively young technology, introduced in Exchange 2007, and replacing the WebDAV protocol. MS puts a lot of effort into developing and improving EWS. Now it is a powerful tool, with a simple and clear API, as well as with excellent documentation, which allows to solve the management tasks of MS Exchange objects.

The EWS architecture is shown in the following image:



As you can see, the EWS is hosted on servers with a Client Access Server (CAS) role. This role is responsible for processing requests from the user, i.e. any client, such as Outlook, MFCMapi, browser + OWA, etc., they all connect to CAS. The request from the client application goes into IIS, where the application implements the functionality of the EWS is located. Those. EWS “lives” in IIS and runs in a separate process or w3wp.exe processes (in which processes run the IIS application pool). In addition to EWS, other applications can “spin” there, for example, OWA, ECP and PowerShell.

EWS acts as a layer between the client request and the internal Exchange. When an EWS request from a client application arrives, it is proxied to internal Exchange calls, and then it goes to the Mailbox Server role , where the operations themselves are already performed.

Note: A little about the internal structure of the Mailbox role can be found in my previous article .

Physically, the EWS is located inside the .NET assembly. And starting with Exchange 2010, not only EWS calls come in, but also OWA. Those. MS apparently realized that the idea of ​​several branches with the same code functionality was not successful and decided to leave only one branch, which should simplify and speed up support and development.

We got a general idea, we can move on to programming.

Development


We will need:
  1. MS Exchange Server 2007 - 2010 for testing
  2. Visual Studio 2008 - 2010
First, create an empty C # console project. Next you need to add reference'y with the description of classes / methods / types, etc., which we need to work with EWS. The easiest way to do this, if you have Exchange, is to add a Web Reference . In VS 2010, you need to select the project and select Add Service Rederence , then Advanced , Add Web Reference and enter the address of your test server in the URL field in the format https: // [server name] /EWS/Services.wsdl , i.e. should be like this:



After clicking next, the download of references will begin, and if everything goes well, you will be asked to indicate the name of this reference, and at the end it will be added to the project.

Everything, now we can try to connect to the server. And the first thing to do is get the ExchangeServiceBinding object, this is probably the most important object in the EWS, it is through it that all valid methods will be called and it identifies the specific connection on the client side. To create this object, you can use the following method:

public static ExchangeServiceBinding GetBinding( String server, String domain, String user, String password) { var esb = new ExchangeServiceBinding(); //    esb.Credentials = new NetworkCredential(user, password, domain); //     EWS esb.Url = "https://" + server + "/EWS/Exchange.asmx"; esb.RequestServerVersionValue = new RequestServerVersion(); //   Exchange  //  Exchange 2007 SP1  2010  Exchange2007_SP1 //  Exchange 2007  SP   Exchange2007 esb.RequestServerVersionValue.Version = ExchangeVersionType.Exchange2007_SP1; return esb; } 

Note: If the server uses a self-signed certificate, then connect will not work. such certificate will not pass validation. As a workaround, you can add an additional code to apply any certificates:

 ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true; 

With the ExchangeServiceBinding you can try to do something useful, for example, send a message. MSDN suggests that you need to use the CreateItemType object. To do this, we write the following method:

 public static void SendMessage( ExchangeServiceBinding esb, String to, String subject, String body) { //  CreateItem request //       // ,      ,    var createItemRequest = new CreateItemType { Items = new NonEmptyArrayOfAllItemsType(), MessageDispositionSpecified = true, MessageDisposition = MessageDispositionType.SendOnly }; //  item  Message //  recipients,      var message = new MessageType(); message.ToRecipients = new EmailAddressType[1]; message.ToRecipients[0] = new EmailAddressType(); message.ToRecipients[0].EmailAddress = to; //   message.Subject = subject; //     message.Body = new BodyType(); message.Body.BodyType1 = BodyTypeType.Text; message.Body.Value = body; //   request   Item' createItemRequest.Items.Items = new ItemType[1]; createItemRequest.Items.Items[0] = message; //   CreateItemResponseType createItemResponse = esb.CreateItem(createItemRequest); //   ArrayOfResponseMessagesType responseMessages = createItemResponse.ResponseMessages; //  ,   var responseMessage = responseMessages.Items; foreach (var rmt in responseMessage.Where(rmt => rmt.ResponseClass == ResponseClassType.Error)) { throw new Exception(rmt.MessageText); } } 


Note: The code above shows the easiest way to send a message, and we don’t see the “power” of the classes used, and they provide extensive possibilities for customizing the operations performed (setting various properties, flags, etc.). More about this and not only I will try to tell in the following articles.

Calling this code can be done like this:

 static void Main() { ServicePointManager.ServerCertificateValidationCallback = (obj, certificate, chain, errors) => true; try { const String server = "myserver", domain = "mydomain", user = "myuser", password = "mypassword", mailTo = "myuser2@mydomain.local", subject = "read me", body = "ehlo, developers!"; var esb = GetBinding(server, domain, user, password); SendMessage(esb, mailTo, subject, body); Console.WriteLine("Done!"); } catch (Exception e) { if(e.Message != null) Console.WriteLine(e.Message); } } 


If it seemed to you that the code ran a frighteningly long time (I have about 5 seconds), do not worry, this happens only on the first call. Almost all the time it takes to initialize only once. Also, if this was the first EWS call for the server, then the server needs to initialize on its part and create a new w3wp instance to process the request, and this may also take some time.

Conclusion


We briefly familiarized ourselves with the EWS technology and wrote a simple example of sending a letter to the addressee.

As you can see, the code is very short and understandable. MS documentation is pretty good and almost always with examples. If you programmed in C ++ MAPI, then you will appreciate how much simpler this method is.

If you have a task to write an email client or any other tasks related to remote work on Exchange objects, I hope that you will use the EWS. because IMHO this method is the easiest and most understandable of all with whom I had to work.

Thanks for attention.

To be continued...

Source: https://habr.com/ru/post/117268/


All Articles