Работа со скрытыми папками с помощью EWS в Exchange
Узнайте, как сделать папку скрытой и найти скрытые папки с помощью управляемого API EWS или EWS в Exchange.
За одним исключением папки в корневом каталоге почтового ящика Exchange (поддереве, отличном от IPM) скрыты от пользователя. И наоборот, все папки в msgFolderRoot (поддереве IPM) видны пользователю. Так как же скрыть папку в msgFolderRoot? Это не так сложно — это сводится только к одному свойству, расширенному свойству PidTagAttributeHidden (0x10F4000B). Если для этого свойства задано значение true, Outlook или другой клиент, использующий свойство для определения видимости папки, будет скрывать папку в представлении пользователя. Так как это расширенное свойство, его сложнее использовать, чем среднее свойство папки, поэтому в этой статье описаны основные сценарии.
Таблица 1. Методы управляемого API EWS и операции EWS для работы со скрытыми папками
Задача | Метод управляемого API EWS | Операция EWS |
---|---|---|
Скрытие папки |
Folder.Bind , за которым следует Folder.Update |
GetFolder , за которым следует UpdateFolder |
Поиск скрытых папок |
FindFolders |
FindFolder |
Вам интересно, что такое одно исключение, т. е. какая папка в корневом is видима для пользователей? Это папка Finder (также известная как значение перечисления SearchFoldersWellKnownFolder или значение элемента searchfoldersDistinguishedFolderId ), которая содержит папки поиска пользователей. Папки поиска, созданные в папке Finder, видны пользователям Outlook. Если необходимо создать папку поиска, которая не видна пользователям, переместите ее в корневую папку, чтобы скрыть ее. В отличие от других папок, установка для свойства PidTagAttributeHiddenзначения true не приведет к скрытию папки поиска в папке Finder.
Скрытие папки с помощью управляемого API EWS
Вы можете сделать существующую папку скрытой, изменив расширенное свойство PidTagAttributeHidden на true. Сначала создайте расширенное определение свойства для свойства. Затем используйте метод Bind , чтобы перейти к папке, а затем обновите значение свойства PidTagAttributeHidden до true и с помощью метода Update сохраните изменения.
В этом примере предполагается, что служба является допустимым объектом ExchangeService для владельца почтового ящика, что пользователь прошел проверку подлинности на сервере Exchange Server и что folderId является допустимым Folder.Id , который определяет папку для скрытия.
private static void MakeHidden(FolderId folderId, ExchangeService service)
{
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
PropertySet propSet = new PropertySet(isHiddenProp);
// Bind to a folder and retrieve the PidTagAttributeHidden property.
Folder folder = Folder.Bind(service, folderId, propSet);
// Set the PidTagAttributeHidden property to true.
folder.SetExtendedProperty(isHiddenProp, true);
// Save the changes.
folder.Update();
}
Скрытие папки с помощью EWS
С помощью EWS можно сделать существующую папку скрытой, изменив расширенное свойство PidTagAttributeHidden на true. Сначала используйте операцию GetFolder , чтобы получить папку, а затем получите свойство PidTagAttributeHidden , включив элемент ExtendedFieldURI и установив для параметра PropertyTag значение 4340, а для свойства PropertyType — логическое значение.
Это также XML-запрос, который отправляет управляемый API EWS при использовании метода Bind для получения папки, прежде чем сделать ее скрытой.
Значение FolderId сокращается для удобства чтения.
<?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>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
</t:AdditionalProperties>
</m:FolderShape>
<m:FolderIds>
<t:FolderId Id="IQywAAAA==" />
</m:FolderIds>
</m:GetFolder>
</soap:Body>
</soap:Envelope>
Сервер отвечает на запрос GetFolder сообщением GetFolderResponse , которое содержит значение элемента ResponseCodeNoError, указывающее, что папка успешно получена. Ответ также содержит значение для свойства ExtendedProperty. В этом примере для параметра Value задано значение false, что означает, что папка в настоящее время не скрыта.
<?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="898"
MinorBuildNumber="23"
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: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="IQywAAAA=="
ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAABED" />
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean" />
<t:Value>false</t:Value>
</t:ExtendedProperty>
</t:Folder>
</m:Folders>
</m:GetFolderResponseMessage>
</m:ResponseMessages>
</m:GetFolderResponse>
</s:Body>
</s:Envelope>
Чтобы изменить значение ExtendedProperty на true, используйте операцию UpdateFolder . Добавьте элементы ExtendedProperty, ExtendedFieldURI и Value для расширенного свойства PidTagAttributeHidden и задайте для элемента Valueзначение true , чтобы скрыть папку.
Это также XML-запрос, который отправляет управляемый API EWS при использовании метода Update для обновления папки, чтобы сделать ее скрытой.
<?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="IQywAAAA=="
ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAABED" />
<t:Updates>
<t:SetFolderField>
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
<t:Folder>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:Folder>
</t:SetFolderField>
</t:Updates>
</t:FolderChange>
</m:FolderChanges>
</m:UpdateFolder>
</soap:Body>
</soap:Envelope>
Сервер отвечает на запрос UpdateFolder сообщением UpdateFolderResponse , которое содержит значение элемента ResponseCodeNoError, указывающее, что папка успешно обновлена и теперь скрыта.
Поиск всех скрытых папок с помощью управляемого API EWS
Вы можете найти все скрытые папки в родительской папке, создав расширенное определение свойства Для расширенного свойства PidTagAttributeHidden , а затем с помощью метода FindFolders найти папки со значением PidTagAttributeHidden , которое имеет значение true. В этом примере в качестве родительской папки для поиска используется msgFolderRoot, также известный как top of Information Store или IPM Subtree.
В этом примере предполагается, что служба является допустимым объектом ExchangeService для владельца почтового ящика и что пользователь прошел проверку подлинности на сервере Exchange Server.
private static void FindHiddenFolders(ExchangeService service)
{
// Create an extended property definition for the PidTagAttributeHidden property.
ExtendedPropertyDefinition isHiddenProp = new ExtendedPropertyDefinition(0x10f4, MapiPropertyType.Boolean);
// Create a folder view to retrieve up to 100 folders and
// retrieve only the PidTagAttributeHidden and the display name.
FolderView folderView = new FolderView(100);
folderView.PropertySet = new PropertySet(isHiddenProp, FolderSchema.DisplayName);
// Indicate a Traversal value of Deep, so that all subfolders are retrieved.
folderView.Traversal = FolderTraversal.Deep;
// Find all hidden folders under the MsgFolderRoot.
// This call results in a FindFolder call to EWS.
FindFoldersResults findFolder = service.FindFolders(WellKnownFolderName.MsgFolderRoot,
new SearchFilter.IsEqualTo(isHiddenProp, true), folderView);
// Display the folder ID and display name of each hidden folder.
foreach (Folder folder in findFolder)
{
Console.WriteLine("FolderId: {0}", folder.Id);
Console.WriteLine("DisplayName: {0}", folder.DisplayName);
Console.WriteLine("\r\n");
}
}
Поиск всех скрытых папок с помощью EWS
Вы можете использовать EWS для поиска всех скрытых папок в существующей папке, вызвав операцию FindFolder и выполнив поиск папок, для которых расширенное свойство PidTagAttributeHidden имеет значение true. Для этого включите ограничениеIsEqualTo, которое ищет элемент ExtendedFieldURI для свойства PidTagAttributeHidden ( PropertyTag — 4243, а значение PropertyType — boolean), как показано в следующем запросе. В этом примере в качестве родительской папки для поиска используется msgFolderRoot, также известный как top of Information Store или IPM Subtree.
Это также XML-запрос, который управляемый API EWS отправляет при использовании метода FindFolders для поиска всех скрытых папок.
<?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" />
<t:TimeZoneContext>
<t:TimeZoneDefinition Id="Central Standard Time" />
</t:TimeZoneContext>
</soap:Header>
<soap:Body>
<m:FindFolder Traversal="Deep">
<m:FolderShape>
<t:BaseShape>IdOnly</t:BaseShape>
<t:AdditionalProperties>
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
<t:FieldURI FieldURI="folder:DisplayName" />
</t:AdditionalProperties>
</m:FolderShape>
<m:IndexedPageFolderView MaxEntriesReturned="100"
Offset="0"
BasePoint="Beginning" />
<m:Restriction>
<t:IsEqualTo>
<t:ExtendedFieldURI PropertyTag="4340"
PropertyType="Boolean" />
<t:FieldURIOrConstant>
<t:Constant Value="true" />
</t:FieldURIOrConstant>
</t:IsEqualTo>
</m:Restriction>
<m:ParentFolderIds>
<t:DistinguishedFolderId Id="msgfolderroot" />
</m:ParentFolderIds>
</m:FindFolder>
</soap:Body>
</soap:Envelope>
Сервер отвечает на запрос FindFolder сообщением FindFolderResponse , которое содержит значение элемента ResponseCodeNoError, указывающее, что поиск в папке выполнен успешно, а также все скрытые папки в корневой папке сообщения.
Значения 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="898"
MinorBuildNumber="23"
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: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="6"
TotalItemsInView="6"
IncludesLastItemInRange="true">
<t:Folders>
<t:ContactsFolder>
<t:FolderId Id="IBHgAAAA=="
ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACz" />
<t:DisplayName>{06967759-274D-40B2-A3EB-D7F9E73727D7}</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:ContactsFolder>
<t:ContactsFolder>
<t:FolderId Id="IBHwAAAA=="
ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAAC7" />
<t:DisplayName>{A9E2BC46-B3A0-4243-B315-60D991004455}</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:ContactsFolder>
<t:ContactsFolder>
<t:FolderId Id="IBIQAAAA=="
ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAADO" />
<t:DisplayName>GAL Contacts</t:DisplayName>
<t:ExtendedProperty>
<t:ExtendedFieldURI PropertyTag="0x10f4"
PropertyType="Boolean" />
<t:Value>true</t:Value>
</t:ExtendedProperty>
</t:ContactsFolder>
<t:ContactsFolder>
<t:FolderId Id="IBHQAAAA=="
ChangeKey="AwAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACa" />
<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="HAAAAA=="
ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAAAACS" />
<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:Folder>
<t:FolderId Id="IQywAAAA=="
ChangeKey="AQAAABYAAAD32nSTjepyT63rYH17n9THAAAeZIBf" />
<t:DisplayName>TestFolder</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>
После создания скрытых или незакрытых папок может потребоваться получить иерархию папок или синхронизировать иерархию папок. Примеры, показывающие, как получить иерархию папок с помощью управляемого API EWS или получить иерархию папок с помощью EWS , также указывают, какие папки в иерархии скрыты.