Google Apps Script で領収書管理を楽にする

2021/2/16

はじめに

確定申告のため、メールに添付された領収書をちまちまと手作業で整理したんですが、なかなかに面倒だったので、Google Apps Script で自動化してみました。

自動化内容

概要

  • Gmail で受信したメール(検索クエリで抽出)に添付されている pdf ファイルを Google Drive にコピー。
  • 保存先 Google Drive は年毎にフォルダ分けし、コピーした pdf は日付と識別キー(サービス毎に設定)を含めたものにリネーム。
  • 識別キー毎にメール検索クエリを設定。
  • 処理済みメールにはラベルを付けて、重複処理を回避。

実装

const LABEL_NAME = '自動処理済み';
const FOLDER_ID = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
const KEY_TO_QUERY = {
  // Zendesk 領収書用設定。
  'zendesk': 'subject:(Your payment was successfully processed.)',

  // ここに設定を追加していく。
};
const SEARCH_COUNT = 10;


const _copyEmailAttachmentToDrive = (folder, label, key, query, searchCount) => {
  // 重複処理回避用ラベルは除外するようにクエリ修正。
  const queryWithoutLabel = query + ' -{label:' + label.getName() + '}';
  GmailApp.search(queryWithoutLabel, 0, searchCount).forEach(thread => {
    GmailApp.getMessagesForThread(thread).forEach(message => {
      // 受信日取得&整形。
      const date = message.getDate();
      const yyyy = date.getFullYear().toString();
      const mm = ('00' + (date.getMonth()+1)).slice(-2);
      const dd = ('00' + date.getDate()).slice(-2);

      // 添付ファイルコピー先の年毎フォルダ準備。
      let yearfolder = null;
      const folderIterator = folder.getFoldersByName(yyyy);
      if (folderIterator.hasNext()) {
        yearfolder = folderIterator.next();
      } else {
        yearfolder = folder.createFolder(yyyy);
      }
      // 添付ファイル(pdf のみ)をコピーしてリネーム。
      message.getAttachments()
        .filter(attachment => attachment.getContentType() === 'application/pdf')
        .forEach((attachment, i) => {
          const file = yearfolder.createFile(attachment);
          file.setName(yyyy + mm + dd + '_' + key + '_' + i);
        });
    });
    // 重複処理回避のためにラベルを付ける。
    label.addToThread(thread);
  });
}

function copyEmailAttachmentToDrive() {
  const folder = DriveApp.getFolderById(FOLDER_ID);
  const label = GmailApp.getUserLabelByName(LABEL_NAME);
  
  Object.keys(KEY_TO_QUERY).forEach(key => {
    _copyEmailAttachmentToDrive(folder, label, key, KEY_TO_QUERY[key], SEARCH_COUNT);
  });
}

補足

  • 前提として、親フォルダと重複処理用ラベルは作成しておく必要あり
  • デフォルトだとタイムゾーンが日本ではなかったので、プロジェクトで設定する必要あり
  • せっかく Google Apps Script 使ったので、定期起動する設定をすると良いかと
  • .pdf 拡張子が消えるが、Google Drive 上は正しく pdf と認識されており、ダウンロードする際にはちゃんと拡張子付きでダウンロード可

おわりに

面倒な手作業を割り切って受け入れるか、ごく稀にしか扱わない不慣れな Google Apps Script 開発か・・・。今回は勢いで実装してしまいましたが、今後の保守まで考えると難しい問題ではあります。