[Microsoft Graph API+PHP]指定のフォルダ内にある未読メールのIDの一覧を読み取る

PHP

お疲れ様です。すぺきよです。

前回に引き続き、PHPとMicrosoft Graph APIを使ってOutlookから情報を読み取り処理する方法です。

今回は前回取得したフォルダのIDなどを使って指定するフォルダの中で未読になっているメールのIDの一覧を取得する方法をまとめます。

しかし、今回読み取りたいメールの一覧情報には多数のレコードが含まれていることが考えられます。

そのため、情報の取得はページ単位で読み取る必要があります。

この場合の全件読み取りの方法(イテレーション)も併せて紹介します。

各種バージョン

前回と同じですが、明記しておきます。

microsoft/microsoft-graph

2.1

vlucas/phpdotenv

5.6

前提条件

こちらも前回と同じです。

以下のコードを、GraphHelperクラスに追加するところまで行ってください。

    public static function getUserClient()
    {
        return self::$userClient;
    }

実際のコード

指定したフォルダ内の未読メールの一覧を取得する実際のコードです。

1ページで読み取れなかった場合は、イテレータという機能を利用し、全ての情報を読み込みます。

以下の「getUnreadMailIdsInFolder」関数が今回紹介したいコードになります。

<?php
// Enable loading of Composer dependencies
require_once realpath(__DIR__ . '/../composer/vendor/autoload.php');
require_once 'GraphHelper.php';

use Microsoft\Graph\Generated\Users\Item\MailFolders\Item\Messages\MessagesRequestBuilderGetRequestConfiguration;
use Microsoft\Graph\Generated\Models;
use Microsoft\Graph\Core\Tasks\PageIterator;

main();
exit(0);

function loadDotEnv()
{
    // Load .env file
    $dotenv = Dotenv\Dotenv::createImmutable(__DIR__);
    $dotenv->load();
    $dotenv->required(['CLIENT_ID', 'TENANT_ID', 'GRAPH_USER_SCOPES']);
}

function main()
{
    loadDotEnv();

    //初期化
    GraphHelper::initializeGraphForUserAuth();

    //現在受信トレイに入っている未読になっているメールのIDの一覧を取得
    $unread_mail_id_list = getUnreadMailIdsInFolder("inbox");
    var_dump($unread_mail_id_list);
}

//指定されたフォルダ内の未読になっているメールのID一覧を取得する
function getUnreadMailIdsInFolder(string $folder_id) : array
{
    /** @var MessagesRequestBuilderGetQueryParameters $query_parameters */
    $query_parameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();
    $query_parameters->select  = ['from','isRead','receivedDateTime','subject'];
    $query_parameters->orderby = ['receivedDateTime DESC'];
    $query_parameters->filter  = 'isRead eq false';
    $query_parameters->top     = 100;

    $configuration = new MessagesRequestBuilderGetRequestConfiguration();
    $configuration->queryParameters = $query_parameters;

    $mail_id_list = [];

    /** @var Models\MailFolderCollectionResponse $results */
    $results = GraphHelper::getUserClient()->me()->mailFolders()->byMailFolderId($folder_id)->messages()->get($configuration)->wait();

    //参考:https://learn.microsoft.com/ja-jp/graph/sdks/paging?tabs=PHP
    $pageIterator = new PageIterator($results, GraphHelper::getUserClient()->getRequestAdapter());
    
    $callback = function($message) use (&$mail_id_list) : bool 
    {
        /** @var Models\Message $message */
        $mail_id_list[] = $message->getId();
        return true;
    };
    
    $pageIterator->iterate($callback);

    return array_unique($mail_id_list);
}

処理に成功すると30行目の「var_dump($unread_mail_id_list);」によって、取得できたメールのIDを以下の様に標準出力に出力します。

array(1) {
  [0]=>
  string(152) "XX***(中略)***XXX="
}

ここの「XX***(中略)***XXX=」の部分がメールのIDです。

複数件のメールが読み取れれば、複数のメールIDが出力されます。

実際にこのメールのIDを使ってMicrosoft Graph Explorerで情報を見てみましょう。

クエリの入力ボックスに「https://graph.microsoft.com/v1.0/me/messages/XX(中略)XXX=」を入力し、「Run query」ボタンをクリックしてみましょう。

画面下部分の「Response preview」の部分に、メールIDで指定したメールの詳細情報が表示されると思います。

Query Parameterの作り方

今回のコードの37行目〜44行目までの部分で、メールを抽出する際の条件を指定しています。

ここの条件をカスタマイズする方法について説明します。

$query_parameters = MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();

37行目の部分です。

検索条件を作るためのクエリパラメータ作成用のクラスをインスタンスを作成しています。

このインスタンスを作成するクラスですが、検索する対象のデータごとに切り替える必要があります。

何を検索する際にどのクラスを利用する必要があるかどうかは、Microsoft Graph APIのリファレンスを参照します。

今回はメールのメッセージの一覧を抽出したいので、APIリファレンスの左メニューから一つずつ見て。メールについての情報を探します。

今回は「メッセージを一覧表示する」というピッタリそうな項目が見つかりました。

このページの説明を読みつつ、コードの例を参照すると、使うべきクラス、実装方法がわかります。

今回は「MessagesRequestBuilderGetRequestConfiguration::createQueryParameters();」を呼び出すことで生成されるインスタンスになりますね。

composer内のこのコードを調べてみると「MessagesRequestBuilderGetQueryParameters」クラスのインスタンスが返ってくる様です。

$query_parameters->select = [‘from’,’isRead’,’receivedDateTime’,’subject’];

38行目の部分です。

この部分は検索した結果読み取りたい情報を指定します。

今回は、読み取れた情報が正しいかどうか判断するために最低限の、条件を指定しています。

ここを指定しなくても問題なく動作しますが、取得可能な情報を全て返してしまう様です。

こうなってしまうと扱う情報が増えてネットワークに負荷をかけてしまうため、できるだけ最低限の情報を指定する方が良いでしょう。(Microsoftも推奨しています。)

selectについての細かい仕様はAPIの「クエリパラメータの使用、selectパラメーター」(英語版)を参照してください。

ここで読み取る対象として指定できる情報は今回はメールに関する情報なので、APIリファレンスの「メール、メッセージ、プロパティ」(英語版)を参照します。

このプロパティに記載されているものであれば指定できると思います。

各プロパティの詳細を確認しながら、目的別にどの値を取得するべきか判断しましょう。

$query_parameters->orderby = [‘receivedDateTime DESC’];

39行目の部分です。

この部分は、レコードが複数件取得できた際に返ってくる情報を、何を基準に並び替えるかどうかを指定します。

SQLを使ったことがある場合、この部分がどう動くかはなんとなく予想できますね。

ここも何も指定しなくても情報の取得は可能ですが、未指定の場合はどの様な並びで情報が返って来るかわかりません。

ある日突然、仕様変更が行われ、初期の並べ替え条件が変わることによって、アプリが予期せぬ動作をする可能性があるので、目的に合わせてきっちりと指定する様にしましょう。

orderbyの細かい仕様についてはAPIの「クエリパラメータの使用、orderbyパラメーター」(英語版)を参照してください。

$query_parameters->filter = ‘isRead eq false’;

40行目の部分です。

この部分は情報の検索条件を指定し、この条件にマッチしたレコードをMicrosoft Graph APIが返してくれます。

何も条件を指定しないと、大量のレコードを読み取ってしまう可能性があるため、目的に合わせて指定する様にしましょう。(私は恐ろしくて、実際にここを指定せずに実行したことはありません。)

ここでは左辺にプロパティ(isRead)、真ん中に比較演算子(eq)、右辺に値(false)を書いて1セットとしていますが、このような比較演算子はあまり見慣れないと思います。

よくある比較演算子は、イコール(=)やノットイコール(!=)、大なり小なり(<、>、<=、>=)などの記号です。

しかし、クエリパラメータという形式上、記号はパーセントエンコードなどをしなければならず、扱いづらいため、この様な表記をしているのだと思います。(ちなみにShellScriptの比較演算子に近いです。)

各種比較演算子の使い方など、フィルターについての詳細はAPIの「フィルター クエリ パラメーターを使用する」(英語版)を参照してください。

$query_parameters->top = 100;

41行目の部分です。

ここでは、一度のリクエストで読み取る件数を指定します。

記事の最初の方でページ単位で情報を読み取ると説明しましたが、その1ページごとに読み取れる件数を指定します。

topパラメータについての説明は、「クエリパラメータの使用、topパラメーター」(英語版)を参照してください。

また、ここで指定可能な行数はエンドポイント(呼び出し対象の機能)によって違いがあります。

今回はメールのメッセージ一覧なので、「メッセージを一覧表示する」(英語版)の下記画像の位置にtopに指定できる件数の範囲についての記載があります。

この記事を書いている時点では「1〜1000」までが指定可能で、何も指定しなければ10件が規定値のようです。

topパラメータのとセットで使えるskipパラメータというものもあります。

skipパラメータは指定した条件で取得可能な情報のうち、先頭から順に取得をスキップする件数を指定します。名前の通りですね。

topパラメータとskipパラメータをうまく使うと、複数ページにわたる情報を読み取ることが可能です。

イテレータによるページの切り替え

読み取る対象の情報がたくさんあり、情報が1ページで読み取れない場合は、topパラメータとskipパラメータを組み合わせて複数ページにわたる情報をページを切り替えながら処理する必要があります。

このページングの処理ですが、自分で実装することもできますが、イテレータを利用することにより、ページを意識せずに順番に情報を扱うことが可能です。

そのイテレータを使って読み取っているのが、ここでいうと61行目の「$pageIterator->iterate($callback);」の部分です。

イテレータの扱い方については「Microsoft Graph SDK を使用してコレクションをページ表示する」(英語版)を参照してください。

PHPでは、無名関数という機能とともに利用します。

iterate関数に与えた無名関数に対し、読み取ることができたレコードが一件ずつ渡されるので、それを順番に処理します。

ページングが発生すると、イテレータが勝手に次のページの情報を読み取ってくれて、最後のページの最後のレコードの読み取りが終わると処理が終了します。

今回の処理は、未読メールを一意に示すIDを配列に溜める処理になっています。

最後に

今回は、Microsoft Graph APIを使って情報を読み取る方法の紹介と、各情報について調べる際にどのページのどこを見ればいいかを備忘録的にまとめてみました。

Microsoft Graph APIをつかうと色々なことができる様になるのですが、そもそもAPIを使わなくてもアプリが充実しているおかげで大抵のことはできてしまうため、使い方の情報が少ないです。

今後、Microsoft Graph APIに入門する人の助けになれば幸いです。

参考URL

タイトルとURLをコピーしました