LoginSignup
25
20

More than 5 years have passed since last update.

社内で作成されまくったメーリングリストをGASで整理する(情シス向け)

Last updated at Posted at 2016-12-22

はじめに

多くの情報システム管理者が頭を抱える事の1つにメーリングリスト(以下ML)の管理があります。

うちの会社ではG Suite(法人向けGoogleApps)を利用しているのですが、長年問題を抱えていたMLの管理について、少しのルールと簡単なGASのコードで大分マシになりましたので、共有させていただきます。

会社のメーリングリスト多すぎ問題

会社にはおびただしい数のMLが存在します。初めてに数えたときは2000個近くありました。
働いているメンバーは自分がどれだけのMLに参加しているかなんて普通は考えません。

しかし、誰かがその管理を行う必要があり、整理されているべきです。
日々、整理を行うにあたって、下記の項目が整理されていないと一気に管理が面倒になります。

  • 何を目的に作成されたのか?(何のPJなのか?)
  • 管理者は誰なのか?
  • メンバーは誰なのか?
  • 現在使われてるのか?

幸い、GSuiteはMLとして使用するグループには名前やメモを入れる事ができるので、目的や担当者を登録できます。
せっかくの年末の棚卸し期なので、一覧化して必要でないものはガンガン削っていきましょう。

スプレッドシートの用意

MLのメアド、MLの説明、ML名、メンバー数、メンバーのメアドを一覧化したいと思います。
スプレッドシートのスクリプトエディタからGASのコードを入力していきます。

トークンとトリガー

このコードでキモとなるのが、トークンとトリガーの関係です。
2000件近くのML、1件につき、5人のメンバーが登録されていた場合、10000件近く処理することになります(実際はもっと多いですが)。
GASの仕様で、処理が6分を超えるとタイムアウトエラーが起こります。
なので、処理ごとにプロセストークンを発行し、4分を超えた場合に現在のプロセスを再開するトリガーを発行する必要があります。

コードに関する注意点

情シス向けに作成しております。管理者権限が無いと動作しない部分があります。

/**
 * 全MLとユーザ一覧を取得
 */
function getGroupAddressAndUsers()
{
  // アクティブなシートを設定
  var ss = SpreadsheetApp.openById("ここにシートのIDを入力");
  var sheet = ss.getSheets()[0];
  var pageToken, prev_pageToken;
  //スクリプト情報を取得
  var Properties = PropertiesService.getScriptProperties();
  //現在のページトークンを取得。無かったら初期化
  var pageToken = Properties.getProperty("task_page");
  if(pageToken == 'undefined') {
    pageToken = null;
  }

  var rows = [];  
  var starttime = new Date(); //時刻格納用の変数
  //タイトルを設定
  sheet.getRange(1, 1, 1, 5).setValues([["メールアドレス", "説明", "名前", "メンバー数", "メンバーのアドレス"]]);

  do {
    //現在時刻と開始時刻の差分を取得
    var nowtime = new Date();
    var nowdiff = parseInt((nowtime.getTime()-starttime.getTime())/60000);

    // ”Admin Directory API”からグループ一覧を取得
    all_groups_page = AdminDirectory.Groups.list({
      domain: 'gaiax.com', //使用しているドメイン
      maxResults: 20,      //取得する件数
      pageToken: pageToken //トークン
    });
    var groups = all_groups_page.groups;

    //取得するグループが無い場合は終了
    if (!groups) {
      return;
    }

    // グループに所属するメンバーの取得し、配列に保存
    groups.forEach(function(group, i) {
      var members = AdminDirectory.Members.list(group.email).members;
      rows = addMemberRow(rows, group, members);
    })

    //現在時刻と開始時刻を比較して、差分が4分を超えていたら処理中断
    //(5分を超える処理はタイムアウトエラーになるため)
    if(nowdiff >= 4){

      // 配列の内容をシートへ書き込み
      sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, 5).setValues(rows);
      rows = [];

      //次の処理のトリガーを設置、プロパティに現在のトークンを登録しプログラムを停止
      Properties.setProperty("task_page",pageToken);
      setTrigger();

      return;
    }

    //新しいトークンを取得
    prev_pageToken = pageToken;
    pageToken = all_groups_page.nextPageToken;            
  } while (pageToken);  

  //トークンに変化がない場合、完了
  if(prev_pageToken == pageToken) {    
    //プロジェクトトリガーを全削除
    deleteTrigger();
    //トリガー用変数の初期化
    Properties.setProperty("task_page",'');

    // シートに書き込み
    sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, 5).setValues(rows);

  //5分を超えずに終わった場合
  } else {
    // シートに書き込み
    sheet.getRange(sheet.getLastRow() + 1, 1, rows.length, 5).setValues(rows);
    rows = [];

    //次の処理のトリガーを設置,プロパティにトークンを登録しプログラムを停止
    Properties.setProperty("task_page",pageToken);
    setTrigger();
  }
  return;
}

//メンバーの配列データを返す
function addMemberRow(rows, group, members) {
  // グループに所属するメンバーの取得

  var nowtime = new Date();//////////////////////

  //メンバーが居なかった場合
  if(members == undefined || members == 0){
    var cols = [];
    cols.push(group.email);
    cols.push(group.description);
    cols.push(group.name);
    cols.push(group.directMembersCount);
    cols.push("-----");
    cols.push(nowtime.toLocaleString());

    rows.push(cols);
  //メンバーが居た場合
  } else {
    for (var j = 0; j < members.length; j++){
      var cols = [];      
      cols.push(group.email);
      cols.push(group.description);
      cols.push(group.name);
      cols.push(group.directMembersCount);
      cols.push(members[j].email);
      rows.push(cols);
      cols.push(nowtime.toLocaleString());

    }
  }
  return rows;
}

//トリガーを全削除する関数
function deleteTrigger() {
  var allTriggers = ScriptApp.getProjectTriggers();
  for(var i=0; i < allTriggers.length; i++) {
      ScriptApp.deleteTrigger(allTriggers[i]);
  }
}

//トリガーを設置する関数(getGroupAddressAndUsers 関数を実行予定として登録)
function setTrigger(){
   deleteTrigger();
   var triggerman = ScriptApp.newTrigger("getGroupAddressAndUsers")
                   .timeBased()
                   .everyMinutes(5)
                   .create();
}

//トリガーをリセット
function resetTrigger() {
  var Properties = PropertiesService.getScriptProperties();

  //プロジェクトトリガーを全削除
  deleteTrigger();
  //トリガー用変数の初期化
  Properties.setProperty("task_page",'');
}

25
20
3

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
25
20