Gmailストレージ容量との戦い~GoogleAppsScriptを使った効果的な取捨選択~

開発グループPMO(プロジェクトマネジメントオフィス)の大嶋です。 実はウィルゲートのエンジニアでは最古参なことに最近気づきました。

そんなわけ(?)で、今回は組織の在籍期間が長くなってくると遭遇しがちな情報資産の氾濫という側面から「一足遅いですがこれを大掃除して新年を迎えよう!」というテーマでGmail資産の整理についてお伝えします。

GoogleAppsの容量が逼迫している

ウィルゲートでも、かねてより業務上のメールやファイル共有を中心にGoogleAppsを活用してきています。 近年ではSlackなどチャットサービスへの移行によりメールによるコミュニケーションは減ってきているものの、「フォーマルな連絡はメール」であったり「社内外のシステムからの通知はメール」といった形で、Gmailを使う機会はまだまだあるのではないでしょうか。

GoogleAppsは他のストレージサービスと比べても普通に使うには十分なストレージ容量がありますが、長く在籍しているとどうしても容量上限との戦いになってきます。 GoogleAppsは通常で30GB(無償版は15GB)の容量があり、追加で月額課金の形式で容量を増やすことはできるので短期的には「物理あるいは札束で殴る」的な解決をすることも可能です。

f:id:oshima106:20180907150822p:plain

ですが、仕事をやりくりできる人は得てして限られた時間の中で取捨選択してうまくやりくりしているのではないかと思います。 そこで限られた容量の中でGmailを効果的に運用する方法について考えてみます。

容量を逼迫させる原因

Gmail容量を逼迫させる原因であり、削除するべき対象は大きく分けて以下の2つと考えられます。

  1. 単独で大きなサイズを占めている
    • メールに添付ファイルや解像度の高い画像がついているようなもの
  2. 一つ一つは小さくても同様の内容が大量に存在している
    • メルマガやシステムアラート通知など

このあたりはデータや画像を圧縮して処理したり、N+1問題のような実装を避ける、といったシステム開発における 性能改善の考え方にも通じるものを感じます。

サイズの大きなものを特定

Gmailでは条件を指定したメールの検索ができるので、これを活用して特定していきます。

  • 『larger:3m』のようなサイズ指定で探す
    • この例では、主に添付ファイルを含む3MB以上のサイズのメールが抽出されます
    • 自身の業務に関連性が低いものを中心に削除していきます
  • 『filename:pptx』 のような拡張子で探す
    • 必要な添付ファイルは個別にローカルに保存するなどしてメールは削除してしまうのも一つの手です

これらを『before:2018/01/01』のような日付指定と組み合わせて抽出することで、過去のサイズの大きなファイルをまとめて削除する、といったこともできます。

f:id:oshima106:20190109174756p:plain

1つ1つが小さくても件数がかさんでいるものを特定

こちらが今回の本題です。 サイズや拡張子であたりを付けられる探し方に比べると、特定が難しいことがあります。

主なあたりの付け方としては、メールタイトル、送信元、送信先メーリングリスト)で検索して大量に来ていないかを調べることになります。 あたりをつけるのが難しい場合は、直近何日かの期間に来ているメールを対象に絞って傾向を調べてみましょう。

とはいえざっと見ても数100通くらいはあって目視ではシンドいのと、この先毎回同じことをするのも避けたいので、GoogleAppsScript のコードを実行することで集計してみました。 この例では、ここ5日以内に送信されたメールを対象に送信元アドレスごとの件数をカウントしています。

/**
 * 所定の条件でメールを検索して送信元ごとの件数を集計する
 */
function processMailFromCount() {
  // メールの検索条件を設定(5日前より新しいメール)
  var SEARCH_CONDITION =  "newer_than:5d";

  // Gmailを指定条件で検索する
  var resultThreads = GmailApp.search(SEARCH_CONDITION);

  var resultCounts = {};  // 送信元アドレスごとのカウント用配列
  var messagesInThread  = {};  // スレッド内のメッセージ取得用配列
  var mailFrom = "";  // 送信元メールアドレス
  
  // 見つかった件数を記録
  Logger.log('検索条件:' + SEARCH_CONDITION);
  Logger.log('対象スレッド件数:' + resultThreads.length);
  Logger.log('========集計開始========');
  
  // 検索結果で取得したスレッドを順に処理し、送信元アドレスごとの件数を集計
  for each(var thread in resultThreads){
    messagesInThread = thread.getMessages();
    // スレッド内のメッセージを順に見て送信元アドレスを取得
    for each(var message in messagesInThread){
      mailFrom = message.getFrom();
      var mailAddress = mailFrom.match(/<.*@.*>/); // 送信者名 <hogehoge@gmail.com> 形式のメールアドレス部分を抽出
      if (mailAddress != null){
        mailFrom = mailAddress[0].substring(1,mailAddress[0].length - 1); // 角括弧を除いて整形
      }
     // 送信元アドレスごとの件数をカウントアップ
      if (mailFrom in resultCounts) {
          resultCounts[mailFrom] += 1;
      } else {
        resultCounts[mailFrom] = 1;
      }
    }
  }
  
  // 件数を降順にソートする
  var keys=[];
  for(var key in resultCounts){
    keys.push(key);
  }
  keys.sort(function(a,b){
    return resultCounts[b]-resultCounts[a];
  });
  
  // ログに送信元:件数 のフォーマットで書き出す
  for (key in keys){
    Logger.log(keys[key] + ': ' + resultCounts[keys[key]]);
  }

  Logger.log('========集計終了========');
};

結果どのくらい減らせたのか

直近5日(GoogleAppsScriptの仕様で一度に最大500件)を対象にメールの送信元を集計すると、自社メディアサービス「Milly」のシステムから送信されているものをはじめ、システムから通知されているものが大多数を占めていることが判明。

f:id:oshima106:20190109182339p:plain

実際に来ていた内容は外部API連携処理のエラー通知や、広告運用状況の通知など。特定の画面にアクセスする際に出力されるランタイムエラー情報のアラート通知など直接的な悪影響がないため対策が後回しになっているものでした。 StackTraceログがメールに貼り付けられているものもあるため、メール1通あたりのサイズもそこそこ大きくなっていました。

これらを順に削除していくことで、1.5GBくらいの容量を空けることができました。大掃除というにはちょっと物足りないですが、当面半年くらいはやりくりできそうです。

f:id:oshima106:20190109190057p:plain

おわりに

今回は日常業務にちょっとしたエンジニアリングを活用した事例のご紹介でした。 今後もウィルゲートではこういったライトなものから、現場のコアな技術のことまで引き続きお伝えできればと思います。