Empezar a trabajar con aplicaciones de cliente de EWSGet started with EWS client applications

Cree su primera aplicación utilizando Servicios Web Exchange (EWS) de Exchange.Create your first application by using Exchange Web Services (EWS) in Exchange.

EWS es un servicio integral que las aplicaciones pueden usar para tener acceso a casi toda la información almacenada en un buzón de Exchange Online, Exchange Online como parte de Office 365 o Exchange local. EWS usa protocolos web estándar para proporcionar acceso a un servidor Exchange. Bibliotecas como la API administrada de EWS ajustan las operaciones de EWS para proporcionar una interfaz orientada a objetos. Una vez que haya ejecutado los ejemplos de este artículo, tendrá un conocimiento básico de lo que puede hacer con EWS.EWS is a comprehensive service that your applications can use to access almost all the information stored in an Exchange Online, Exchange Online as part of Office 365, or Exchange on-premises mailbox. EWS uses standard web protocols to provide access to an Exchange server; libraries like the EWS Managed API wrap the EWS operations to provide an object-oriented interface. After you've run the examples in this article, you will have a basic understanding of what you can do with EWS.

Puede llamar a las operaciones de EWS desde cualquier sistema operativo o lenguaje, porque las solicitudes y respuestas de EWS usan el protocolo SOAP. Los ejemplos de este artículo se han escrito con C# y usan los objetos HttpWebRequest y HttpWebResponse .NET Framework. Sin embargo, la parte importante del código es el código XML que se usa para realizar la solicitud EWS y la respuesta XML devuelta desde el servidor. Los ejemplos de código hacen hincapié en las transacciones de XML y no en el procesamiento del código XML.You can call EWS operations from any operating system or language, because the EWS requests and responses use the SOAP protocol. The examples in this article are written using C# and make use of the .NET Framework HttpWebRequest and HttpWebResponse objects; however, the important part of the code is the XML used to make the EWS request and the XML response returned from the server. The code examples emphasize the XML transactions and not processing the XML.

Necesitará un servidor de ExchangeYou'll need an Exchange server

Si ya tiene una cuenta de buzón de Exchange, puede omitir este paso. En caso contrario, dispone de las opciones siguientes para configurar un buzón de Exchange para su primera aplicación de EWS:If you already have an Exchange mailbox account, you can skip this step. Otherwise, you have the following options for setting up an Exchange mailbox for your first EWS application:

Después de haber comprobado que puede enviar y recibir correo electrónico desde el servidor Exchange, está listo para configurar el entorno de desarrollo. Puede usar Outlook Web App para comprobar que puede enviar correo electrónico.After you've verified that you can send and receive email from your Exchange server you are ready to set up your development environment. You can use Outlook Web App to verify that you can send email.

También debe conocer la dirección URL del punto de conexión de EWS para su servidor. En una aplicación de producción, se usaría Autodiscover para determinar la dirección URL de EWS. Los ejemplos de este artículo usan la dirección URL del punto de conexión EWS de Office 365, https://outlook.office365.com/EWS/Exchange.asmx. La sección Próximos pasos contiene vínculos a más información sobre Autodiscover cuando esté listo.You'll also need to know the URL of the EWS endpoint for your server. In a production application, you'd use Autodiscover to determine the EWS URL. The examples in this article use the Office 365 EWS endpoint URL, https://outlook.office365.com/EWS/Exchange.asmx. The Next steps section has links to more information about Autodiscover when you're ready.

Si está probando la aplicación mediante un servidor Exchange que tiene el certificado autofirmado predeterminado, necesitará crear un método de validación de certificados que cumpla los requisitos de seguridad de su organización.If you are testing your application using an Exchange server that has the default self-signed certificate, you'll need to create a certificate validation method that meets the security requirements of your organization.

Configurar el entorno de desarrolloSet up your development environment

Las herramientas que usa para crear su primera aplicación de EWS dependen del sistema operativo y el idioma que use, y son principalmente una cuestión de gustos. Si quiere seguir los ejemplos de C# de este artículo, necesitará:The tools that you use to create your first EWS application depend on the operating system and language that you use, and are mostly a matter of taste. If you want to follow along with the C# examples in this article, you'll need:

  • Cualquier versión de Visual Studio que admita la versión 4.0 de .NET Framework.Any version of Visual Studio that supports the .NET Framework 4.0.

  • Una conexión a Internet que su equipo de desarrollo pueda usar para ponerse en contacto con el servidor Exchange. Si puede usar Outlook Web App con un nombre DNS en lugar de una dirección IP para conectarse al servidor Exchange, ya está preparado.An Internet connection that your development machine can use to contact your Exchange server. If you can use Outlook Web App with a DNS name rather than an IP address to connect to your Exchange server, you are set up.

Crear la primera aplicación de EWSCreate your first EWS application

La aplicación de EWS que creará muestra dos escenarios típicos de uso de EWS:The EWS application that you will create shows two typical scenarios for using EWS:

  1. Obtener información de un buzón de Exchange y mostrar esa información al usuario.Get information from an Exchange mailbox and display that information to the user.

  2. Realizar una acción, como enviar un correo electrónico, y comprobar la respuesta para ver si la acción se realizó correctamente.Perform an action, such as sending an email, and check the response to see if the action succeeded.

Comencemos.Let's get started.

Configurar la soluciónSet up the solution

En primer lugar, cree una nueva solución de aplicación de consola mediante Visual Studio. Cuando la solución esté lista, cree un nuevo objeto denominado Tracing.cs. Use este objeto para escribir información tanto en la consola como en un archivo de registro para que pueda revisar los resultados después de ejecutar el código. Pegue el siguiente código en el archivo Tracing.cs:First, create a new console application solution using Visual Studio. When the solution is ready, create a new object called Tracing.cs. Use this object to write information to both the console and a log file so that you can review the results after you run your code. Paste the following code into the Tracing.cs file.

using System;
using System.IO;
namespace Microsoft.Exchange.Samples.EWS
{
  class Tracing
  {
    private static TextWriter logFileWriter = null;
    public static void OpenLog(string fileName)
    {
      logFileWriter = new StreamWriter(fileName);
    }
    public static void Write(string format, params object[] args)
    {
      Console.Write(format, args);
      if (logFileWriter != null)
      {
        logFileWriter.Write(format, args);
      }
    }
    public static void WriteLine(string format, params object[] args)
    {
      Console.WriteLine(format, args);
      if (logFileWriter != null)
      {
        logFileWriter.WriteLine(format, args);
      }
    }
    public static void CloseLog()
    {
      logFileWriter.Flush();
      logFileWriter.Close();
    }
  }
}

Luego abra el archivo Program.cs. Colocará el resto del código del ejemplo en este archivo.Next, open the Program.cs file. You will put the rest of the code for the example in this file.

En primer lugar, configure el shell del programa. El programa hará lo siguiente:First, set up the shell of the program. The program will:

  1. Crear un archivo de registro para que la solicitud y la respuesta se puedan escribir en el disco para estudio posterior.Create a log file so that the request and response can be written to disk for later study.

  2. Obtener la dirección de correo electrónico y la contraseña de la cuenta a la que usted tendrá acceso.Get the email address and password of the account that you'll access.

  3. Llamar a los métodos de ejemplo.Call the sample methods.

Reemplazar el método Main en el archivo Program.cs por el código siguiente.Replace the Main method in the Program.cs with the following code.

    static void Main(string[] args)
    {
      // Start tracing to console and a log file.
      Tracing.OpenLog("./GetStartedWithEWS.log");
      Tracing.WriteLine("EWS sample application started.");
      var isValidEmailAddress = false;
      Console.Write("Enter an email address: ");
      var emailAddress = Console.ReadLine();
      
        isValidEmailAddress = (emailAddress.Contains("@") && emailAddress.Contains("."));
      if (!isValidEmailAddress)
      {
        Tracing.WriteLine("Email address " + emailAddress + " is not a valid SMTP address. Closing program.");
        return;
      }
      SecureString password = GetPasswordFromConsole();
      if (password.Length == 0)
      {
        Tracing.WriteLine("Password empty, closing program.");
      }
      NetworkCredential userCredentials = new NetworkCredential(emailAddress, password);
      // These are the sample methods that demonstrate using EWS.
      // ShowNumberOfMessagesInInbox(userCredentials);
      // SendTestEmail(userCredentials);
     
      Tracing.WriteLine("EWS sample application ends.");
      Tracing.CloseLog();
      Console.WriteLine("Press enter to exit: ");
      Console.ReadLine();
    }
    // These method stubs will be filled in later.
    private static void ShowNumberOfMessagesInInbox(NetworkCredential userCredentials)
    {
    }
    private static void SendTestEmail(NetworkCredential userCredentials)
    {
    }

Lo último que debe hacer es agregar el método estático GetPasswordFromConsole. Este método devuelve un objeto SecureString que contiene una contraseña escrita en la consola.The last thing that you need to do is add the GetPasswordFromConsole static method. This method returns a SecureString object that contains a password typed at the console.

    private static SecureString GetPasswordFromConsole()
    {
      SecureString password = new SecureString();
      bool readingPassword = true;
      Console.Write("Enter password: ");
      while (readingPassword)
      {
        ConsoleKeyInfo userInput = Console.ReadKey(true);
        switch (userInput.Key)
        {
          case (ConsoleKey.Enter):
            readingPassword = false;
            break;
          case (ConsoleKey.Escape):
            password.Clear();
            readingPassword = false;
            break;
          case (ConsoleKey.Backspace):
            if (password.Length > 0)
            {
              password.RemoveAt(password.Length - 1);
              Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
              Console.Write(" ");
              Console.SetCursorPosition(Console.CursorLeft - 1, Console.CursorTop);
            }
            break;
          default:
            if (userInput.KeyChar != 0)
            {
              password.AppendChar(userInput.KeyChar);
              Console.Write("*");
            }
            break;
        }
      }
      Console.WriteLine();
      password.MakeReadOnly();
      return password;
    }

Obtener el número de nuevos mensajes en la Bandeja de entradaGet the number of new messages in an Inbox

Una operación común en una aplicación de EWS es obtener información sobre los mensajes de correo electrónico, las citas, las reuniones y las carpetas en donde se almacenan. En este ejemplo se obtiene el número de mensajes que hay en la Bandeja de entrada de una cuenta y se muestra el número total de mensajes y el número de mensajes no leídos. Esto demuestra las siguientes acciones comunes para aplicaciones de EWS:A common operation in an EWS application is to get information about email messages, appointments, meetings, and the folders that store them. This example gets the number of messages in an account's Inbox and displays the total number of messages and the number of unread messages. It demonstrates the following common actions for EWS applications:

  • Realizar una solicitud EWS al servidor Exchange.Making an EWS request to the Exchange server.

  • Analizar la respuesta XML devuelta para obtener la información solicitada.Parsing the returned XML response for the requested information.

  • Manejar los mensajes de error y las excepciones comunes.Handling common exceptions and error messages.

Agregue el código siguiente al método ShowNumberOfMessagesInInbox que era auxiliar después del método main. Cuando se ejecute la aplicación, se imprimirá el número de mensajes que hay en la Bandeja de entrada de la cuenta y el número de mensajes no leídos de la Bandeja de entrada. Después de ejecutar la aplicación, puede abrir el archivo GetStartedWithEWS.log para ver la solicitud XML que se envió al servidor Exchange y la respuesta que devolvió el servidor.Add the following code to the ShowNumberOfMessagesInInbox method that was stubbed out after the main method. When you run the application, it will print the number of messages in the account's Inbox and the number of unread messages in the Inbox. After you run the application, you can open the GetStartedWithEWS.log file to see the XML request that was sent to the Exchange server and the response that the server returned.

      /// This is the XML request that is sent to the Exchange server.
      var getFolderSOAPRequest =
"<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
"<soap:Envelope xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\"\n" +
"   xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">\n" +
"<soap:Header>\n" +
"    <t:RequestServerVersion Version=\"Exchange2007_SP1\" />\n" +
"  </soap:Header>\n" +
"  <soap:Body>\n" +
"    <GetFolder xmlns=\"http://schemas.microsoft.com/exchange/services/2006/messages\"\n" +
"               xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\">\n" +
"      <FolderShape>\n" +
"        <t:BaseShape>Default</t:BaseShape>\n" +
"      </FolderShape>\n" +
"      <FolderIds>\n" +
"        <t:DistinguishedFolderId Id=\"inbox\"/>\n" +
"      </FolderIds>\n" +
"    </GetFolder>\n" +
"  </soap:Body>\n" +
"</soap:Envelope>\n";
      // Write the get folder operation request to the console and log file.
      Tracing.WriteLine("Get folder operation request:");
      Tracing.WriteLine(getFolderSOAPRequest);
      var getFolderRequest = WebRequest.CreateHttp(Office365WebServicesURL);
      getFolderRequest.AllowAutoRedirect = false;
      getFolderRequest.Credentials = userCredentials;
      getFolderRequest.Method = "POST";
      getFolderRequest.ContentType = "text/xml";
      var requestWriter = new StreamWriter(getFolderRequest.GetRequestStream());
      requestWriter.Write(getFolderSOAPRequest);
      requestWriter.Close();
      try
      {
        var getFolderResponse = (HttpWebResponse)(getFolderRequest.GetResponse());
        if (getFolderResponse.StatusCode == HttpStatusCode.OK)
        {
          var responseStream = getFolderResponse.GetResponseStream();
          XElement responseEnvelope = XElement.Load(responseStream);
          if (responseEnvelope != null)
          {
            // Write the response to the console and log file.
            Tracing.WriteLine("Response:");
            StringBuilder stringBuilder = new StringBuilder();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(stringBuilder, settings);
            responseEnvelope.Save(writer);
            writer.Close();
            Tracing.WriteLine(stringBuilder.ToString());
            // Check the response for error codes. If there is an error, throw an application exception.
            IEnumerable<XElement> errorCodes = from errorCode in responseEnvelope.Descendants
                                               ("{http://schemas.microsoft.com/exchange/services/2006/messages}ResponseCode")
                                               select errorCode;
            foreach (var errorCode in errorCodes)
            {
              if (errorCode.Value != "NoError")
              {
                switch (errorCode.Parent.Name.LocalName.ToString())
                {
                  case "Response":
                    string responseError = "Response-level error getting inbox information:\n" + errorCode.Value;
                    throw new ApplicationException(responseError);
                  case "UserResponse":
                    string userError = "User-level error getting inbox information:\n" + errorCode.Value;
                    throw new ApplicationException(userError);
                }
              }
            }
            // Process the response.
            IEnumerable<XElement> folders = from folderElement in
                                              responseEnvelope.Descendants
                                              ("{http://schemas.microsoft.com/exchange/services/2006/messages}Folders")
                                            select folderElement;
            foreach (var folder in folders)
            {
              Tracing.Write("Folder name:     ");
              var folderName = from folderElement in
                                 folder.Descendants
                                 ("{http://schemas.microsoft.com/exchange/services/2006/types}DisplayName")
                               select folderElement.Value;
              Tracing.WriteLine(folderName.ElementAt(0));
              Tracing.Write("Total messages:  ");
              var totalCount = from folderElement in
                                 folder.Descendants
                                   ("{http://schemas.microsoft.com/exchange/services/2006/types}TotalCount")
                               select folderElement.Value;
              Tracing.WriteLine(totalCount.ElementAt(0));
              Tracing.Write("Unread messages: ");
              var unreadCount = from folderElement in
                                 folder.Descendants
                                   ("{http://schemas.microsoft.com/exchange/services/2006/types}UnreadCount")
                               select folderElement.Value;
              Tracing.WriteLine(unreadCount.ElementAt(0));
            }
          }
        }
      }
      catch (WebException ex)
      {
        Tracing.WriteLine("Caught Web exception:");
        Tracing.WriteLine(ex.Message);
      }
      catch (ApplicationException ex)
      {
        Tracing.WriteLine("Caught application exception:");
        Tracing.WriteLine(ex.Message);
      }

Enviar un mensaje de correo electrónicoSend an email message

Otra operación común para una aplicación de EWS consiste en enviar mensajes de correo electrónico o convocatorias de reunión. En este ejemplo se crea y se envía un mensaje de correo electrónico usando las credenciales del usuario que se especificaron anteriormente. Aquí se ven estas tareas de aplicación comunes de EWS:Another common operation for an EWS application is to send email messages or meeting requests. This example creates and sends an email message using the user credentials that were entered earlier. It demonstrates these common EWS application tasks:

  • Crear y enviar un correo electrónico.Creating and sending an email.

  • Analizar la respuesta XML devuelta para determinar si el correo electrónico se ha enviado correctamente.Parsing the returned XML response to determine if the email was correctly sent.

  • Manejar los mensajes de error y las excepciones comunes.Handling common exceptions and error messages.

Agregue el código siguiente al método SendTestEmail que era auxiliar después del método main. Después de ejecutar la aplicación, puede abrir el archivo GetStartedWithEWS.log para ver la solicitud XML que se envió al servidor Exchange y la respuesta que devolvió el servidor.Add the following code to the SendTestEmail method that was stubbed out after the main method. After you run the application, you can open the GetStartedWithEWS.log file to see the XML request that was sent to the Exchange server and the response that the server returned.

var createItemSOAPRequest =
      "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n" +
      "<soap:Envelope xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
      "               xmlns:m=\"http://schemas.microsoft.com/exchange/services/2006/messages\" \n" +
      "               xmlns:t=\"http://schemas.microsoft.com/exchange/services/2006/types\" \n" +
      "               xmlns:soap=\"http://schemas.xmlsoap.org/soap/envelope/\">\n" +
      "  <soap:Header>\n" +
      "    <t:RequestServerVersion Version=\"Exchange2007_SP1\" />\n" +
      "  </soap:Header>\n" +
      "  <soap:Body>\n" +
      "    <m:CreateItem MessageDisposition=\"SendAndSaveCopy\">\n" +
      "      <m:SavedItemFolderId>\n" +
      "        <t:DistinguishedFolderId Id=\"sentitems\" />\n" +
      "      </m:SavedItemFolderId>\n" +
      "      <m:Items>\n" +
      "        <t:Message>\n" +
      "          <t:Subject>Company Soccer Team</t:Subject>\n" +
      "          <t:Body BodyType=\"HTML\">Are you interested in joining?</t:Body>\n" +
      "          <t:ToRecipients>\n" +
      "            <t:Mailbox>\n" +
      "              <t:EmailAddress>sadie@contoso.com</t:EmailAddress>\n" +
      "              </t:Mailbox>\n" +
      "          </t:ToRecipients>\n" +
      "        </t:Message>\n" +
      "      </m:Items>\n" +
      "    </m:CreateItem>\n" +
      "  </soap:Body>\n" +
      "</soap:Envelope>\n";
      // Write the create item operation request to the console and log file.
      Tracing.WriteLine("Get folder operation request:");
      Tracing.WriteLine(createItemSOAPRequest);
      var getFolderRequest = WebRequest.CreateHttp(Office365WebServicesURL);
      getFolderRequest.AllowAutoRedirect = false;
      getFolderRequest.Credentials = userCredentials;
      getFolderRequest.Method = "POST";
      getFolderRequest.ContentType = "text/xml";
      var requestWriter = new StreamWriter(getFolderRequest.GetRequestStream());
      requestWriter.Write(createItemSOAPRequest);
      requestWriter.Close();
      try
      {
        var getFolderResponse = (HttpWebResponse)(getFolderRequest.GetResponse());
        if (getFolderResponse.StatusCode == HttpStatusCode.OK)
        {
          var responseStream = getFolderResponse.GetResponseStream();
          XElement responseEnvelope = XElement.Load(responseStream);
          if (responseEnvelope != null)
          {
            // Write the response to the console and log file.
            Tracing.WriteLine("Response:");
            StringBuilder stringBuilder = new StringBuilder();
            XmlWriterSettings settings = new XmlWriterSettings();
            settings.Indent = true;
            XmlWriter writer = XmlWriter.Create(stringBuilder, settings);
            responseEnvelope.Save(writer);
            writer.Close();
            Tracing.WriteLine(stringBuilder.ToString());
            // Check the response for error codes. If there is an error, throw an application exception.
            IEnumerable<XElement> errorCodes = from errorCode in responseEnvelope.Descendants
                                               ("{http://schemas.microsoft.com/exchange/services/2006/messages}ResponseCode")
                                               select errorCode;
            foreach (var errorCode in errorCodes)
            {
              if (errorCode.Value != "NoError")
              {
                switch (errorCode.Parent.Name.LocalName.ToString())
                {
                  case "Response":
                    string responseError = "Response-level error getting inbox information:\n" + errorCode.Value;
                    throw new ApplicationException(responseError);
                  case "UserResponse":
                    string userError = "User-level error getting inbox information:\n" + errorCode.Value;
                    throw new ApplicationException(userError);
                }
              }
            }
            Tracing.WriteLine("Message sent successfully.");
          }
        }
      }
      catch (WebException ex)
      {
        Tracing.WriteLine("Caught Web exception:");
        Tracing.WriteLine(ex.Message);
      }
      catch (ApplicationException ex)
      {
        Tracing.WriteLine("Caught application exception:");
        Tracing.WriteLine(ex.Message);
      }

Siguientes pasosNext steps

Ahora que ya ha escrito su primera aplicación de EWS, está listo para descubrir otras formas de usar EWS. A continuación, le damos algunas ideas para empezar.Now that you've written your first EWS application, you're ready to discover other ways to use EWS. Here are some ideas to get you started:

Si surge algún problema con la aplicación envíe una pregunta o un comentario al foro (y no olvide leer la primera publicación).If you run into any issues with your application, try posting a question or comment in the forum (and don't forget to read the first post).

Vea tambiénSee also