GoogleAppsScriptで全ユーザーを取得・改

佐野

佐野 2014年11月17日

ついにGoogleAppsScriptの
「UserManager.getAllUsers()」関数が使えなくなり、
Admin Directory APIを
使用せざるを得なくなってきたかと思います。

従来までとはやや異なり、
Googleデベロッパーコンソールでも
「Admin SDK」をONにしておく必要があるほか、
取得する値が「object」ではなく連想配列であったりと、
かなり概念が変わってきます。

今回やりたいと思ったのは、全ユーザー情報の取得です。
こちらのURLにも、そのサンプルがあり、「listAllUsers()」関数が、
氏名の名を基準に全ユーザーのリスト表示を行うというものです。
https://developers.google.com/apps-script/advanced/admin-sdk-directory

が、じつはこれで全てのユーザーが取得できるわけではありません。

「AdminDirectory.Users.list()」関数によりユーザー情報を取得するのですが、
引数が必須であり、引数には取得するユーザーの条件を連想配列で指定します。
サンプルの場合、「maxResults」が100に指定してあるため、
100ユーザーまでとなっています。
「maxResults」のプロパティなしの場合、デフォルトで100を指定されますが、
このプロパティで指定できる数値は、1から500までです。
つまり、最大で500ユーザーまでしか取得できません

もし、500を超えるお客様のドメインでの開発となった場合、どうするのか?
色々悩んだ末、ひとつの結論に辿り着きました。
それは、メールアドレスで頭文字検索を行い、数を限定するという方法です。

「a」から順番に、頭文字で限定取得すれば、1回に取得する回数を減らす事ができ、
「maxResults」の最大値を超える事は、まずないはずです。
頭文字が同じメールアドレスが500もあるという事は、まずないですよね。

その検索方法を探すのに、苦労しました。
https://developers.google.com/admin-sdk/directory/v1/reference/users/list?hl=ja
こちらに「AdminDirectory.Users.list()」関数によるリファレンスがあり、
下段の方に「Try it!」のコーナーがあり、
ここで引数に入れるべき連想配列の値のテストも行えます。

テストを行うには、右側の「Authorize requests using OAuth 2.0:」
のスイッチをONにします。

oauth20-on
ポップアップでAPIの種類や認証を問われますが、そのまま進んでも大丈夫です。

そこからさらに下にある、各ボックスに条件を指定していくのですが、
どの値を入れるのかが、わかりにくいのが少々厄介ですが、
各テキストの後に入力すべき値の型が記載されているので、
それをヒントにするのもいいでしょう。と言っても、ほとんど(String)ですが・・・

必要な項目を言えば、まずは「domain」の値。
ここには、メールアドレスのドメインを入力します。
複数ドメインを所有する組織であれば、そのドメインごとに変更する必要があります。
ドメインを入力して、下にある青い「Excute」ボタンをクリックすると、
「Response」項目に、大量の情報が表示されるはずです。
「Request」部分には、PHP等で使用するためのURLが記載されています。

これだけでも、色々な情報が出力されて、おいしい状況なのですが、
もう少し限定してみたいという場合、
たとえば今回でしたら必要な情報はメールアドレスなので、
「fields」に、「users/emails」を入力します。
他にも色々な限定出力可能な情報があるので、
入力項目のすぐ右側にある「Use fields editor」をクリックすると、
どの項目に限定して出力させるかを、チェックボックスで選択でき、
また複数項目の選択も可能です。

この状態で出力すると、各アカウントのメールアドレスと、
そのメールアドレスがprimary(一意)であるかどうかが出力されるはずです。

このテストは、「list()」に、どのような連想配列を入れればよいかのテストですが、
ここで入力して成功したものを、値として使えば可能となります。

結果的に作成したスクリプトが、以下のとおりです。

//頭文字検索に使用する文字列 「charAt()」関数で1文字ずつ呼び出す
var searchStrs = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890";

//この配列に、メールアドレスを格納する
var allUserMails = new Array();

// 複数ドメインを考慮する
var domains = ["domain1.com","domain2.com"];

for(var i = 0;i < domains.length;i ++){
	for(var j = 0;j < searchStrs.length;j ++){
		
		//呼び出すユーザーの条件を指定する
		var optionalArgs = {
			domain:domains[i],		 //ドメインを入力
			maxResults:500,				//デフォルトでは100件までなので、500(最大数)を指定
			query:"email:"+ searchStrs.charAt(j) +"*",//メールアドレスの頭文字で検索を行う
			fields:"users/emails"	//メールアドレスの情報のみを限定して取得
		};
		
		//ユーザー情報の呼び出し
		var userDatas = AdminDirectory.Users.list(optionalArgs);
		if(userDatas.users){
			//呼び出されたユーザーの回数分ループする
			for(var k = 0;k < userDatas.users.length;k ++){
				//呼び出したメールアドレスには別名も含まれているため、その回数分をループ
				for(var l = 0;l < userDatas.users[k].emails.length;l ++){
					//メールアドレスのうち、primary(一意である)かどうかをチェック
					//念のために、既に取得してあるものは重複しないように対象外にする
					if(userDatas.users[k].emails[l].primary == true &&
						 allUserMails.indexOf(userDatas.users[k].emails[l].address) == -1){
						allUserMails.push(userDatas.users[k].emails[l].address);
					}
				}
			}
		}
	}
}

ループをやや重ねすぎかもしれませんが、
これで900件近くのアカウント情報を1分弱で出力してくれます。

ひとまずは「allUserMails」配列に全ユーザーのメールアドレスを格納しておき、
さらにスプレッドシートで保存したうえで、
別プログラムで動かすなりしていくとよいでしょう。
ここで一呼吸置いておかないと、また同じ処理を繰り返したり、
スクリプトの最大連続起動時間の5分を超えてしまう可能性も考えられます。

後はメールアドレスを基にユーザーを取得し、設定などを行うだけです。
その話はまた、別の機会といたしましょう。