使用 Exchange 中的 EWS 处理文件夹
了解如何使用 Exchange 中的 EWS 托管 API 或 EWS 创建、获取、更新和删除文件夹。
Exchange 中的 EWS 使用文件夹组织和整理邮箱。 使用 EWS 托管 API 或 EWS 新建、获取、更新和删除文件夹。 下表中列出的每个方法或操作都对 Folder 对象、 Folder 类型或派生的文件夹类或类型之一执行。
表 1. 用于创建、获取、更新和删除文件夹的方法和操作
若要... | EWS 托管的 API 方法 | EWS 操作 |
---|---|---|
创建文件夹 | Folder.Save | CreateFolder |
创建文件夹层次结构 | 不可用 | CreateFolderPath |
获取文件夹 | Folder.Bind | GetFolder |
获取文件夹层次结构 | Folder.FindFolders | FindFolder |
更新文件夹 | Folder.Update | UpdateFolder |
删除文件夹 | Folder.Delete | DeleteFolder |
使用 EWS 托管 API 创建文件夹
下列代码示例演示如何使用 Folder 类创建一个新的通用文件夹,其中 DisplayName 为"自定义文件夹", FolderClass 属性值为 IPF.Note。 Folder.Save 方法将文件夹另存为“收件箱”文件夹的子文件夹。
这些示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。
// Create a custom folder.
Folder folder = new Folder(service);
folder.DisplayName = "Custom Folder";
folder.FolderClass = "IPF.Note";
// Save the folder as a child folder of the Inbox.
folder.Save(WellKnownFolderName.Inbox);
如果要创建不同类型的文件夹(如 CalendarFolder、 ContactsFolder、 SearchFolder或 TasksFolder),请创建特定类的新实例(而不是泛型 Folder 类),并且不设置 FolderClass 属性。 例如,下面的代码示例说明了如何新建 TasksFolder。
// Create a custom Tasks folder.
TasksFolder folder = new TasksFolder(service);
folder.DisplayName = "Custom Tasks";
// Save the folder as a child folder in the Inbox folder.
// This method call results in a CreateFolder call to EWS.
folder.Save(WellKnownFolderName.Inbox);
如果尝试创建特定类的实例并设置 FolderClass 属性,则会引发 ErrorNoFolderClassOverride 错误。
请注意,不能使用 EWS 托管 API 在单个方法调用中批量创建多个文件夹。
使用 EWS 创建文件夹
可以使用 EWS 创建一个或多个文件夹。
若要创建单个文件夹,请发送 CreateFolder 操作请求邮件。 CreateFolder 操作请求指示父文件夹是收件箱,DisplayName为"自定义文件夹",FolderClass 元素值为 IPF.Note。
这也是 EWS 托管 API 在创建新文件夹并调用 Folder.Save 方法时发送的 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:CreateFolder>
<m:ParentFolderId>
<t:DistinguishedFolderId Id="inbox" />
</m:ParentFolderId>
<m:Folders>
<t:Folder>
<t:FolderClass>IPF.Note</t:FolderClass>
<t:DisplayName>Custom Folder</t:DisplayName>
</t:Folder>
</m:Folders>
</m:CreateFolder>
</soap:Body>
</soap:Envelope>
服务器使用 CreateFolderResponse 邮件响应 CreateFolder 请求,其中包括 ResponseCode 值 NoError(表示文件夹创建成功)和新创建邮件的 FolderId。
如果要创建多个文件夹,请在 CreateFolder 操作请求消息中包含多个Folder元素。 所有新文件夹必须在同一父文件夹中。
使用 EWS 创建文件夹层次结构
可以使用 EWS CreateFolderPath 操作在单个调用中创建文件夹层次结构。 EWS 托管 API 中不提供相同的功能。 相反,如果使用的是 EWS 托管 API,则可以逐个创建文件夹,如使用 EWS 创建文件夹中所示。
注意
EWS 托管 API 无法实现此功能。
使用 EWS 托管 API 获取文件夹
下面的代码示例演示如何使用 Folder.Bind 方法获取收件箱文件夹。 最佳做法是将返回的属性限制为仅返回应用程序所需的属性。 此示例通过创建 PropertySet 对象并将 IdOnly 值应用于 BasePropertySet 属性,将返回属性限制为仅包含 Id 属性。
此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。
// As a best practice, limit the properties returned to only those that are required.
// In this scenario, you only need the FolderId.
PropertySet propSet = new PropertySet(BasePropertySet.IdOnly);
// Bind to an existing folder and get only the properties specified in the PropertySet.
// This method call results in a GetFolder call to EWS.
Folder rootfolder = Folder.Bind(service, WellKnownFolderName.Inbox, propSet);
如果需要返回其他属性,请将 FolderSchema 类中的属性添加到 PropertySet,或使用重载的 Bind 方法之一,以返回所有第一类属性。
请注意,不能使用 EWS 托管 API 一次获取多个文件夹。 必须在每个文件夹上分别调用 Bind 方法。
使用 EWS 获取文件夹
可以使用 EWS 获取单个文件夹或多个文件夹。
若要获取单个文件夹,请将 GetFolder 操作请求邮件发送到服务器。 在下面的示例中, BaseShape 设置为 IdOnly,因此仅返回指定文件夹的 FolderId。 FolderIds 元素指示要检索的文件夹是收件箱文件夹。
这也是 EWS 托管 API 在使用 Folder.Bind 方法绑定到文件夹时发送的 XML 请求。
如果要获取多个文件夹,请在 GetFolder 操作请求消息中包含多个FolderIds元素。
<?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:GetFolder>
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
</m:FolderShape>
<m:FolderIds>
<t:DistinguishedFolderId Id="inbox" />
</m:FolderIds>
</m:GetFolder>
</soap:Body>
</soap:Envelope>
下面的 XML 示例演示 GetFolderResponse 从服务器发送到客户端以响应 GetFolder 操作请求的消息。 它仅包含 “收件箱”文件夹的 FolderId 值。 为了方便读取,已缩短一些属性和元素的值。
<?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="800"
MinorBuildNumber="16"
Version="V2_6"
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:GetFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:GetFolderResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:Folders>
<t:Folder>
<t:FolderId Id="AAAENAAA=" ChangeKey="AQAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAEkbCr"/>
</t:Folder>
</m:Folders>
</m:GetFolderResponseMessage>
</m:ResponseMessages>
</m:GetFolderResponse>
</s:Body>
</s:Envelope>
使用 EWS 托管 API 获取文件夹层次结构
下面的代码示例演示如何检索指定根文件夹的子文件夹。 此示例检索 MsgFolderRoot 文件夹的子文件夹,该文件夹是 IPM 子树的根目录(存储邮箱文件夹和项目)。
在此示例中,将创建 FolderView 类对象,以限制 Folder.FindFolders 方法响应的结果。 此方案将属性限制为返回到以下内容:ID、 DisplayName,以及指示该文件夹是否为隐藏文件夹的扩展属性。 将 FolderView.Traversal 值设置为 Deep 以执行递归搜索,以便服务器检索子文件夹,并将根文件夹设置为 MsgFolderRoot,以便服务器返回所有用户的文件夹(并且服务器不会返回非 IPM 子树中的系统文件夹)。
此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。
// Create a new folder view, and pass in the maximum number of folders to return.
FolderView view = new FolderView(folderViewSize);
// Create an extended property definition for the PR_ATTR_HIDDEN property,
// so that your results will indicate whether the folder is a hidden folder.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
// As a best practice, limit the properties returned to only those required.
// In this case, return the folder ID, DisplayName, and the value of the isHiddenProp
// extended property.
view.PropertySet = new PropertySet(BasePropertySet.IdOnly, FolderSchema.DisplayName, isHiddenProp);
// Indicate a Traversal value of Deep, so that all subfolders are retrieved.
view.Traversal = FolderTraversal.Deep;
// Call FindFolders to retrieve the folder hierarchy, starting with the MsgFolderRoot folder.
// This method call results in a FindFolder call to EWS.
FindFoldersResults findFolderResults = service.FindFolders(WellKnownFolderName.MsgFolderRoot, view);
使用 EWS 获取文件夹层次结构
以下 XML 示例显示如何使用 FindFolder 操作通过 EWS 检索文件夹层次结构。 此示例检索 msgfolderroot 文件夹(IPM 子树的根目录)及其所有子文件夹。 Traversal 属性设置为 Deep,以便服务器对文件夹层次结构执行递归搜索,并且仅返回响应中指定根目录下的文件夹和子文件夹。 在此示例中, BaseShape 元素设置为 IdOnly ,以便服务器仅返回 FolderId 元素。 若要使输出更易于理解,请将 DisplayName 元素包含在结果中,方法是将其包含在请求的 AdditionalProperties 元素中,以及 PR_ATTR_HIDDEN 属性的 ExtendedFieldURI 值, 以便知道这些文件夹是否为隐藏文件夹。
这也是在您调用 FindFolders 方法时 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:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:FieldURI FieldURI="folder:DisplayName" />
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
</t:AdditionalProperties>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="100"
Offset="0"
BasePoint="Beginning" />
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="msgfolderroot" />
</m:ParentFolderIds>
</m:FindFolder>
</soap:Body>
</soap:Envelope>
下面的 XML 示例演示 FindFolderResponse 从服务器发送到客户端以响应 FindFolder 操作请求的消息。 它仅包含 FolderId、DisplayName,以及msgrootfolder 文件夹下所有子文件夹的 PR_ATTR_HIDDEN 扩展属性的值。 如果 Value 元素设置为 true,应在客户端视图中隐藏文件夹。
这也是 EWS 托管 API 通过使用 FindFolder 方法获取多个文件夹时发送的 XML 响应。 为了便于阅读,某些属性和元素的值已缩短,并且为了简洁起见,未包含某些文件夹。
<?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="815"
MinorBuildNumber="6"
Version="V2_7"
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:FindFolderResponse xmlns:m="http://schemas.microsoft.com/exchange/services/2006/messages"
xmlns:t="http://schemas.microsoft.com/exchange/services/2006/types">
<m:ResponseMessages>
<m:FindFolderResponseMessage ResponseClass="Success">
<m:ResponseCode>NoError</m:ResponseCode>
<m:RootFolder IndexedPagingOffset="16"
TotalItemsInView="16"
IncludesLastItemInRange="true">
<t:Folders>
<t:CalendarFolder>
<t:FolderId Id="AAAEOAAA="
ChangeKey="AgAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAA3"/>
<t:DisplayName>Calendar</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean"/>
<t:Value>false</t:Value>
</t:ExtendedProperty>
</t:CalendarFolder>
<t:ContactsFolder>
<t:FolderId Id="AAAEPAAA="
ChangeKey="AwAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAA4"/>
<t:DisplayName>Contacts</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean"/>
<t:Value>false</t:Value>
</t:ExtendedProperty>
</t:ContactsFolder>
<t:ContactsFolder>
<t:FolderId Id="AAAUKAAA="
ChangeKey="AwAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAAS5"/>
<t:DisplayName>Recipient Cache</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean"/>
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:ContactsFolder>
<t:Folder>
<t:FolderId Id="AAAUJAAA="
ChangeKey="AQAAABYAAAAPxolXAHv3TaHUnjW8wWqXAAAAAASx"/>
<t:DisplayName>Conversation Action Settings</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean"/>
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:Folder>
…
</t:Folders>
</m:RootFolder>
</m:FindFolderResponseMessage>
</m:ResponseMessages>
</m:FindFolderResponse>
</s:Body>
</s:Envelope>
使用 EWS 托管 API 更新文件夹
下面的代码示例演示如何使用 EWS 托管 API 更新文件夹的显示名称。
首先,创建 PropertySet 以限制服务器在 Folder.Bind 响应中返回的属性数。 建议使用 IdOnlyBasePropertySet 来减少对 Exchange 数据库的调用。 接下来,使用 Bind 方法绑定到要更新的文件夹。 然后,更新 DisplayName 属性,并使用 Folder.Update 方法保存更改。
在此示例中假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。 本地变量 folderId 是要更新的文件夹的 ID 。
// As a best practice, only include the ID value in the PropertySet.
PropertySet propertySet = new PropertySet(BasePropertySet.IdOnly);
// Bind to an existing folder and get the FolderId.
// This method call results in a GetFolder call to EWS.
Folder folder = Folder.Bind(service, folderId, propertySet);
// Update the display name of the folder.
folder.DisplayName = "Updated folder name";
// Save the updates.
// This method call results in an UpdateFolder call to EWS.
folder.Update();
使用 EWS 更新文件夹
以下 XML 示例演示如何使用 EWS 更新文件夹的显示名称。
首先,发送 GetFolder 操作请求消息以获取要更新的文件夹,如 使用 EWS获取文件夹层次结构中所示。
接下来,向服务器发送 UpdateFolder 操作请求消息以更新文件夹。 UpdateFolder操作请求将 DisplayName 更新为“已更新自定义文件夹”。
这也是 EWS 托管 API 在使用 Folder.Update 方法更新文件夹时发送的 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:UpdateFolder>
<m:FolderChanges>
<t:FolderChange>
<t:FolderId Id="OrV9ZAAA=" ChangeKey="AQAAABYAAABVzRdyy/cHS4XTC9itCRdUAAAOrXWb" />
<t:Updates>
<t:SetFolderField>
<t:FieldURI FieldURI="folder:DisplayName" />
<t:Folder>
<t:DisplayName>Updated Custom Folder</t:DisplayName>
</t:Folder>
</t:SetFolderField>
</t:Updates>
</t:FolderChange>
</m:FolderChanges>
</m:UpdateFolder>
</soap:Body>
</soap:Envelope>
服务器使用UpdateFolderResponse 消息响应 UpdateFolder 请求,该消息包含 NoError 的 ResponseCode 值,以及使用更新的 ChangeKey 属性值所更新的文件夹 FolderId。
使用 EWS 托管 API 删除文件夹
本文提供了一个基本示例,演示如何使用 EWS 托管 API 删除文件夹。 有关删除文件夹的更多详细信息,请参阅使用 Exchange 中的 EWS 删除项目。
如果要使用 EWS 托管 API 删除文件夹,请首先使用 Folder.Bind 方法将服务对象绑定到要删除的文件夹。 接下来,使用 Folder.Delete 方法通过 HardDelete 删除模式删除文件夹。
此示例假定 service 是有效的 ExchangeService 对象,且用户已通过 Exchange 服务器的身份验证。 本地变量 folderId 是要删除的文件夹的 ID 。
// Bind to an existing folder and get all its properties.
// This method call results in a GetFolder call to EWS.
Folder folder = Folder.Bind(service, folderId);
// HardDelete the folder.
// This method call results in a DeleteFolder call to EWS.
folder.Delete(DeleteMode.HardDelete);
使用 EWS 删除文件夹
本文提供了一个基本 XML 示例,演示如何使用 EWS 删除文件夹。 有关删除文件夹的更多详细信息,请参阅使用 Exchange 中的 EWS 删除项目。
若要使用 EWS 删除文件夹,请首先发送 GetFolder 操作请求消息,以获取要更新的文件夹,如 使用 EWS 获取文件夹中所示。
接下来,将 DeleteFolder 操作请求消息发送到服务器,以删除文件夹。 DeleteFolder 操作请求指示 DeleteType 为 HardDelete,并且它包含要删除的文件夹的 FolderId。
这也是使用 Folder.Delete 方法删除文件夹时 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:DeleteFolder DeleteType="HardDelete">
<m:FolderIds>
<t:FolderId Id="OrV9ZAAA=" ChangeKey="AQAAABYAAABVzRdyy/cHS4XTC9itCRdUAAAOrXWf" />
</m:FolderIds>
</m:DeleteFolder>
</soap:Body>
</soap:Envelope>
服务器使用 DeleteFolderResponse 邮件响应 DeleteFolder 请求,该邮件中包括 NoError 的 ResponseCode 值,该值表示文件夹删除成功。
后续步骤
检索到服务器上文件夹或更改文件夹后,可能希望同步文件夹层次结构或订阅有关服务器上文件夹更改的通知。