Google App Script 自動化

【GAS】Google Playの注文情報をカレンダーに登録

はじめに

Amazonと楽天市場の注文情報をGoogleカレンダーに登録できるようにしたら、他の注文情報も全部カレンダーに登録できるようにしてしまえ、ということで、Google Playの注文についてもカレンダーに登録できるようにしました。

ここで紹介する内容は、以下の条件を満たす方が対象となります。

対象読者

  • Google Playで購入することがある
  • Google Playからの注文確認メールをGmailで受信している
  • Google Playの注文確認メールの内容をGoogleカレンダーに自動登録させてみたい

では、どのように実装するのかを見ていきましょう。

Google Playの注文内容をカレンダー登録

ほとんどの処理はAmazonの注文情報処理や、楽天市場注文処理と同様です。

主な違いは以下の3点です。

  • Gmailでメールを抽出する際の検索文字が、Google Playからの注文確認メールを抽出する
  • イベントとして登録する文字が「GooglePlay注文」である
  • イベントの詳細に登録する内容の抽出方法がGoogle Play注文確認メール用に特化している

処理概要

以下のような処理を実装することを考えます。

  • Google Playから注文確認メールを受信
  • 未処理のメールを抽出
  • カレンダー注文確認メールの内容を登録
  • 注文確認メールに処理済みラベルを付ける

そして、この処理を定期的に行わせます。

未処理メールの抽出

楽天市場からの注文確認メールで、未処理のメールの抽出は以下の検索文字列で実現します。

メールの抽出条件の構文は、Gmailの抽出条件に設定できる構文と同じです。

// 処理済み後に付けるラベル名
var LABEL = '自動処理済';

// GMail検索文字列(Google Playからの投信積み立て完了メール)※未読でラベルなしが条件
var SEARCH_QUERY = 'is:unread -label:' + LABEL + ' from:googleplay-noreply@google.com subject:"Your Google Play Order Receipt from" ';

処理済みを識別するために、処理完了後に該当メールのラベルに「自動処理済」を付けます。

そのため、抽出条件は以下の4つとなります。

  • 未読であること(is:unread)
  • 「自動処理済」のラベルが付いていないこと(-label:自動処理済)
  • 楽天市場からのメールであること(from:googleplay-noreply@google.com)
  • 注文確認メールであることが確認できること(subject:"Your Google Play Order Receipt from")

Gmailへのアクセス方法については以下の記事を参照ください。

イベント内容説明

イベントの詳細を表示させたときに、以下のように注文確認メールの内容が確認できるようにします。

以下に処理概要とコードの抜粋を示します。

  • メールのプレーンテキストをmessage.getPlainBody()で取得してbodyに格納し、そこから改行で区切った本文をrowsに格納し、その後1行ごとに処理します。
  • 「Thank you」という文字列が出現する行から、「Questions? Visit」という文字が出現する行までを詳細内容に登録するためにcontentsに格納します。
  • 登録するイベントの開始日時startTimeはメールを受信した日時とします。
  • 終了時間endTimeはメール受信時間の10分後としていますが、好みによって変えてください。
  • startTime, endTime, contentsの内容を取得したら、registerCalendar()でカレンダーに登録します。
  • カレンダーに登録後、メールに処理が完了したことを示すラベル「自動処理済」をputLabel()で付けます。

// 検索文字列
var CUT_START = 'Thank you';
var CUT_END = 'Questions? Visit';
var FORWARD_MSG = '---------- Forwarded message ---------';

for(var k in threads){
  var thread = threads[k]
  var messages = thread.getMessages();
  for (var j in messages){
    var message = messages[j];
    var body = message.getPlainBody();   // HtmlメールからPlain textの本文を取得する
    var startTime = message.getDate();
    var endTime = new Date(startTime.getTime() + 10 * 60000);

    var contents = null;      // 登録内容
    var flgAdd = 0;           // 追加フラグ(0:追加しない、1:追加する)
    var flgEnd = 0;           // 終了フラグ(0:続ける、1:処理しないで終了する)

    // 注文メールの内容確認
    var rows = body.split("\n");
    for (var i in rows) {
      var row = rows[i];

      // 切り取り開始位置確認
      if (row.indexOf(CUT_START) >= 0) {
        flgAdd = 1;
      } 
      else if(row.indexOf(CUT_END) >= 0){
        flgAdd = 0;
      }
      else if(row.indexOf(FORWARD_MSG) >= 0){
        flgEnd = 1;
        break;
      }

      // CUT_STARTからCUT_ENDまでの間を取得する
      if(flgAdd){
        if(contents == null){
          contents = row;
        }
        else{
          contents = contents + row + '\n';
        }
      }
    }

    if(flgEnd){
      continue;
    }

    // Googleカレンダーに登録
    if(registerCalendar(calendar, startTime, endTime, contents)){

      // 処理済みメールとしてラベルを付ける
      putLabel(thread);
    }
  }
}

上記コードは説明のために抜粋したものなので、このままでは動作しません。

コードの全体については、「すべてのコード」を確認ください。

カレンダー登録

カレンダーのタイトルは「GooglePlay注文」とします。※好みで変えてください。

カレンダーに登録する詳細内容に、Google Playからの注文確認メールの内容を登録します。

また、イベントの色は緑色にしていますが、ここも好きな色を設定してください。

function registerCalendar(calendar, startTime, endTime, contents){
  if (startTime && endTime && contents) {
    var title = 'GooglePlay注文';

    // カレンダーに追加
    if(checkExist(calendar, startTime, endTime, title) == false){
      var options = {
        description : contents
      }
      var event = calendar.createEvent(title, startTime, endTime, options);
      event.setColor(CalendarApp.EventColor.GREEN);
      event.removeAllReminders();   // 利用実績なので通知しない
    }
  }  
}

登録済み情報チェック

カレンダーに追加する前に、同じ時間の同じタイトルで、既にカレンダーへの登録があるかチェックしています。

そして、同じイベントの登録がない場合に、カレンダーに登録します。

function checkExist(calendar, registStart, registEnd, registTitle){

  // イベントリスト取得
  var events = calendar.getEvents(registStart, registEnd);
  for(const event of events){
    var title = event.getTitle();
    if(title.indexOf(registTitle) >= 0){
      return true;    // イベント登録済み
    }
  }
  return false;  // イベント未登録
}

この関数では、カレンダーへの登録があるかをチェックし、以下のように値を返します。

  • イベント登録済み:true
  • イベント未登録:false

処理済みラベル

処理済みを識別する方法としては、既読にする方法もあるのですが、それだとメールをチェックした時に気づくことができず見落とす可能性が高くなるため、処理済みメールの識別には「自動処理済」のラベルを付けることにします。

この「自動処理済」のラベルについては、好みで変更することができます。

var LABEL = '自動処理済';

function putLabel(thread){
  var label = GmailApp.getUserLabelByName(LABEL);
  if(label){
    thread.addLabel(label);
    Logger.log('既存ラベル使用');
  }
  else{
    var newlabel = GmailApp.createLabel(LABEL);
    thread.addLabel(newlabel);
    Logger.log('新規ラベル追加');
  }
}

「自動処理済」のラベルがない場合は、新規にラベルを作る仕組みとしています。

実行結果

Googleカレンダーには以下のように登録されます。

イベントをクリックすることで、詳細内容を確認することができます。

全てのコード

/*
 * GooglePlayの注文内容をGoogle Calendarに登録する
 * 
 * Google Calenderに以下のフォーマットで終日イベントが作成される。
 * 「GooglePlay注文」
 * 
 * 2021/09/16 Created by N.Sekiya
 */

// 処理済み後に付けるラベル名(ラベルが存在しなければ自動的に作られる)
var LABEL = '自動処理済';

// GMail検索文字列(Google PlayGoogle Playからの投信積み立て完了メール)※未読でラベルなしが条件
var SEARCH_QUERY = 'is:unread -label:' + LABEL + ' from:googleplay-noreply@google.com subject:"Your Google Play Order Receipt from" ';

// 検索文字列
var CUT_START = 'Thank you';
var CUT_END = 'Questions? Visit';
var FORWARD_MSG = '---------- Forwarded message ---------';

function registGooglePlayOrderInformationToCalendar() {

  // デフォルトカレンダーを取得
  var calendar = CalendarApp.getDefaultCalendar();

  var threads = GmailApp.search(SEARCH_QUERY, 0, 1);
  if (threads.length === 0) {
    Logger.log('メールが見つかりません');
    return;
  }

  for(var k in threads){
    var thread = threads[k]
    var messages = thread.getMessages();
    for (var j in messages){
      var message = messages[j];
      var body = message.getPlainBody();   // HtmlメールからPlain textの本文を取得する
      var startTime = message.getDate();
      var endTime = new Date(startTime.getTime() + 10 * 60000);
      //Logger.log("body=" + body);

      var contents = null;      // 登録内容
      var flgAdd = 0;           // 追加フラグ(0:追加しない、1:追加する)
      var flgEnd = 0;           // 終了フラグ(0:続ける、1:処理しないで終了する)

      // 注文メールの内容確認
      var rows = body.split("\n");
      for (var i in rows) {
        var row = rows[i];

        // 切り取り開始位置確認
        if (row.indexOf(CUT_START) >= 0) {
          flgAdd = 1;
        } 
        else if(row.indexOf(CUT_END) >= 0){
          flgAdd = 0;
        }
        else if(row.indexOf(FORWARD_MSG) >= 0){
          flgEnd = 1;
          break;
        }

        // CUT_STARTからCUT_ENDまでの間を取得する
        if(flgAdd){
          if(contents == null){
            contents = row;
          }
          else{
            contents = contents + row + '\n';
          }
        }
      }

      if(flgEnd){
        continue;
      }

      //Logger.log(startTime);
      //Logger.log(endTime);
      //Logger.log(contents);

      // Googleカレンダーに登録
      if(registerCalendar(calendar, startTime, endTime, contents)){

        // 処理済みメールとしてラベルを付ける
        putLabel(thread);
      }
    }
  }
}

/*
 * Google Calendarに登録
 */
function registerCalendar(calendar, startTime, endTime, contents){
  if (startTime && endTime && contents) {
    var title = 'GooglePlay注文';

    // カレンダーに追加
    if(checkExist(calendar, startTime, endTime, title) == false){
      var options = {
        description : contents
      }
      var event = calendar.createEvent(title, startTime, endTime, options);
      event.setColor(CalendarApp.EventColor.GREEN);
      event.removeAllReminders();   // 利用実績なので通知しない

      return true;
    }
  }  
  return false;
}

/*
 * 登録済み情報があるかチェック 
 */
function checkExist(calendar, registStart, registEnd, registTitle){

  // イベントリスト取得
  var events = calendar.getEvents(registStart, registEnd);
  for(const event of events){
    var title = event.getTitle();
    if(title.indexOf(registTitle) >= 0){
      return true;    // イベント登録済み
    }
  }
  // イベント未登録
  return false;
}

/*
 * 処理済みとしてスレッドにラベルを付ける
 * LABELで指定されるラベルが存在しない場合は作成する
 */
function putLabel(thread){
  var label = GmailApp.getUserLabelByName(LABEL);
  if(label){
    thread.addLabel(label);
    Logger.log('既存ラベル使用');
  }
  else{
    var newlabel = GmailApp.createLabel(LABEL);
    thread.addLabel(newlabel);
    Logger.log('新規ラベル追加');
  }
}

繰返し実行

正しく動作することを確認したら、繰り返し実行できるよう設定します。

繰り返し実行には、トリガーの設定を行います。設定方法については、以下の記事を参照ください。

繰り返し実行する間隔は、急ぐ必要のない処理なので5分おきにします。

最後に

更に、Amazon、楽天市場、Google Playのどこから購入しても注文内容を一つのGoogleスプレッドシートに自動的に追加できるようになると、物品管理リストが自動的にできるようになりますね。

あら、書いてて関谷さんが欲しくなりました。近いうちに機能追加しようと思います。

また、Amazon、楽天市場、Google Playの注文確認メールの処理には共通した処理が多いので、この共通処理をライブラリ化してコードのメンテナンス性を上げることを考えるのが良いと思います。

ライブラリ化についてはどこかで説明しようと思います。

では、今日も良い一日を。

-Google App Script, 自動化
-, , , , ,