使用 Exchange 中的 EWS 批量处理电子邮件

了解如何使用 Exchange 中的 EWS 托管 API 或 EWS 在单个调用中创建、获取、更新和删除电子邮件批。

可以使用 EWS 托管 API 或 EWS 来处理成批的电子邮件,以减少客户端对 Exchange 服务器的调用数。 使用 EWS 托管 API 批量创建、获取、更新、删除和发送邮件时,将使用 ExchangeService 对象方法,而处理单个电子邮件时,将使用 EmailMessage 对象方法。 如果使用 EWS,则使用相同的操作来处理单封和批电子邮件。

表 1. 用于处理批量电子邮件的 EWS 托管 API 方法和 EWS 操作

若要... 使用此 EWS 托管 API 方法 使用此 EWS 操作
批量创建电子邮件
ExchangeService.CreateItems
CreateItem
批量获取电子邮件
ExchangeService.BindToItems
GetItem
批量更新电子邮件
ExchangeService.UpdateItems
UpdateItem
批量删除电子邮件
ExchangeService.DeleteItems
DeleteItem

本文介绍如何使用 EWS 托管 API 或 EWS 完成电子邮件批处理的基本任务。

使用 EWS 托管 API 批量创建电子邮件

可以使用 EWS 托管 API CreateItems 方法批量创建消息,如以下示例所示。 本示例在本地创建三个 EmailMessage 对象,将每封邮件添加到集合,然后对邮件集合调用 CreateItems 方法。

此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。

public static Collection<ItemId> CreateDraftEmailInBatch(ExchangeService service)
{
    // These are unsaved local instances of an EmailMessage object.
    // Despite the required parameter of an ExchangeService object (service), no call
    // to an Exchange server is made when the objects are instantiated.
    // A call to the Exchange server is made when the service.CreateItems() method is called.
    EmailMessage message1 = new EmailMessage(service);
    EmailMessage message2 = new EmailMessage(service);
    EmailMessage message3 = new EmailMessage(service);
    // Set the properties on the first message.
    message1.Subject = "Project priorities";
    message1.Body = "(1) Buy pizza, (2) Eat pizza";
    message1.ToRecipients.Add("sadie@contoso.com");
    // Set the properties on the second message.
    message2.Subject = "Company Soccer Team";
    message2.Body = "Are you interested in joining?";
    message2.ToRecipients.Add("magdalena@contoso.com");
    // Set the properties on the third message.
    message3.Subject = "Code Blast";
    message3.Body = "Are you interested in getting together to finish the methods for the ContosoLive project?";
    message3.ToRecipients.Add("mack@contoso.com");
    // Add the EmailMessage objects to a collection.
    Collection<EmailMessage> messageItems = new Collection<EmailMessage>() { message1, message2, message3 };
    // Create the batch of email messages on the server.
    // This method call results in an CreateItem call to EWS.
    ServiceResponseCollection<ServiceResponse> response = service.CreateItems(messageItems, WellKnownFolderName.Drafts, MessageDisposition.SaveOnly, null);
    // Instantiate a collection of item IDs to populate from the values that are returned by the Exchange server.
    Collection<ItemId> itemIds = new Collection<ItemId>();
    // Collect the item IDs from the created email messages.
    foreach (EmailMessage message in messageItems)
    {
        try
        {
            itemIds.Add(message.Id);
            Console.WriteLine("Email message '{0}' created successfully.", message.Subject);
        }
        catch (Exception ex)
        {
            // Print out the exception and the last eight characters of the item ID.
            Console.WriteLine("Exception while creating message {0}: {1}", message.Id.ToString().Substring(144), ex.Message);
        }
    }
    // Check for success of the CreateItems method call.
    if (response.OverallResult == ServiceResult.Success)
    {
            Console.WriteLine("All locally created messages were successfully saved to the Drafts folder.");
            Console.WriteLine("\r\n");
    }

    // If the method did not return success, print the result message for each email.
    else
    {
        int counter = 1;
        foreach (ServiceResponse resp in response)
        {
            // Print out the result and the last eight characters of the item ID.
            Console.WriteLine("Result (message {0}), id {1}: {2}", counter, itemIds[counter - 1].ToString().Substring(144), resp.Result);
            Console.WriteLine("Error Code: {0}", resp.ErrorCode);
            Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);
            Console.WriteLine("\r\n");
            counter++;
        }
    }
    return itemIds;
}

请注意,该示例仅将邮件保存在 Drafts 文件夹中;它不发送消息。 有关如何发送邮件的详细信息,请参阅 使用 EWS 托管 API 批量发送电子邮件

使用 EWS 批量创建电子邮件

可以使用 CreateItem EWS 操作批量创建电子邮件,如以下代码示例所示。 这也是使用 EWS 托管 API 批量创建电子邮件时 EWS 托管 API 发送的 XML 请求。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:CreateItem MessageDisposition="SaveOnly">
      <m:SavedItemFolderId>
        <t:DistinguishedFolderId Id="drafts" />
      </m:SavedItemFolderId>
      <m:Items>
        <t:Message>
          <t:Subject>Project priorities</t:Subject>
          <t:Body BodyType="HTML">(1) Buy pizza, (2) Eat pizza</t:Body>
          <t:ToRecipients>
            <t:Mailbox>
              <t:EmailAddress>sadie@contoso.com</t:EmailAddress>
            </t:Mailbox>
          </t:ToRecipients>
        </t:Message>
        <t:Message>
          <t:Subject>Company Soccer Team</t:Subject>
          <t:Body BodyType="HTML">Are you interested in joining?</t:Body>
          <t:ToRecipients>
            <t:Mailbox>
              <t:EmailAddress>magdalena@contoso.com</t:EmailAddress>
            </t:Mailbox>
          </t:ToRecipients>
        </t:Message>
        <t:Message>
          <t:Subject>Code Blast</t:Subject>
          <t:Body BodyType="HTML">Are you interested in getting together to finish the methods for the ContosoLive project?</t:Body>
          <t:ToRecipients>
            <t:Mailbox>
              <t:EmailAddress>mack@contoso.com</t:EmailAddress>
            </t:Mailbox>
          </t:ToRecipients>
        </t:Message>
      </m:Items>
    </m:CreateItem>
  </soap:Body>
</soap:Envelope>

服务器使用 CreateItemResponse 消息响应 CreateItem 请求,其中包含每个新邮件的 ResponseCodeNoError,指示已成功创建和保存每封电子邮件。

请注意,该示例仅将邮件保存在 Drafts 文件夹中;它不发送消息。 有关如何发送邮件的详细信息,请参阅 使用 EWS 批量发送电子邮件

使用 EWS 托管 API 批量发送电子邮件

使用与批量创建电子邮件相同的代码发送电子邮件,但一些 CreateItems 方法参数已更改。 因此,若要使用 EWS 托管 API 发送电子邮件,请使用用于 批量创建电子邮件的代码,并将对 CreateItems 方法的调用替换为以下示例中的 调用。 在此示例中,邮件在“已发送邮件”文件夹中创建,邮件处置更改为 MessageDisposition.SendAndSaveCopy,以便发送邮件,而不仅仅是在本地保存。

// Create and send the batch of email messages on the server.
// This method call results in an CreateItem call to EWS.
ServiceResponseCollection<ServiceResponse> response = service.CreateItems(messageItems, WellKnownFolderName.SentItems, MessageDisposition.SendAndSaveCopy, null);

使用 EWS 批量发送电子邮件

使用与分批创建电子邮件相同的代码发送电子邮件,但 CreateItem 操作的一些属性值会更改。 因此,若要使用 EWS 发送电子邮件,请使用用于 批量创建电子邮件的代码,并将 MessageDisposition 值更改为“SendAndSaveCopy”,并将 DistinguishedFolderId 更改为“sentitems”,如以下代码示例所示。

<m:CreateItem MessageDisposition="SendAndSaveCopy">
  <m:SavedItemFolderId>
    <t:DistinguishedFolderId Id="sentitems" />
  </m:SavedItemFolderId>

服务器使用 CreateItemResponse 邮件响应 CreateItem 请求,该邮件包含针对每封新邮件的 ResponseCodeNoError,指示已成功创建和发送每封电子邮件。

使用 EWS 托管 API 批量获取电子邮件

可以使用 EWS 托管 API BindToItems 方法批量获取电子邮件,如以下示例所示。

此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。

public static Collection<EmailMessage> BatchGetEmailItems(ExchangeService service, Collection<ItemId> itemIds)
{
    // Create a property set that limits the properties returned by the Bind method to only those that are required.
    PropertySet propSet = new PropertySet(BasePropertySet.IdOnly, EmailMessageSchema.Subject, EmailMessageSchema.ToRecipients);
    // Get the items from the server.
    // This method call results in a GetItem call to EWS.
    ServiceResponseCollection<GetItemResponse> response = service.BindToItems(itemIds, propSet);

    // Instantiate a collection of EmailMessage objects to populate from the values that are returned by the Exchange server.
    Collection<EmailMessage> messageItems = new Collection<EmailMessage>();
    foreach (GetItemResponse getItemResponse in response)
    {
        try
        {
            Item item = getItemResponse.Item;
            EmailMessage message = (EmailMessage)item;
            messageItems.Add(message);
            // Print out confirmation and the last eight characters of the item ID.
            Console.WriteLine("Found item {0}.", message.Id.ToString().Substring(144));
        }
        catch (Exception ex)
        {
           Console.WriteLine("Exception while getting a message: {0}", ex.Message);
        }
    }
    // Check for success of the BindToItems method call.
    if (response.OverallResult == ServiceResult.Success)
    {
        Console.WriteLine("All email messages retrieved successfully.");
        Console.WriteLine("\r\n");
    }
        return messageItems;
}

使用 EWS 批量获取电子邮件

可以使用 GetItem EWS 操作和以下示例中的代码批量获取电子邮件。 这也是使用 EWS 托管 API 批量获取电子邮件时 EWS 托管 API 发送的 XML 请求。

ItemIdChangeKey 属性会缩短,以实现可读性。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:GetItem>
      <m:ItemShape>
        <t:BaseShape>IdOnly</t:BaseShape>
        <t:AdditionalProperties>
          <t:FieldURI FieldURI="item:Subject" />
          <t:FieldURI FieldURI="message:ToRecipients" />
        </t:AdditionalProperties>
      </m:ItemShape>
      <m:ItemIds>
        <t:ItemId Id="m4NxAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB0" />
        <t:ItemId Id="m4NyAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB1" />
        <t:ItemId Id="m4NzAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKB2" />
      </m:ItemIds>
    </m:GetItem>
  </soap:Body>
</soap:Envelope>

服务器使用 GetItemResponse 消息响应 GetItem 请求,该消息包含每个请求的消息的第一类属性

使用 EWS 托管 API 批量更新电子邮件

可以使用 EWS 托管 API UpdateItems 方法批量获取电子邮件,如以下示例所示。

有关可写电子邮件属性的列表,请参阅 Exchange EWS 中的Email属性和元素

有关如何在更新后发送草稿邮件的详细信息,请参阅 使用 EWS 托管 API 发送电子邮件

此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。

public static Collection<EmailMessage> BatchUpdateEmailItems(ExchangeService service, Collection<EmailMessage> messageItems)
{
    // Update the subject of each message locally.
    foreach (EmailMessage message in messageItems)
    {
        // Update the Subject of the email.
        message.Subject = "Updated subject at " + DateTime.Now;
        // Print out confirmation with the last eight characters of the item ID and the email subject.
        Console.WriteLine("Updated local email message {0} with the subject '{1}'.", message.Id.ToString().Substring(144), message.Subject);
    }
    // Send the item updates to the server.
    // This method call results in an UpdateItem call to EWS.
    ServiceResponseCollection<UpdateItemResponse> response = service.UpdateItems(messageItems, WellKnownFolderName.Drafts, ConflictResolutionMode.AutoResolve, MessageDisposition.SaveOnly, null);
    // Check for success of the UpdateItems method call.
    if (response.OverallResult == ServiceResult.Success)
    {
        Console.WriteLine("All email messages updated successfully.\r\n");
    }
    // If the method did not return success, print the result message for each email.
    else
    {
        Console.WriteLine("All emails were not successfully saved on the server.\r\n");
        int counter = 1;
        foreach (ServiceResponse resp in response)
        {
            Console.WriteLine("Result for (message {0}): {1}", counter, resp.Result);
            Console.WriteLine("Error Code: {0}", resp.ErrorCode);
            Console.WriteLine("ErrorMessage: {0}\r\n", resp.ErrorMessage);
            counter++;
        }
    }
    return messageItems;
}

使用 EWS 批量更新电子邮件

可以使用 GetItem EWS 操作批量更新电子邮件,如以下代码示例所示。 这也是使用 EWS 托管 API 批量更新电子邮件时 EWS 托管 API 发送的 XML 请求。

有关可写电子邮件元素的列表,请参阅 Exchange EWS 中的Email属性和元素

有关如何在更新后发送草稿邮件的详细信息,请参阅 使用 EWS 发送草稿电子邮件

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:UpdateItem MessageDisposition="SaveOnly"
                  ConflictResolution="AutoResolve">
      <m:SavedItemFolderId>
        <t:DistinguishedFolderId Id="drafts" />
      </m:SavedItemFolderId>
      <m:ItemChanges>
        <t:ItemChange>
          <t:ItemId Id="m4OVAAA="
                    ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKCy" />
          <t:Updates>
            <t:SetItemField>
              <t:FieldURI FieldURI="item:Subject" />
              <t:Message>
                <t:Subject>Updated subject at 1/17/2014 2:58:09 PM</t:Subject>
              </t:Message>
            </t:SetItemField>
          </t:Updates>
        </t:ItemChange>
        <t:ItemChange>
          <t:ItemId Id="m4OWAAA="
                    ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKCz" />
          <t:Updates>
            <t:SetItemField>
              <t:FieldURI FieldURI="item:Subject" />
              <t:Message>
                <t:Subject>Updated subject at 1/17/2014 2:58:09 PM</t:Subject>
              </t:Message>
            </t:SetItemField>
          </t:Updates>
        </t:ItemChange>
        <t:ItemChange>
          <t:ItemId Id="m4OXAAA="
                    ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKC0" />
          <t:Updates>
            <t:SetItemField>
              <t:FieldURI FieldURI="item:Subject" />
              <t:Message>
                <t:Subject>Updated subject at 1/17/2014 2:58:09 PM</t:Subject>
              </t:Message>
            </t:SetItemField>
          </t:Updates>
        </t:ItemChange>
      </m:ItemChanges>
    </m:UpdateItem>
  </soap:Body>
</soap:Envelope>

服务器使用 UpdateItemResponse 消息响应 UpdateItem 请求,该消息包含 NoErrorResponseCode 值,该值指示每个更新已成功保存在服务器上。 任何冲突都报告在 ConflictResult 元素中。

使用 EWS 托管 API 批量删除电子邮件

可以使用 EWS 托管 API DeleteItems 方法批量删除消息,如以下示例所示。

此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。

public static void BatchDeleteEmailItems(ExchangeService service, Collection<ItemId> itemIds)
{
    // Delete the batch of email message objects.
    // This method call results in an DeleteItem call to EWS.
    ServiceResponseCollection<ServiceResponse> response = service.DeleteItems(itemIds, DeleteMode.SoftDelete, null, AffectedTaskOccurrence.AllOccurrences);

    // Check for success of the DeleteItems method call.
    // DeleteItems returns success even if it does not find all the item IDs.
    if (response.OverallResult == ServiceResult.Success)
    {
        Console.WriteLine("Email messages deleted successfully.\r\n");
    }
    // If the method did not return success, print a message.
    else
    {
        Console.WriteLine("Not all email messages deleted successfully.\r\n");
    }
}

使用 EWS 批量删除电子邮件

可以使用 DeleteItem EWS 操作批量删除电子邮件,如以下代码示例所示。 这也是使用 EWS 托管 API 批量删除电子邮件时 EWS 托管 API 发送的 XML 请求。

<?xml version="1.0" encoding="utf-8"?>
<soap:Envelope xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
               xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
               xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types"
               xmlns:soap="https://schemas.xmlsoap.org/soap/envelope/">
  <soap:Header>
    <t:RequestServerVersion Version="Exchange2007_SP1" />
  </soap:Header>
  <soap:Body>
    <m:DeleteItem DeleteType="SoftDelete"
                  AffectedTaskOccurrences="AllOccurrences">
      <m:ItemIds>
        <t:ItemId Id="m4OkAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDE" />
        <t:ItemId Id="m4OlAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDF" />
        <t:ItemId Id="m4OmAAA="
                  ChangeKey="CQAAABYAAAApjGm7TnMWQ5TzjbhziLL0AAF/yKDG" />
      </m:ItemIds>
    </m:DeleteItem>
  </soap:Body>
</soap:Envelope>

服务器使用 DeleteItemResponse 消息响应 DeleteItem 请求,该消息包含已删除的每个项的 ResponseCodeNoError。 请注意,如果找不到项 ID,操作也会返回成功。

验证批处理是否成功完成

当无法按请求处理批处理请求中的一个或多个电子邮件时,将为每个失败的电子邮件返回错误,并按预期处理批处理中的其余电子邮件。 如果项目已删除,因此无法发送、检索或更新,或者该项目已移到其他文件夹,因此具有新的项目 ID,并且无法使用发送的项目 ID 进行修改,则批处理可能会失败。 本部分中的信息演示如何获取有关电子邮件批处理失败的错误详细信息。

若要使用 EWS 托管 API 验证批处理是否成功,可以检查 ServiceResponseCollectionOverallResult 属性是否等于 ServiceResult.Success。 如果是,则已成功处理所有电子邮件。 如果 OverallResult 不等于 ServiceResult.Success,则一个或多个电子邮件未成功处理。 ServiceResponseCollection 中返回的每个对象包含以下属性:

这些属性包含有关无法按请求处理电子邮件的原因的信息。 本文中的示例输出每个失败消息 的 ResultErrorCodeErrorMessage 。 可以使用这些结果来调查问题。

对于 EWS,若要验证批处理过程是否成功,请检查正在处理的每个项的 ResponseClass 属性。 下面是 ResponseMessageType 的基本结构,这是派生所有响应消息的基类型。

<ResponseMessage ResponseClass="Success | Warning | Error">
            <MessageText/>
            <ResponseCode/>
            <DescriptiveLinkKey/>
            <MessageXml/>
</ResponseMessage>

如果电子邮件处理成功,则 ResponseClass 属性设置为 “成功 ”;如果电子邮件未成功处理,则设置为 “错误 ”。 对于电子邮件,在批处理期间不会遇到 警告 。 如果 ResponseClassSuccess,则后面的 ResponseCode 元素也始终设置为 NoError。 如果 ResponseClassError,则需要检查 MessageTextResponseCodeMessageXml 元素的值,以确定导致问题的原因。 描述性LinkKey 当前未使用。

另请参阅