Google App Script 自動化

【GAS】楽天カードの利用速報をカレンダーに自動登録

はじめに

Google Apps Scriptを使った便利な自動化の例を紹介します。

まず、楽天カードには、カードを利用するとすぐに利用速報として利用額をメールで送信する機能があります。

このメールから必要な情報を抽出して、カレンダーに登録することで、何時いくら使ったのかを記録して簡単に振り返ることができるようになります。

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

対象読者

  • 楽天カードを使用している
  • 楽天カードから利用速報通知メールを受け取る設定になっている
  • 利用速報の情報をGoogleカレンダーに自動登録させたい

Google Apps Scriptについては以下の記事を参照ください。

楽天カードの利用速報内容をカレンダー登録

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

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

  • Gmailでメールを抽出する際の検索文字が、楽天カードの利用速報メールを抽出する
  • 利用速報メールの内容解析
  • カレンダーに登録する文字が「本+利用額」もしくは「家+利用額」である

処理概要

最初に、以下の処理を実装することを考えます。

  • 楽天カードから利用速報メールを受信
  • 未処理のメールを抽出
  • カード利用日に利用額をカレンダーに登録
  • 登録時、本人カード利用の場合は「本+利用額」とする
  • 登録時、家族カード利用の場合は「家+利用額」とする
  • 利用速報メールに処理済みラベルを付ける

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

未処理メールの抽出

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

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

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

// GMail検索文字列(楽天カードからの請求予定金額情報)
var SEARCH_QUERY = 'is:unread -label:' + LABEL + ' from:info@mail.rakuten-card.co.jp subject:【速報版】カード利用のお知らせ';

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

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

  • 未読であること(is:unread)
  • 「自動処理済」のラベルが付いていないこと(-label:自動処理済)
  • 楽天カードからのメールであること(from:info@mail.rakuten-card.co.jp)
  • 利用速報であること(subject:【速報版】カード利用のお知らせ)

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

カレンダー登録

カレンダーのタイトルは、本人カードの場合と家族カード使用の場合で分けてます。

  • 本人カードの場合 「本+利用額」
  • 家族カードの場合 「家+利用額」

タイトルの表示内容については好みで変えてください。

以下のコードでは、who(「本」or「家」)+ amount(利用額)で指定しています。

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

function registerCalendar(calendar, day, amount, who){
  var registerDate = new Date(day);
  if (day && amount && who) {
    var title = who + amount;
    Logger.log('登録内容:' + day + '登録内容:' + title);

    // カレンダーに追加
    if(checkConflict(calendar, registerDate, title) == false){
      var event = calendar.createAllDayEvent(title, registerDate);
      event.setColor(CalendarApp.EventColor.PALE_GREEN);
      event.removeAllReminders();   // 利用実績に通知はしない
    }
  }  
}

登録済み情報チェック

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

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

function checkConflict(calendar, registerDate, registerTitle){

  // registerDateで指定する日付のイベントリスト取得
  var events = calendar.getEventsForDay(registerDate);

  // イベントリスト中のイベント毎に登録済みかチェックする
  for (var i in events) {
    var event = events[i];                          // イベントひとつ取得
    var eventTitle = event.getTitle();              // イベントタイトル取得
    if(event.isAllDayEvent()){                      // 終日イベントかチェック
      if(eventTitle.indexOf(registerTitle) >= 0) {  // イベント登録済みかチェック
        Logger.log('登録済:event.getTitle()=' + event.getTitle() + 'registerTitle=' + registerTitle);

        // イベント登録済み
        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カレンダーには以下のように登録されます。

ただ、詳細内容には何も登録していないので上の画像のように表示されます。

楽天カードの利用速報メールには、利用日、利用者、利用額の3つの情報しかないため、詳細に登録する情報がないためです。

もちろん、追加で登録したい内容があったら好みに合わせて修正してください。

全てのコード

以下に全てのコードを示します。

/*
 * 楽天カードからの速報版カード利用のお知らせ金額をGoogle Calendarに登録する
 * 
 * Google Calenderに以下のフォーマットで終日イベントが作成される。
 * 「本|家xxx,xxx円」
 *  本:本人利用
 *  家:家族利用
 * 
 * 2021/09/13 Created by N.Sekiya
 */

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

// GMail検索文字列(楽天カードからの請求予定金額情報)
var SEARCH_QUERY = 'is:unread -label:' + LABEL + ' from:info@mail.rakuten-card.co.jp subject:【速報版】カード利用のお知らせ';

// 検索文字列
var PAY_DAY = '■利用日: ';
var PAY_AMOUNT = '■利用金額: ';
var PAY_WHO = '■利用者: ';

function registPreliminaryPaymentInformationToCalendar() {

  // デフォルトカレンダーを取得
  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 payDay = null;        // 利用日
      var payWho = null;        // カード使用者(本人|家族)
      var payAmount = null;     // 支払金額
      //Logger.log(body);

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

        if (row.indexOf(PAY_DAY) >= 0) {
          payDay = row.replace(PAY_DAY, '');
        } 
        else if (row.indexOf(PAY_WHO) >= 0){
          payWho = row.replace(PAY_WHO, '');
          payWho = payWho.substring(0, 1);
        }
        else if (row.indexOf(PAY_AMOUNT) >= 0) {
          payAmount = row.replace(PAY_AMOUNT, '');
          payAmount = payAmount.replace(' ', '');

          // Google Calendarに登録
          registerCalendar(calendar, payDay, payAmount, payWho);

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

/*
 * Google Calendarに登録
 */
function registerCalendar(calendar, day, amount, who){
  var registerDate = new Date(day);
  if (day && amount && who) {
    var title = who + amount;
    Logger.log('登録内容:' + day + '登録内容:' + title);

    // カレンダーに追加
    if(checkConflict(calendar, registerDate, title) == false){
      var event = calendar.createAllDayEvent(title, registerDate);
      event.setColor(CalendarApp.EventColor.PALE_GREEN);
      event.removeAllReminders();   // 利用実績に通知はしない
    }
  }  
}

/*
 * 登録済み情報があるかチェック
 * 
 */
function checkConflict(calendar, registerDate, registerTitle){

  // registerDateで指定する日付のイベントリスト取得
  var events = calendar.getEventsForDay(registerDate);

  // イベントリスト中のイベント毎に登録済みかチェックする
  for (var i in events) {
    var event = events[i];                          // イベントひとつ取得
    var eventTitle = event.getTitle();              // イベントタイトル取得
    if(event.isAllDayEvent()){                      // 終日イベントかチェック
      if(eventTitle.indexOf(registerTitle) >= 0) {  // イベント登録済みかチェック
        Logger.log('登録済:event.getTitle()=' + event.getTitle() + 'registerTitle=' + registerTitle);

        // イベント登録済み
        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分おきにします。

最後に

残念ながら、楽天カード以外のカードは所有していないので、他のカード会社が利用速報メールの配信があるのかはわかりません。

でも、楽天カード以外のカード会社から同様の利用速報メールを受け取っており、その内容をカレンダーに表示させたい方がいらしたら、気軽に相談してください。

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

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