2015/05/11

Google Apps Scriptによるメール自動返信botの作成(1)

自分語りで一記事余計に使ってしまったため、この記事が本編となる。

前提
  • 自動返信のプログラムにはGoogle Apps Scriptを用いる。
  • 返信内容のパターンは自分で考える
  • この記事では本文に「おはよ」が含まれ、かつ特定のアドレスからのメールに対して予め決められた内容を返信するプログラムを作る
必要なもの
  • 自動返信bot用のGoogleアカウント
  • bot用とは別のメールアドレス(Gmailでなくてもよい)

さて、さっそく実際のプログラミングに移ろう。まず今回使用する「Google Apps Script」を使用できるようにする。
まずはGoogleドライブへ入り、新規→その他→「アプリを追加」を選択。検索フォームに「Google Apps Script」と入力し、検索する。恐らく一番上に出てくるであろう「Google Apps Script」の右側にある「接続」をクリック。
そしてドライブの最初の画面に戻り、再び新規→その他と進むと、「Google Apps Script」(以下、GAS)が出現しているはずである。これをクリックする。
クリックするとGASのメニューが表示されるので「空のプロジェクト」をクリックする。新しくプロジェクトが作成されるので、ここにメールの返信スクリプトを書いていくことになる。

さて、実際のプログラミングに移る前に、処理の内容を検討する。

  1. 受信トレイからメールを取得する
  2. 取得したメールが未読かを確認する
  3. 未読であればメールの差出人を確認し、自分が送ったメールアドレスか確かめる
  4. 自分が送信したものであれば、本文を読み込む
  5. 本文に、決められたパターンと合致する文言があるか(今回では「おはよ」)確認する
  6. パターンと合致した場合、そのパターンにふさわしい内容の返信メールを作成し、送信する。

これらの機能ごとに関数を作成していくことにする。

1.受信トレイからメールを取得し、未読かどうかを確認する。(confirmUnread関数)

function confirmUnRead(){
  var thds = GmailApp.getInboxThreads(0,10);
  for(var n in thds){
    var thd = thds[n];
    if(thd.isUnread()){
      thd.markRead();
      confirmFrom(thd);
    }
  }
}
基本的に文法はjavascriptに準拠している。その上でGoogleが用意した関数その他を利用していく、というスタイルになる。
var thds = GmailApp.getInboxThreads(0,10);
使用した関数:getInboxThreads(start, max) - Class GmailApp - Apps Script Google Developers 
早速Googleが用意してくれた関数を用いる。
ここでは受信トレイの最初から10番目までの「スレッド」を取得している。プログラミングではいつものことだが、一番最初のスレッドは「0番目」なので注意する。
  for(var n in thds){
    var thd = thds[n];
    if(thd.isUnread()){
      thd.markRead();
      confirmFrom(thd);
    }
  }
使用した関数:
- isUnread() - Class GmailThread - Apps Script Google Developers
- markRead() - Class GmailThread - Apps Script Google Developers  取得したのはスレッドの配列なので、そこからスレッドをひとつずつ未読かどうか確認する作業を行う。その作業では当然for文を使うが、javascriptに慣れていない私はここで一回詰まってしまった。
for(var n in thds){
 この部分なのだが、Javaでいうところの拡張for文のノリ、つまりスレッドの配列からスレッドを1つずつ取り出せるのだろうと思って書いたのだがうまく動かず、リファレンスを読むとどうも違うようで、各オブジェクトのプロパティを取り出してnに代入しているようだ。
 より具体的には「取り出したものが配列の何番目か」、というのがnに代入されているようだ。
var thd = thds[n];
 というわけで、このように書けばthds配列中のすべてのスレッドを取り出せることになる。取り出した配列はisUnread関数で未読かどうかを確認、もしそれがtrue(未読)であれば、if文内の処理(スレッドを既読にし、スレッドを引数としてconfirmFrom関数を実行)を行う。

2.取得した未読メールが自分からのメールか確認する(confirmFrom関数)
さて、そのconfirmFrom関数の内容だ。

function confirmFrom(thd){
  var msgs = thd.getMessages();
  for(m in msgs){
    var m = msgs[m];
    if(m.getFrom().indexOf('自分が送信に使うメールアドレス',0)!=-1){
        confirmBody(m);
    }      
  }
}
使用した関数:
- getMessages() - Class GmailThread - Apps Script Google Developers
- getFrom() - Class GmailMessage - Apps Script Google Developers  引数として渡されているのは「スレッド」であり、いくつかの「メッセージ」の連なりだ。よって、このスレッドからメッセージを取り出す。受信トレイからスレッドの配列を取り出したのと同様に、getMessages関数を用いてメッセージの配列を取得しmsgsに代入し、これまた同様にfor文を用い、メッセージの配列からメッセージを取り出す。
 取り出したメッセージの送信元は、getFrom関数を用いて取得する。そして更に、その送信元の文字列に自分のメールアドレスが含まれているか、indexOfを用いて検索する。indeOfはGAS特有の機能ではなく、javascript標準の関数だ。第一引数に検索する文字列、第二引数に走査を開始する位置を入れると、その検索する文字列がはじまる位置を返してくれる関数で、見つからなければ-1を返す。よって、この関数の戻り値が-1でなければ、送信元アドレスの文字列に自分のアドレスが含まれていることがわかる。
 どうしてダイレクトに
m.getFrom=="自分が送信に使うメールアドレス"
としなかったかというと、getFromで取得される送信元は、送信時に使ったメールクライアントなどによって同じアドレスでも別の送信元文字列となることがあるからだ。
具体的には、Gmailでは「(登録した送信者名)<送信に使用したメールアドレス>」の形となる。送信者名を変更したりした場合にプログラムを修正しなくて済むように、ここはindexOfを用いることにした。

取得したメッセージが自分(が送信に用いるアドレス)からのメールであるときには、メッセージを引数としてconfirmBody関数を実行するようにした。これ以降の内容については次回の記事で扱うことにする。

0 件のコメント:

コメントを投稿