Поделиться через


Работа со скрытыми папками с помощью 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 , также указывают, какие папки в иерархии скрыты.

См. также