Google Apps ScriptでGmailにあるカード明細をスプレッドシートに出力する

GASを使ってGmailの整理の自動化を進めているのですが、Amazonやメインで使っている銀行口座やクレジットカードなどの明細はせっかくなのでスプレッドシートに転記してからメールを削除するようにすると色々便利そうです。

  • メインの出費項目をそれぞれのサイトに行って検索しなくてもワンストップで確認できる
  • GASのURL Fetch Serviceは1日あたりの制限があるがGmailで取得すれば回数を圧迫しない(スクリプトの実行時間制限はあるけど)

というわけで手始めに猫でも取れると評判の楽天カードの明細をスプレッドシートに転記してから削除するGASを書きました。

今回はGASで取得しやすくするためにGmail側で受信時にラベルをつけるフィルタを設定することにしました。楽天はカード決済があるたびにメールでお知らせしてくれます。(これは親切で良いですね。)楽天カードは利用明細メールに金額だけで情報の少ない速報版があるのでそれは除外するようにフィルタを設定します。

楽天の明細メールをプレーンテキストで取得すると次のようなフォーマットになります。

(中略)
< カードご利用情報 >
《リボ払い変更可能なご利用分》
■利用日: 2018/11/01
■利用先: hoge
■利用者: 本人
■支払方法: 1回
■利用金額: 1,686 円
■支払月: 2018/12
■カード利用獲得ポイント:
 16 ポイント
■ポイント獲得予定月:
 2018/12

■利用日: 2018/11/02
■利用先: fuga
■利用者: 本人
■支払方法: 1回
■利用金額: 500 円
■支払月: 2018/12
■カード利用獲得ポイント:
 5 ポイント
■ポイント獲得予定月:
 2018/12

(中略)

結構抜き出しやすそうです。利用先は日本語は半角カナでの記載になるので変換してあげると良さそうです。このうち利用者欄は結構最近追加された部分で、今後も多分本人しか使わないので今回は取得から外します。

function syncRakutenCard() {
  /* 楽天カードの利用明細をスプレッドシートに同期 */
  var result = [];
  var threads = GmailApp.getUserLabelByName('expense/receipt').getThreads();

  for (var i = 0; i < threads.length; i++) {
    var messageBody = threads[i].getMessages()[0].getPlainBody();
    var cardUses = messageBody.match(/利用日[\s\S]*?ポイント獲得予定月:(\r\n|\r|\n).*/g);
    for (var j = 0; j < cardUses.length; j++) {
      var useDate = cardUses[j].match(/利用日:.*/)[0].replace('利用日: ', '');
      var payee = cardUses[j].match(/利用先:.*/)[0].replace('利用先: ', '');
      var payNum = cardUses[j].match(/支払方法:.*/)[0].replace('支払方法: ', '');
      var amount = cardUses[j].match(/利用金額:.*/)[0].replace(/[^0-9]/g, '');
      var payMonth = cardUses[j].match(/支払月:.*/)[0].replace('支払月: ', '');
      var point = cardUses[j].match(/カード利用獲得ポイント:(\r\n|\r|\n).*/)[0].replace(/\D*/g, '');
      var pointMonth = cardUses[j].match(/ポイント獲得予定月:(\r\n|\r|\n).*/)[0].replace(/[^\d\/]/g, '');
      result.push([useDate, hankana2zenkana(payee), payNum, amount, payMonth, point, pointMonth]);
    }
  }

  var output = result.reverse(); // 日付が古い順にする
  var rakutenSheet = SpreadsheetApp.openById(prop.getProperty('BALANCE_SHEET_ID')).getSheetByName('楽天カード');
  var startRow = rakutenSheet.getLastRow() + 1;
  rakutenSheet.getRange(startRow, 1, output.length, 7).setValues(output); // シートに記入
  console.log('カード使用情報: ' + output.length + '件');
  GmailApp.moveThreadsToTrash(threads); // スレッドを削除
  console.log(threads.length + '件の楽天カード明細メールを削除しました。');
}

ラベルのついたスレッドを取得してループを回してスプレッドシートに書き込む配列を作っています。カナの半角全角変換関数はJavaScriptで正規表現(文字列置換え編) - Qiitaからお借りしました。Gmailスレッドは日付が新しい順から取得されているので、スプレッドシートは古い順に書き込むように配列を.reverse()で反転させています。メールの削除はループ中にもできますが念のため最後にしました。

結果

できました(Amazonの5円なんだろうと思ったらインベスターZのセールですね)

あとはGASのトリガーで毎月の支払確定日あたりに実行すればOKですね。Amazonの履歴も同じスプレッドシートに同期しておけば、今度は各シートの項目同士をリンクしたり、スプレッドシートのクエリ関数でいい感じにまとめられそうです。