Exchange で EWS を使用して隠しフォルダーを操作する

Exchange で EWS マネージ API または EWS を使用して、フォルダーを非表示にしたり、隠しフォルダーを検索したりする方法について説明します。

1 つの例外を除き、Exchange メールボックスのルート内 (非 IPM サブツリー) のフォルダーはユーザーから非表示になっています。 逆に、MsgFolderRoot (IPM サブツリー) 内のすべてのフォルダーはユーザーに表示されます。 MsgFolderRoot の下のフォルダーを非表示にしてみましょう。 それほど複雑ではありません。たった 1 つのプロパティ (PidTagAttributeHidden (0x10F4000B) 拡張プロパティ) を操作するだけです。 このプロパティを true に設定すると、Outlook またはこのプロパティを使用してフォルダーの表示/非表示を決定する別のクライアントでは、ユーザーにはフォルダーが非表示になります。 これは拡張プロパティであるため、通常のフォルダー プロパティよりも使用するのが複雑です。そのため、この記事では、主なシナリオについて順を追って説明します。

表 1. 隠しフォルダーを処理するための EWS マネージ API メソッドと EWS 操作

タスク EWS マネージ API メソッド EWS 操作
フォルダーを非表示にする
Folder.Bind の後に Folder.Update
GetFolder の後に UpdateFolder
隠しフォルダーを検索する
FindFolders
FindFolder

ルート内のフォルダーのうち、ユーザーに表示されている例外のフォルダーは、 Finder フォルダー (SearchFoldersWellKnownFolder 列挙値または searchfoldersDistinguishedFolderId 要素値とも呼ばれる) です。これにはユーザーの検索フォルダーが含まれます。 Finder フォルダーに作成される検索フォルダーは、Outlook ユーザーに表示されます。 ユーザーに表示されない検索フォルダーを作成する必要がある場合は、ルート フォルダーに移動して非表示にします。 他のフォルダーとは異なり、PidTagAttributeHidden プロパティを true に設定しても、Finder フォルダー内の検索フォルダーは非表示にされません。

EWS マネージ API を使用してフォルダーを非表示にする

PidTagAttributeHidden 拡張プロパティを true に変更して、既存のフォルダーを隠しフォルダーにすることができます。 最初に、プロパティ用に拡張プロパティの定義を作成します。 次に、Bind メソッドを使用してフォルダーを見つけ、PidTagAttributeHidden プロパティの値を true に更新し、Update メソッドを使用して変更を保存します。

この例では、service がメールボックスの所有者に対して有効な ExchangeService オブジェクトであり、ユーザーは Exchange サーバーから認証されており、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 を使用してフォルダーを非表示にする

PidTagAttributeHidden 拡張プロパティを true に変更し、EWS を使用して、既存のフォルダーを隠しフォルダーにすることができます。 最初に、GetFolder 操作を使用してフォルダーを見つけ、ExtendedFieldURI 要素を含め、PropertyTag 値を 4340、PropertyType 値を Boolean に設定することによって PidTagAttributeHidden プロパティを取得します。

これは、隠しフォルダーにする前にフォルダーを取得するため Bind メソッドを使用する際に、EWS マネージ API が送信する XML 要求でもあります。

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 メッセージで応答します。このメッセージには、フォルダーが正常に取得されたことを示す、値が NoErrorResponseCode要素が含まれます。 この応答には、ExtendedPropertyValue も含まれます。 この例では、Valuefalse に設定されています。これは、フォルダーが現時点では非表示になっていないことを意味します。

<?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 操作を使用します。 要素の ExtendedPropertyExtendedFieldURIValuePidTagAttributeHidden 拡張プロパティに含め、Value 要素を true に設定してフォルダーを非表示にします。

これは、フォルダーを更新して隠しフォルダーにするため Update メソッドを使用する際に、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: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 メッセージで応答します。このメッセージには、フォルダーが正常に更新されて非表示にされたことを示す、NoErrorResponseCode 要素の値が含まれます。

EWS マネージ API を使用してすべての隠しフォルダーを検索する

親フォルダーにあるすべての隠しフォルダーは、PidTagAttributeHidden 拡張プロパティの拡張プロパティの定義を作成し、FindFolders メソッドを使用して PidTagAttributeHidden 値が true に設定されているフォルダーを検索することによって見つけることができます。 この例では、MsgFolderRoot (インフォメーション ストアの先頭または IPM サブツリーとも呼ばれる) が、検索する親フォルダーとして使用されます。

この例では、service はメールボックス所有者の有効な ExchangeService オブジェクトであり、ユーザーは Exchange サーバーから既に認証されていると想定しています。

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 を使用してすべての隠しフォルダーを検索する

FindFolder 操作を呼び出し、PidTagAttributeHidden 拡張プロパティが true に設定されているフォルダーを検索することによって、EWS を使用して既存のフォルダーの下のすべての隠しフォルダーを検索できます。 この検索を行うには、次の要求に示すように、ExtendedFieldURI 要素を検索する IsEqualToRestrictionPidTagAttributeHidden プロパティ (PropertyTag 値を 4243、PropertyType 値を Boolean に設定) に含めます。 この例では、MsgFolderRoot (インフォメーション ストアの先頭または IPM サブツリーとも呼ばれる) が、検索する親フォルダーとして使用されます。

これは、すべての隠しフォルダーを検索するのに 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" />
    <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 メッセージで応答します。このメッセージには、メッセージのルート フォルダーの下のすべての隠しフォルダーを含むフォルダー検索が正常に行われたことを示す、NoErrorResponseCode 要素の値が含まれます。

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>

フォルダーを非表示または再表示したら、フォルダー階層を取得するか、フォルダー階層を同期させることをお勧めします。 EWS マネージ API を使用してフォルダー階層を取得する方法または EWS を使用してフォルダー階層を取得する方法を示す例は、階層内のどのフォルダーが非表示にされているかも示します。

関連項目