2014年11月7日金曜日

Google Apps Scriptを使ってGmailのラベルを一括でつけてみる

~はじめに~
 こんにちは、井下です。

 前回はGoogle Apps Scriptの検証を行いましたが、今回はWebアプリケーションを題材にします。

~テーマ~
 タイトルにもありますが、Google Apps Scriptを使ってGmailのラベルを一括でつけてみます。

 やりたいこととしてはフィルタ機能でもできるのですが、
 今のところフィルタ機能の操作はGoogle Apps Scriptに用意されていません。
 そのため、フィルタを作成・編集自体は自動化できなくなっています。
 
 システムとして提供した機能の中で、自動でラベルをつけていきたい場合や、
 フィルタで提供されている以外の設定をしたい場合、
 GmailAppを使って実装することになります。



~実装イメージ~
 今回の実装イメージとしては

 ①画面からラベル名とラベル付けの条件(From、To、件名)を入力してクリックする
 ②自分のアカウントのGmailに新しいラベルが追加されている+ラベル付けもされている

 となるように作ります。
 Webアプリケーションとしての見栄えを出すために、入力させるようにしていますが、
 もちろん固定値として据え置くこともできます。


 実装したWebアプリケーションはこんな感じになりました。

 ①入力画面
 

 ②ラベル付けに成功しました(ラベル名に「テスト」、件名に「テスト」と入力しています)




 









 ③実際にラベルができています
 




 
 
 ④件名に「テスト」とつくスレッドがラベル付けされています






~実装内容~
 ソースコードとしてはこんな感じです。
 
 ①入力画面のソースコード(index.html)
  <div class="main">
  <div class="centering">
  <form name="addLabel">
    <h3>ラベル名</h3>
    <p><input type="text" name="label" class="search_value"></p>
       <h3>ラベル付け条件</h3>
    <div>
      <div class="search_set">
        <div class="search_title">From:</div><input type="text" name="from" class="search_value">
      </div>
      <div class="search_set">
        <div class="search_title">To:</div><input type="text" name="to" class="search_value">
      </div>
      <div class="search_set">
        <div class="search_title">件名:</div><input type="text" name="subject" class="search_value">
      </div>
    </div>
       <input type="submit" value="ラベル付け" onclick='google.script.run.withSuccessHandler(onSuccess).addLabel(this.parentNode)'>
  </form>
  </div>
  </div>
     <script>
    function onSuccess(message){
      alert(message);
    }
  </script>
Google App Scriptと連携するからと言っても、HTML自体はごく普通に書くことができます。
 赤字になっている部分はGoogleから提供されているフォームの送信処理になります。

 汎用的に書くと次のようになります。
 google.script.run.withSuccessHandler(onSuccess).サーバ側のメソッド名(this.parentNode)

 また、サーバ側のメソッドからの返り値はonSuccessメソッドに引き渡されます。

 今回サーバ側のメソッドとして定義しているaddLabelメソッドでは、
 ラベル付けの成否などを文字列として返すようになっています。


 ②サーバ側のソースコード(HTMLの呼び出すメソッド&HTMLとやりとりするメソッド)
  function doGet() {
    var output = HtmlService.createTemplateFromFile('index');
    return output.evaluate();
  }
     function addLabel(form){
    var offset = 100;
    var max = 2000;
    
    var labelName = form.label;
    var from = form.from;
    var to = form.to;
    var subject = form.subject;
    
    if(labelName && (from || to || subject)){
      var label = getLabel(labelName);
      var query = generateQuery(from, to, subject);
      var theads = getTheads(query);
      
      if(theads.length > max){
        return '条件にヒットするスレッドが多すぎます。'
      }
         for(var index = 0; theads.length + offset > index; index = index + offset + 1){
        labelToThreads(label, theads.slice(index, index + offset));
      }
        return 'ラベル付けに成功しました。';
    }
    else {
      return '入力が不足しています。';
    }
  } 
doGetのHtmlService.createTemplateFromFile('index')により、index.htmlを呼び出しています。

 addLabelはindex.htmlから送信されてきた情報を受け取っています。
 変数formにフォームで入力した情報が格納されており、
 form.(name属性名)でそれぞれの情報を取得できます。

 例として、入力画面の「ラベル名」に入力した値はform.labelで取得しています。

 また、getLabel、getTheadsというメソッドを作成し、内部処理でGmailAppを利用して
 ラベル付けに必要な情報を取得しています。
 
 getLabelメソッド
  function getLabel(labelName) {
    var label = GmailApp.getUserLabelByName(labelName);
    if(!label){
      label = GmailApp.createLabel(labelName);
    }
    return label;
  }
既に存在するラベルであれば、そのラベルの情報を取得し、
 存在しないラベルであれば、新規に生成しています。
 どちらの場合もGmailAppに用意されています。

 getTheadsメソッド
  function getTheads(query){
    var threads = GmailApp.search(query);
    return threads;
  }
GmailAppのsearchメソッドにより、条件に合致するスレッドを取得しています。

~課題~
 一件順調に終わっていそうですが、実は課題が残っています。
 
 今回はGmailAppのsearchメソッド(引数はqueryのみ指定)を利用し、条件に合致するスレッドを
 取得しているのですが、最新のスレッドから500スレッドまでしか取得できないようです。
 
 なので、500スレッド以上にラベル付けを行いたい場合は、
 searchメソッド(引数はquery, start, maxを指定)を利用することになるのですが、
 こちらのsearchメソッドでは最大で100スレッドまでしか取得できません。

 500スレッドまでは前者のsearch、まだ条件に合致するスレッドが残っているなら
 後者のsearchを利用することで理論上は1000スレッドであろうと3000スレッドであろうと
 スレッドにラベル付けができます。

 ただし、どちらのsearchメソッドも処理に時間がかかります。
 前回もGoogle App Scriptの課題として挙げた通り、実行するメソッドの処理に
 一定時間がかかると途中で処理が中断してしまいます。

 社内利用・ビジネスの利用を問わず、実際に自分でアプリケーションを組んでみて、
 パフォーマンスの計測を行ったうえで保証できる範囲や、上限・下限を考えることが必要になりますね。
 また、あくまでGoogle App Scriptを動作させる環境はGoogleが持っているので、
 一定期間で計測を行い、保証範囲を考え直すことも必要になってくるかもしれません。

0 件のコメント:

コメントを投稿