使用 Exchange 中的 EWS 从电子邮件中提取实体
了解如何使用 Exchange 中的 EWS 托管 API 或 EWS 从电子邮件正文中提取信息。
可以使用 EWS 托管 API 或 EWS 访问 Exchange 服务器从电子邮件中提取的地址、联系人、电子邮件地址、会议建议、电话号码、任务和 URL。 然后,可以将此信息用于新应用程序或建议现有应用程序中的后续操作。 例如,如果在电子邮件中标识了联系人实体、会议建议或任务建议,则应用程序可以建议创建包含预填充信息的新项目。 通过使用提取的实体,你可以利用数据背后的意图,并帮助用户将其电子邮件内容无缝集成到可操作的结果中。
已将地址、联系人、电子邮件地址、会议建议、电话号码、任务和 URL 的实体提取内置到 Exchange 存储中的每个项中。 如果使用 EWS 托管 API, Item.EntityExtractionResult 属性将在 Item.Bind 方法调用中为你检索实体。 如果使用 EWS, EntityExtractionResult 元素会在 GetItem 操作调用中为你获取所有提取的实体。 检索提取的实体的结果后,可以遍历每个实体集合以收集相关信息。 例如,如果提取了会议建议,则可以检索建议的会议主题、与会者列表、开始时间和结束时间。
表 1. 包含提取实体的 EWS 托管 API 属性和 EWS 元素
提取的实体 | EWS 托管 API 属性 | EWS 元素 |
---|---|---|
Addresses |
EntityExtractionResult.Addresses |
Addresses |
联系人 |
EntityExtractionResult.Contacts |
联系人 |
电子邮件地址 |
EntityExtractionResult.EmailAddresses |
EmailAddresses |
会议建议 |
EntityExtractionResult.MeetingSuggestions |
MeetingSuggestions |
电话号码 |
EntityExtractionResult.PhoneNumbers |
PhoneNumbers |
任务建议 |
EntityExtractionResult.TaskSuggestions |
TaskSuggestions |
URL |
EntityExtractionResult.Urls |
Urls |
由于实体提取依赖于自然语言识别,因此实体的识别可能是不确定的,成功有时依赖于上下文。 为了演示自然语言识别的工作原理,本文中的示例使用以下电子邮件作为输入。
From: Ronnie Sturgis
To: Sadie Daniels
Subject: Dinner party
Hi Sadie
Are you free this Friday at 7 to join us for a dinner party at our house?
We're at 789 International Blvd, St Paul MN 55104.
Our number is 612-555-0158 if you have trouble finding it.
Please RSVP to either myself or Mara (mara@contoso.com) before Friday morning. Best for you organics (http://www.bestforyouorganics.com) will be catering so we can fully enjoy ourselves!
Also, can you forward this to Magdalena? I don't have her contact information.
See you then!
Ronnie
使用 EWS 托管 API 从电子邮件中提取所有实体
下面的代码示例演示如何显示服务器提取的所有实体,方法是使用 Item.Bind 方法,然后枚举每个提取的实体及其属性。
此示例假定 服务 是有效的 ExchangeService 对象, ItemId 是要移动或复制的电子邮件的 ID 。
public static void ExtractEntities(ExchangeService service, ItemId ItemId)
{
// 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, ItemSchema.EntityExtractionResult);
// Get the item from the server.
// This method call results in an GetItem call to EWS.
Item item = Item.Bind(service, ItemId, propSet);
Console.WriteLine("The following entities have been extracted from the message:");
Console.WriteLine(" ");
// If address entities are extracted from the message, print the results.
if (item.EntityExtractionResult != null)
{
if (item.EntityExtractionResult.Addresses != null)
{
Console.WriteLine("--------------------Addresses---------------------------");
foreach (AddressEntity address in item.EntityExtractionResult.Addresses)
{
Console.WriteLine("Address: {0}", address.Address);
}
Console.WriteLine(" ");
}
// If contact entities are extracted from the message, print the results.
if (item.EntityExtractionResult.Contacts != null)
{
Console.WriteLine("--------------------Contacts----------------------------");
foreach (ContactEntity contact in item.EntityExtractionResult.Contacts)
{
Console.WriteLine("Addresses: {0}", contact.Addresses);
Console.WriteLine("Business name: {0}", contact.BusinessName);
Console.WriteLine("Contact string: {0}", contact.ContactString);
Console.WriteLine("Email addresses: {0}", contact.EmailAddresses);
Console.WriteLine("Person name: {0}", contact.PersonName);
Console.WriteLine("Phone numbers: {0}", contact.PhoneNumbers);
Console.WriteLine("URLs: {0}", contact.Urls);
}
Console.WriteLine(" ");
}
// If email address entities are extracted from the message, print the results.
if (item.EntityExtractionResult.EmailAddresses != null)
{
Console.WriteLine("--------------------Email addresses---------------------");
foreach (EmailAddressEntity email in item.EntityExtractionResult.EmailAddresses)
{
Console.WriteLine("Email addresses: {0}", email.EmailAddress);
}
Console.WriteLine(" ");
}
// If meeting suggestion entities are extracted from the message, print the results.
if (item.EntityExtractionResult.MeetingSuggestions != null)
{
Console.WriteLine("--------------------Meeting suggestions-----------------");
foreach (MeetingSuggestion meetingSuggestion in item.EntityExtractionResult.MeetingSuggestions)
{
Console.WriteLine("Meeting subject: {0}", meetingSuggestion.Subject);
Console.WriteLine("Meeting string: {0}", meetingSuggestion.MeetingString);
foreach (EmailUserEntity attendee in meetingSuggestion.Attendees)
{
Console.WriteLine("Attendee name: {0}", attendee.Name);
Console.WriteLine("Attendee user ID: {0}", attendee.UserId);
}
Console.WriteLine("Start time: {0}", meetingSuggestion.StartTime);
Console.WriteLine("End time: {0}", meetingSuggestion.EndTime);
Console.WriteLine("Location: {0}", meetingSuggestion.Location);
}
Console.WriteLine(" ");
}
// If phone number entities are extracted from the message, print the results.
if (item.EntityExtractionResult.PhoneNumbers != null)
{
Console.WriteLine("--------------------Phone numbers-----------------------");
foreach (PhoneEntity phone in item.EntityExtractionResult.PhoneNumbers)
{
Console.WriteLine("Original phone string: {0}", phone.OriginalPhoneString);
Console.WriteLine("Phone string: {0}", phone.PhoneString);
Console.WriteLine("Type: {0}", phone.Type);
}
Console.WriteLine(" ");
}
// If task suggestion entities are extracted from the message, print the results.
if (item.EntityExtractionResult.TaskSuggestions != null)
{
Console.WriteLine("--------------------Task suggestions--------------------");
foreach (TaskSuggestion task in item.EntityExtractionResult.TaskSuggestions)
{
foreach (EmailUserEntity assignee in task.Assignees)
{
Console.WriteLine("Assignee name: {0}", assignee.Name);
Console.WriteLine("Assignee user ID: {0}", assignee.UserId);
}
Console.WriteLine("Task string: {0}", task.TaskString);
}
Console.WriteLine(" ");
}
// If URL entities are extracted from the message, print the results.
if (item.EntityExtractionResult.Urls != null)
{
Console.WriteLine("--------------------URLs--------------------------------");
foreach (UrlEntity url in item.EntityExtractionResult.Urls)
{
Console.WriteLine("URL: {0}", url.Url);
}
Console.WriteLine(" ");
}
}
// If no entities are extracted from the message, print the result.
else if (item.EntityExtractionResult == null)
{
Console.WriteLine("No entities extracted");
}
}
控制台上显示以下输出。
The following entities have been extracted from the message:
--------------------Addresses---------------------------
Address: 789 International Blvd, St Paul MN 55104
--------------------Contacts----------------------------
Addresses:
Business name:
Contact string: Mara (mara@contoso.com)
Email addresses: mara@contoso.com
Person name: Mara
Phone numbers:
URLs:
--------------------Email addresses---------------------
Email addresses: mara@contoso.com
--------------------Meeting suggestions-----------------
Meeting subject: dinner party
Meeting string: Are you free this Friday at 7 to join us for a dinner party at our house?
Attendee name: Ronnie Sturgis
Attendee user ID: ronnie@contoso.com
Attendee name: Sadie Daniels
Attendee user ID: sadie@cntoso.com
Start time: 10/1/0104 2:00:00 PM
End time: 10/1/0104 2:30:00 PM
Location:
--------------------Phone numbers-----------------------
Original phone string: 612-555-0158
Phone string: 6125550158
Type: Unspecified
--------------------Task suggestions--------------------
Assignee name: Sadie Daniels
Assignee user ID: sadie@contoso.com
Task string: Also, can you forward this to Magdalena?
--------------------URLs--------------------------------
URL: http://www.bestforyouorganics.com
请注意,所有地址、联系人、电子邮件地址、电话号码、任务和 URL 均按预期提取。 但是,会议建议有点复杂。 请注意,会议建议的开始时间和结束时间不是你所期望的。 电子邮件中的开始时间为“本周五 7 点”,但开始时间的提取值为 10/1/0104 2:00:00 PM。 这是因为服务器提取的开始时间和结束时间是编码日期。 有关如何解释会议建议中的 dateTime 值的详细信息,请参阅 [MS-OXCEXT]:客户端扩展消息对象协议。
使用 EWS 从电子邮件中提取所有实体
下面的代码示例演示如何使用 GetItem 操作和 EntityExtractionResult 元素从项检索提取的实体。
这也是使用 Bind 方法使用 EWS 托管 API 从电子邮件中提取所有实体时,EWS 托管 API 发送的 XML 请求。
为了提高可读性, 将缩短 ItemId 元素的值。
<?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="Exchange2013" />
</soap:Header>
<soap:Body>
<m:GetItem>
<m:ItemShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:FieldURI FieldURI="item:EntityExtractionResult" />
</t:AdditionalProperties>
</m:ItemShape>
<m:ItemIds>
<t:ItemId Id="sVC5AAA=" />
</m:ItemIds>
</m:GetItem>
</soap:Body>
</soap:Envelope>
服务器使用包含 ResponseCode 值 NoError 的 GetItemResponse 邮件响应 GetItem 请求,该值指示已成功检索电子邮件。 响应还包括每个提取实体的 EntityExtractionResult 。
为了提高可读性, 将缩短 ItemId 元素的值。
<?xml version="1.0" encoding="utf-8"?>
<s:Envelope xmlns:s="https://schemas.xmlsoap.org/soap/envelope/">
<s:Header>
<h:ServerVersionInfo MajorVersion="15"
MinorVersion="0"
MajorBuildNumber="883"
MinorBuildNumber="10"
Version="V2_10"
xmlns:h="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns="http://schemas.microsoft.com/exchange/services/2006/types"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" />
</s:Header>
<s:Body xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:xsd="http://www.w3.org/2001/XMLSchema">
<m:GetItemResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetItemResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Items>
<t:Message>
<t:ItemId Id="sVC5AAA="
ChangeKey="CQAAABYAAAD32nSTjepyT63rYH17n9THAAAOOqJN" />
<t:EntityExtractionResult>
<t:Addresses>
<t:AddressEntity>
<t:Position>LatestReply</t:Position>
<t:Address>789 International Blvd, St Paul MN 55104</t:Address>
</t:AddressEntity>
</t:Addresses>
<t:MeetingSuggestions>
<t:MeetingSuggestion>
<t:Position>LatestReply</t:Position>
<t:Attendees>
<t:EmailUser>
<t:Name>Ronnie Sturgis</t:Name>
<t:UserId>ronnie@contoso.com</t:UserId>
</t:EmailUser>
<t:EmailUser>
<t:Name>Sadie Daniels</t:Name>
<t:UserId>sadie@contoso.com</t:UserId>
</t:EmailUser>
</t:Attendees>
<t:Subject>dinner party</t:Subject>
<t:MeetingString>Are you free this Friday at 7 to join us for a dinner party at our house?</t:MeetingString>
<t:StartTime>0104-10-01T19:00:00Z</t:StartTime>
<t:EndTime>0104-10-01T19:30:00Z</t:EndTime>
</t:MeetingSuggestion>
</t:MeetingSuggestions>
<t:TaskSuggestions>
<t:TaskSuggestion>
<t:Position>LatestReply</t:Position>
<t:TaskString>Also, can you forward this to Magdalena?</t:TaskString>
<t:Assignees>
<t:EmailUser>
<t:Name>Sadie Daniels</t:Name>
<t:UserId>sadie@contoso.com</t:UserId>
</t:EmailUser>
</t:Assignees>
</t:TaskSuggestion>
</t:TaskSuggestions>
<t:EmailAddresses>
<t:EmailAddressEntity>
<t:Position>LatestReply</t:Position>
<t:EmailAddress>mara@contoso.com</t:EmailAddress>
</t:EmailAddressEntity>
</t:EmailAddresses>
<t:Contacts>
<t:Contact>
<t:Position>LatestReply</t:Position>
<t:PersonName>Mara</t:PersonName>
<t:EmailAddresses>
<t:EmailAddress>mara@contoso.com</t:EmailAddress>
</t:EmailAddresses>
<t:ContactString>Mara (mara@contoso.com</t:ContactString>
</t:Contact>
</t:Contacts>
<t:Urls>
<t:UrlEntity>
<t:Position>LatestReply</t:Position>
<t:Url>http://www.bestforyouorganics.com</t:Url>
</t:UrlEntity>
</t:Urls>
<t:PhoneNumbers>
<t:Phone>
<t:Position>LatestReply</t:Position>
<t:OriginalPhoneString>612-555-0158</t:OriginalPhoneString>
<t:PhoneString>6125550158</t:PhoneString>
<t:Type>Unspecified</t:Type>
</t:Phone>
</t:PhoneNumbers>
</t:EntityExtractionResult>
</t:Message>
</m:Items>
</m:GetItemResponseMessage>
</m:ResponseMessages>
</m:GetItemResponse>
</s:Body>
</s:Envelope>
请注意,所有地址、联系人、电子邮件地址、电话号码、任务和 URL 均按预期提取。 但是,会议建议有点复杂。 请注意,会议建议的开始时间和结束时间不是你所期望的。 电子邮件中的开始时间为“本周五 7 点”,但开始时间的提取值为 10/1/0104 2:00:00 PM。 这是因为服务器提取的开始时间和结束时间是编码日期。 有关解释会议建议中的 dateTime 值的详细信息,请参阅 [MS-OXCEXT]:客户端扩展消息对象协议。