Microsoft365のメール数やファイルサイズをPowerShellで取得する

Microsoft365からGoogle Workspaceに移行するといっても、Exchange OnlineやSharepointのそれぞれのオブジェクト数を割り出さないと移行スケジュールが建てられません。

そこで、この「オブジェクト数」を調査する為に、PowerShellの追加モジュールである「Graph Powershell SDK」を使って、Exchange OnlineやSharepointのオブジェクト数を割り出してみようと思います。

Google Workspaceを新規に導入する時に押さえたいポイント

今回利用するツール等

PowerShellは現在のWindowsには標準でインストール済みではあるのですが、実はバージョンが低いものが入っており、起動する度に最新版を入れろとメッセージが出てくるので、まずはPowerShellの最新版からのインストールより説明します。

また、Graphと名前がついていますが、Graph APIでは全領域をカバーできておらず、PowerShellはAzureの細部にまで手が伸ばせるため、こういった作業の時には必須のツールとなっています。

このオブジェクト取得によってGoogle Workspaceへ移行したい場合にはどれくらいの日数で移行できるのか?といった算出の為の元データとなるため、事前準備の段階から取得しておき、GWM実施直前でも取得してどれくらい増量したのか?といった調査に使えます。

※ちなみにmacOSでもインストールすることが可能です。

Google Workspace MigrateでMicrosoft365からお引越し - 事前準備編

図:macOSでも動かしてみた

調査の為の事前準備

PowerShell最新版のインストール

Windowsの場合

まずはインストール済みのPowershellではなく最新版のPowerShellをインストールします。

  1. こちらのサイトを開く
  2. MSIパッケージとなるので、ここからx64版もしくはarm64版、環境に合わせてダウンロードする
  3. ダウンロードしたインストーラを起動する
  4. 色々オプションが出てきますが基本デフォルトのまま次へ進んでインストールを完了する
  5. スタートメニューをクリックし、検索でPowerShellと入れるとPowershell7というのが出てきます。古いバージョンも共存してるので注意。
  6. これをタスクバーにピン留めすると良いでしょう。

図:インストーラを起動する

図:PowerSehll7が本体です

macOSの場合

macOSの場合もGithubにpkgファイルがリリースされているので同様にインストールは可能です。但し、macOSの場合はターミナル上で動くコマンドであるため、独立したアプリという形ではありません。

また、Homebrew経由でインストールも可能です。その場合、以下のコマンドでインストールが可能です。

インストールができたらターミナル上で「pwsh」コマンドを打てばPowerShellになります。あとはps1ファイルをそのまま実行したり、PowerShellコマンドをそのまま実行することが可能です。

図:ターミナルがPowerShellになる

Graph PowerShell SDKのインストール

続けて、PowerShell7を管理者権限で起動して以下のコマンドを実行します。

動き始めるまでちょっと時間が掛かるので辛抱して待ちます。すると色々とインストールが始まります。インストール後は、以下のコマンドでインストール済みかどうか確認出来ます。

図:モジュールのインストール

アカウント接続

次の作業として同じくPowerShell7にて、Microsoft365と接続します。以下のコマンドを実行します。

するとブラウザが起動して、ログインを促してくるので特権管理者アカウントでログインします。「Authentication complete. You can return to the application. Feel free to close this browser tab.」と出たらブラウザは閉じてオッケー。

PowerShell側は「Welcome to Microsoft Graph!」と出たら接続完了。実際にはここにMicrosoft365の各種スコープを付けて許可をしてあげる必要があるので、後述のPowerShellコマンドではそれらを付与して実行しています。

図:実行時の初回認証

PowerShellで調査する

VSCodeで開発する

今回のPowerShellスクリプトの開発は、MicrosoftのVisual Studio Code上で行っています。もはや開発者であれば知らない人はいないであろう、テキストエディタであり実行環境です。

そこに拡張機能としてこれもMicrosoft謹製のPowerShell for Visual Studio Codeをインストールして作成をすると良いでしょう。

図:拡張機能をインストールする

図:ps1ファイルを編集中の様子

Exchange Online

単一のアカウントの情報を取得する

単純に特定の単一アカウントにおけるOutlook上のフォルダ別のメールの数およびサイズを計測するコードを作成してみます。特定のフォルダのIDを取得しそのサブフォルダ内まで含めて探索して、カウントします。

以下はアーカイブフォルダおよびそのサブフォルダ内を探索します。これは以下のメソッドを利用しています。

もし、対象ユーザの全フォルダの全件数とサイズの合計を出したい場合には、$rootFolderIdの指定方法を以下のように変更しフォルダを大元のルートフォルダに指定します。受信トレイの親フォルダのIDつまり大元のルートフォルダを指定し、そこを基準に処理をします。

但しこれでは調査するだけでなおかつ単一ユーザの情報を知ることが出来るだけなので、実際には全ユーザの情報をまとめてCSV出力するなどしなければ実際の現場では活用しにくいです。

rootFolderIdでは-Filterというオプションを付けてdisplayNameが受信トレイとeq(イコール)のものという条件をつけていますが、ここを日付を指定し「特定の日以前 or 以降の受信日のメール」みたいな指定方法が可能です。Redditでこのあたりが詳しく紹介されています。

上記の例では、ReceivedDateTime ge $timeとあり、受信日が$timeの日付より以降(ge)が指定されています。こうすることで指定期間内のメールの件数やサイズに限定することが可能です。geではなくleとすれば以下となるので日付的には指定日より前という表現になります。フィルタについてはこちらに公式ドキュメントがあります。

※但し、この手法は所謂オンライン・アーカイブと呼ばれる受信トレイ内とは別にあるアーカイブフォルダ内のデータは取得できません。

図:メールの件数とサイズを算出できました

まとめて取得しCSVでエクスポートする

mailという名前の列にメアドを縦に列挙しただけのinbox.csvというCSVファイルを用意します。ここに全ユーザを列挙しておきます。今回のコードは共有メールボックスについてはエラーとなり動作しません。

基本的なコードは前述と同じですが、reportというカスタムオブジェクトを用意し、値をどんどん格納していきます。メールアカウントは今回はもう簡単に「Get-MgUserMessageCount -UserId $userId」でざっくり取得します。ファイルサイズだけ関数を使ってサブフォルダ以下まで探索して取得します。

最終的にresult.csvとして出力して完了というコードになります。ちなみに、$PSScriptRootはps1スクリプトの実行されているカレントディレクトリのパスを取得するもので、inbox.csvはこのスクリプトと同じ場所に保存する必要があり、またresult.csvも同じ場所に出力されることになります。

※但し、この手法は所謂オンライン・アーカイブと呼ばれる受信トレイ内とは別にあるアーカイブフォルダ内のデータは取得できません。

図:出力された結果のCSV

オンライン・アーカイブを取得する

前述までの状態は通常のOutlookの個人のデータを取得する場合のPowerShellスクリプトになります。しかし企業の場合はIn-Place Archiveと呼ばれるオンライン・アーカイブと呼ばれるものを用意してる場合があります。デフォルトでは無効なのですが、有効化してる場合、ここにアーカイブしたデータは前述のコードでは取得できません。そこでこのデータを取得してみたいと思います。

オンライン・アーカイブを有効化する

オンライン・アーカイブはExchange管理センターから個別にユーザに対して有効化する必要があります。以下の手順で有効化すると特別なアーカイブスペースが用意されて、Business Basicだと50GBまで用意されます。

  1. Exchange管理センターを開く
  2. 左サイドバーから受信者→メールボックスを開く
  3. 対象のユーザをクリックする
  4. 右サイドバーが出てくるので、その他タブを開く
  5. メールボックスアーカイブの管理をクリックする
  6. メールボックスアーカイブのステータスを有効にチェックする
  7. 名前はこのアーカイブスペースの名前を入れます(例:Archivemanなど)
  8. 保存をクリックする

これで暫くすると、Web版およびローカル版のOutlookに7.の名前でもってオンライン・アーカイブスペースが表示されます。

図:管理センターから有効化可能

In-Place Archiveが表示されない

有効化して暫くしたら表示されるハズなのに表示されないケースがあります。その場合、PowerShellで以下のコマンドを実行して対象ユーザの更新を行い、ユーザは一度ログアウトしてログインし直すと表示されるようになります。

但し、Get-Mailboxメソッドを使うので、事前にモジュールをインストールが必要です。

これで特権管理者アカウントでログインをすると、メソッドが使えるようになります。

その後以下のようなPS1ファイルを作成してPowerShellで実行してみます。-ArchiveNameで指定する名前はコードではIn-Place Archive ユーザ名となっていますが、ここは前述の7.の項目のアーカイブの名前に該当する部分です。

図:アーカイブスペースが表示されました。

データを取得する

このIn-Place Archive内のデータを取得するのはちょっとだけ大変です。メールの件数とフォルダサイズを取得するわけなのですが、まずは以下のコマンドで調べてみます。こちらも前述のGet-Mailbox同様にExchangeOnlineManagementモジュールのインストールと、Connect-ExchangeOnlineでの接続が必要です。

すると、以下のスクショのような結果が得られました。onlineは自分が作ったArchive用メール格納フォルダ。削除済みアイテムやらDeletetionsやらは自動で生成されてるものですが、これらは今回の対象からは除外したいです。よって、それらを考慮してメールの件数とファイルサイズを取得する必要があります。

図:余計なフォルダも出てくる

実際にオンラインアーカイブ内のメールの件数およびファイルサイズの合計値を出すスクリプトは以下のようになります。但し、注意点がいくつかあって

  • アーカイブ内の余計なフォルダは除外したいのでexcludeFoldersでリストを作っておく
  • Get-MailboxFolderStatisticsにてArchiveオプションにて情報を取得できます。
  • 但し返ってくる値が 100kb( 100000 bytes)みたいな文字列で返ってくるので正規表現等で文字だけ取り出す
  • 同様にアーカイブ内のフォルダのリストを取得して、今度はメールの件数を合計していく
  • where-objectでは、-andを構文内で使うことで複数の条件を指定可能です。

といったちょっとトリッキーな流れになっています。この流れを関数化しておき、前述でも使ったreportのオブジェクトに結果として含めてCSV出力すると良いでしょう。ただ、ReceivedDateTimeを指定して期間指定してフィルタできるかどうかは不明です(調べた限りではできない。

図:サイズと件数合計を取得できた

共有メールボックスを取得する

Microsoft365のExchange OnlineはGoogle Workspaceと違い、共有メールボックスという指定のメンバー内で共同利用する特殊なメールボックスがあります。GWS的には共同トレイに該当するもので、特定個人に紐つかない独立したメールボックスです。Exchange管理センターから作成することができます。

この共有メールボックスに来てるメールのアイテム数とファイルサイズを調査したいと思い調べてみると、また違うメソッドを使う必要があるようです。それを元に構築したコードが以下のとおりです。結果は共有メールボックスのアドレス毎にアイテム数とファイルサイズを列挙し、CSVで出力するものになっています。

  • sharedMailboxesの変数に調査する共有メールボックスのアドレスを列挙する
  • 共有メールボックスの調査はGet-EXOMailboxStatisticsを利用して調べることが可能です。
  • 調べた結果は割と素直に、ItemCountとTotalItemSizeの値を整えて取得が可能です。
  • 最後にレポート用オブジェクトに格納し、Export-CsvにてPS1ファイルと同じ場所にCSV出力しています。

図:共有メールボックスも出力できました

カレンダーを取得する

単一ユーザのイベント数を取得する

Microsoft365のオブジェクト調査対象はメールだけじゃありません。カレンダーもそういったものの1つです。しかし、カレンダーはユーザに1個だけ用意されてるわけじゃなく、予定表を追加にて自分の個人用の予定表に何個も追加して使い分けしてるのが定石です。これらのカレンダーのイベント数(オブジェクト数)も調査したい所です。

主に利用するメソッドは以下のとおりです。

カレンダー一覧を取得して回し、各カレンダーのイベント数を取得します。一度に100件取得して、ページネーションで分かれるのでその部分で再帰処理を掛けて全オブジェクト数を取得します。

図:個人の予定表のデータ全部を対象にする

図:カレンダーのオブジェクト数を取得してみた

全ユーザのイベント数とファイルサイズを取得

前述は単一ユーザのイベント数のみを取得していました。実際の現場では前述にもありましたがユーザリスト(inbox.csv)があって、それら全ユーザ分を取得しつつ、またイベントに付属の添付ファイルのファイルサイズも計測する必要があります(無い場合もある)。

よってこれらを踏まえて、ユーザリストを回しつつイベント数と添付ファイルがあればそのファイルサイズを取得、一覧表にまとめてCSVで出力というものを作成しました。

図:添付ファイルのサイズ等も含めて計測

図:出力されたCSVファイル

パブリックフォルダを取得する

パブリックフォルダ内のコンテンツはメールやカレンダー、ファイル類と広くいろいろなものがごっちゃになってるかと思います。これらのオブジェクト数を割り出すGet-PublicFolderStatisticsというメソッドがあります。現在研究中。

パブリックフォルダが表示されない

Outlookには特殊な機能として「パブリックフォルダ」というものがあります。これはExchange管理センターから作成できますが、これがユーザに表示されないことがあります。その覚書です。この原因は

  • Exchange管理センターでパブリックフォルダが作成されてるが、アクセス許可を対象ユーザに与えていない
  • ユーザにアクセス許可が与えられてるが、ユーザがOutlook上で自身で追加していない(勝手に表示されるわけじゃないため)

の2点になります。障害としてアクセス許可を削除して再度追加したら出てきたみたいなケースもあります。このパブリックフォルダ内のカレンダーやメール、カレンダー類は特殊な個別のメアドが与えられてるものになるので、共有メールボックスや自身のメアドとはまた違うものになるので要注意です。

図:アクセス許可を追加する

図:Outlook上で追加する

図:表示されるようになりました

スクリプトで取得する

Exchange管理センターで用意してるパブリックフォルダはルートとその下にぶら下がるサブフォルダで構成されています。各フォルダ名、アイテム数合計、ファイルサイズ合計を出すPowerShellのコマンドを作ってみました。ただ、サブフォルダ以下にさらにサブフォルダがある場合を考慮していないので、もしそうした構成の場合は再帰的に処理して孫フォルダ以下もすべて浚うように作り変える必要があります。

Sharepoint Online

管理センターから取得する

Exchange Onlineは前述の通り様々な取得対象が存在しており、しかも簡単に取得ができませんでした。しかし、Sharepointの場合にはサイト毎のファイル数やファイルサイズは割と簡単に取得することが可能です。この手法はPowerShellを使わずに手に入れる方法です。

  1. こちらのリンクから自身のテナントのSharepoint管理センターを開く(テナント毎にURLが違うので要注意)
  2. するとアクティブなサイトというページが出てくる
  3. エクスポートをクリックする
  4. CSVでダウンロードされる

CSVの中身を開いてみると、サイト名の他にファイルがファイル数(つまりオブジェクト数)、使用済みストレージ (GB)がファイルサイズ合計となります。Teamsで使われてるかどうか?のフラグなどもあり、これで必要十分と言えば十分です。

図:CSVで簡単に手に入る

スクリプトで取得する

概要

Sharepoint管理センターを使わずにPowerShellにて取得する場合には、Exchange Onlineのように追加のモジュールをインストールしてからスクリプトを実行する必要がありますが、ここハマりポイントが2つありました。

  • SharePoint Online 管理シェルが必要でmacOSではインストールまではできますが、Connect-SPOServiceが動作しませんので接続ができません。
  • Windows11のPowerShell7で上記をインストールしたものの、やはり接続ができない。どうもPowerShell5系でないと動作しないようだ。
  • 公式ではないPnP PowerShellというモジュールもあるようで、こちらはmacOSからも使えるようだ。但しAzureにアプリ登録のコマンドはWindowsのPowerShellからじゃないとできないという罠。
  • そして対応を進めてわかったのが、「SharePoint Online 管理シェル」では標準でファイル数やファイルサイズを取得できないことが判明。故にPnP PowerShellを使うのが正解のようだ。

ということなので、公式ドキュメントにあるまま接続しようとするとエラーに遭遇して先に進めません。

追加モジュールのインストールと接続

ということでSharePoint Online Management Shellではなく、PnP PowerShellを使って取得をしてみることにします。その為には追加でモジュールのインストールが必要です。管理者権限のPowerShellで実行します。

インストールが完了したら、Azure Portalにアプリの登録をするのですが専用のコマンドが用意されています。

yourtenantの部分はメアドの@より後ろの部分がそれに該当。これを実行するとログインと承認が求められるので許可するとアプリがAzure Portalに自動的に登録されます。上記コマンドだとすべてのアプリケーション欄にPnPApp001という名前で登録されます。開いてみて、アプリケーション(クライアント)IDの値が必要なので控えておく。

アプリのアクセス許可も自動的にすべて追加されています。

図:Azureにアプリ登録中

図:クライアントID等が必要

全サイトの情報を取得する

Azure Portalまで使ってClient IDを手に入れてようやくと思いきや、このコードが結構複雑。Sharepoint管理センターのような一覧がパッと取れるわけじゃないという。

  • サイトのドキュメント内のものだけを対象に検索します。
  • 直下→サブフォルダ内まで再帰的に処理してファイル件数とサイズを取得していかなければならない。
  • 量が多いと429エラーが起きる可能性がある(回避策はこちらのサイト
  • 再帰処理をさせる為に関数に切り出しておく箇所がある
  • サイトのURL毎にConnect-PnPOnlineで接続しなおさないときちんとデータが取れません。
  • /sites/以外のURLも含まれてくるのでこれらは処理対象外として除外する

かなり苦労して、結局はSharepoint管理センターのCSV一発で取れるものと殆ど同じなので、ちょっと使い勝手が悪いなぁと思う。別の使い方(フォルダの階層構造をしらべる等)では応用して使えるかもといったところです。

OneDrive Business

Microsoft365のOneDriveはURLを見るとわかるのですが、SharepointとしてのURLが表示されています。つまり仕組みはSharepointと同じで個人向けのサイトとして用意してるものと言えます。

Sharepointと似たようなものであるため、前述のSharepointのデータ取得法で出来ないか?現在研究中です。

管理センターから取得する

Sharepointの場合同様にOneDriveについても管理センターからユーザ別のファイル数とファイルサイズの合計がCSVで簡単に入手することが可能です。但しSharepoint管理センターではなくMicrosoft365管理センターからの入手になります。

  1. ここのリンクからMicrosoft365管理センターに入る
  2. 左サイドバー一番下の「すべてを表示」をクリックする
  3. 左サイドバーのレポート→利用状況をクリックする
  4. 新たな画面で左サイドにOneDriveがいるのでクリックする
  5. 利用状況タブが開かれていますが、右パネルの下に一覧が表示されています。但しユーザはメアドや名前じゃなく数値文字のIDのようなものとして表記されています。
  6. 一覧表を右スクロールしていくと、列の選択というのが出てくるのでクリックする
  7. 未チェックのものがあるので全部チェックを入れて保存をクリック
  8. ファイルやサイズなども表示されていたら、上部にある「エクスポート」をクリックする
  9. CSVがダウンロードされる

CSVの中の「File Count」がファイル数、Storage Used (Byte)が「ファイルサイズ(bytes)」となります。

図:利用状況レポートから出力する

図:CSVを覗いてみる

スクリプトで取得する

基本的にはSharepoint Onlineの時と同様ですが多少異なる点もあります。

  • クライアントIDが必要な点はSharepointと同様です
  • PnP PowerShellを使って取得する点も同様です。
  • yourtenantの部分についても同様です。書き換えが必要です。
  • 初回の接続時およびここのユーザの情報を取得時の2回、認証が必要になるため注意が必要です。
  • ファイル数のカウントの為にGet-FileCount関数を作成し再帰的に処理をしています。
  • 最後にCSV出力をして完成です

図:無事に全ユーザのOneDriveの情報を取得できた

連リンク

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)