かもメモ

自分の落ちた落とし穴に何度も落ちる人のメモ帳

特定のラベルが付いたgmailでの受信を自動的にスプレッドシートに記録したい

サービスとかのメールフォームから送られた内容とかアラートとか、まぁDBに保存してダンプすれるのが本来良いと思うのですが、DBが無かったり諸々のアレでメールだけで受け取っていたりするような事もあると思います。
今回はGmailで受け取ったそれらのメールを、管理しやすいように自動的にスプレッドシートに記録できるようにしてみました。

1. Gmailにラベル設定をする

Gmailの設定 > フィルタとブロック中のアドレス から スプレッドシートに記録したいメールに特定のラベルを付けるフィルタを作成します。

2. スプレッドシートスクリプトを作成する

メール内容を保存するスプレッドシートを作成し、メニューのツール > スクリプト エディタ...を選択して自動保存するためのスクリプトを作成します。

/**
 * ラベルが付いた未読のメール(スレッド)を探して返す
 * @return GmailThread[]
 */
function getMail() {
  var label = "Gmailでつけたラベル名";
  var start = 0;
  var max = 500;
  return GmailApp.search('label:' + label + ' is:unread', start, max);
} 

/**
 * メール本文を整形してスプレッドシートに保存するためのオブジェクトを返す
 * @return Object
 */
function getDatabyMailBody( body ) {
  // <br>タグがあったら改行コードに変換する
  var str = body.replace(/<br(\s+\/)?>/g, "\n");
  /* 適時必要な形式に正規表現などで変換してください */
  var id = str.match(/id: ([0-9]+)/g);
  var code = str.match(/errorcode: .*[^\n]/g);

  return {
    id: id,
    code: code
  };
}

/**
 * gmailを取得してスプレッドシートに保存する
 */
function onSaveMailToSheet() {
  // データを保存するシートの名前
  var sheetName = 'シート1';
  var ss = SpreadsheetApp.getActive().getSheetByName( sheetName );
  var row = ss.getLastRow() + 1;
  var threads = getMail();

  for( var i in threads ) {
    var thread = threads[i];
    var msgs = thread.getMessages();
    // スレッド内のメールをそれぞれチェックする
    for( var j in msgs ) {
      var msg = msgs[j];
      // スレッド内の未読メッセージのみを処理
      if( msg.isUnread() ) {
        var date = msg.getDate();
        var d = getDatabyMailBody( msg.getBody() );
        var values = [
          [date, d.id, d.code]
        ];
        // シートに保存
        // ※ 3コラムなので A:C のRangeを取る。データ数に合わせて変更が必要
        ss.getRange("A" + row +":C" + row).setValues(values);
        row++;
      }
    }
    // スレッドを既読にする
    thread.markRead();
    Utilities.sleep(10000);
  }
}

メッセージの整形は正規表現や不要な部分をreplace()で取ってしまうなど適時行ってください。

ポイントはmsg.isUnread()でメッセージ単位の未読を判定することです。
GmailApp.searchで未読のスレッドを取得しているのですが、Gmailの同じスレッド内に1つでも未読のメッセージがあるとスレッド全体が未読として取得されてしまいます。なので、メッセージ単位で未読・既読を判別して未読のメッセージだけ処理するようにしないと既にシートに保存されているメッセージを重複して保存してしまう可能性がでてしまいます。

また、処理した後はメッセージ単位で既読にしても良いのですが、スレッド全体を既読にする方が処理が少なくて済むので、メッセージを処理するループが終わった段階でthread.markRead();でスレッドを既読にしています。

3. 保存されるかチェックする

f:id:kikiki-kiki:20160415163813p:plain スクリプトエディタのメニューから 実行 > onSaveMailToSheet を選択して、スプレッドシートにラベルの付いた未読のgmailの内容が保存されていればOKです。

4. 定期的にスクリプトを実行させる

f:id:kikiki-kiki:20160415163832p:plain スクリプトエディタのツールバーにある時計マーク 又はメニューのリソース > 現在のプロジェクトのトリガーを選択ます。トリガーの追加をクリックし、

f:id:kikiki-kiki:20160415163919p:plain

実行 イベント
onSaveMailToSheet 時間主導型・時タイマー ・N時間ごと

onSaveMailToSheet 関数を定期的に実行して欲しいので上記の様な設定で保存します。(N時間ごと はメールのくる頻度に合わせて調整してください)
初回の場合は保存ボタンを押した後に「認証が必要です」と出てくるので「続行」を押します。別ウィンドウでGmailの認証が表示されますので「許可」を選択すればOK。後はトリガーで指定した時間毎にGmailをチェックしてスプレッドシートに内容を保存してくれるようになります。


感想

個人的に単純作業とかは人間の手が入れば入るほどミスが発生する可能性が上がると思っているので、あまり生産性のない単純作業なタスクこそガンガン自動化していくべきだと考えています。
今回gmailスプレッドシートに自動保存をやってみてGoogle Apps Scriptには他にも色々なメソッドがある事を改めて知りました。gmailスプレッドシートの連携だけでなく使い方を工夫すれば色々な自動化も出来そうだな―と思いました。
まぁ、今回のみたいなケースだとアプリ側で自動的にSCVとか作成するようにしておくのがベストだとは思いますが、
 

note.

GmailApp.search(query, start, max)

Parameters

Name Type Description
query String 検索クエリ
start int 最初のスレッドのインデックス
max int 返すべきスレッド数の最大値

Return
GmailThread[] — 指定されたクエリにマッチしたGmail threadsの配列を返す


GmailThread.getMessages()

Return
GmailMessage[] — スレッド内のGmailメッセージを配列で返す


GmailMessage.isUnread()

Return
Boolean — 未読ならTrue・既読ならfalseを返す


GmailMessage.getDate()

Return
Date — このメッセージの日付


GmailMessage.getFrom()

Return
String — メこのッセージ送信者のメールアドレス


GmailMessage.getBody()

Gets the HTML content of the body of this message.

Return
String — このメッセージの本文(HTML)


markRead

GmailThread.markRead() — このスレッドを既読としてマークする
GmailMessage.markRead() — このメールを既読としてマークする


[参考]

小さなチーム、大きな仕事〔完全版〕: 37シグナルズ成功の法則

小さなチーム、大きな仕事〔完全版〕: 37シグナルズ成功の法則

  • 作者: ジェイソン・フリード,デイヴィッド・ハイネマイヤー・ハンソン,黒沢 健二,松永 肇一,美谷 広海,祐佳 ヤング
  • 出版社/メーカー: 早川書房
  • 発売日: 2012/01/11
  • メディア: 単行本
  • 購入: 21人 クリック: 325回
  • この商品を含むブログ (39件) を見る