非エンジニアがGASを書いたが請求書フローが間違っているので改善してみた

メールに添付されている請求書をGoogleドライブに保存

メールに添付されている請求書をGoogleドライブに保存するという記事があったのだが、コードが間違っていて使い物にならなかったので改善してみた。

非エンジニアがGASを書いて「ちょっとめんどくさい請求書処理フロー改善」してみた

ちなみにGASとはGoogle Apps Scriptの略でscript.newにアクセスすれば作成可能。

改善して作成したコードは以下の通り。

function Attachment_to_GDrive() {
  const now = new Date()
  const day_before = new Date(now.setDate(now.getDate() - 1))
  const yesterday = Utilities.formatDate(day_before, 'JST', 'yyyy/MM/dd')

  // 請求書を保存するフォルダ
  const folder_id = '1kVqPI0v7cxoug7qpV6Z3BEA6Of2Wuxg7'
  const save_folder = DriveApp.getFolderById(folder_id)

  // メールの検索条件
  const to_mail = 'example@gmail.com'
  const conditions = [
    `is:unread`,          // 未読
    `has:attachment`,     // 添付あり
    `after:${yesterday}`, // 今日(昨日より後)
    `to:${to_mail}`       // 受信用メールアドレス
  ]

  // メール検索
  const search_mail = GmailApp.search(conditions.join(' '))

  // 検索したメールをスレッドで取得
  const messages = GmailApp.getMessagesForThreads(search_mail)

  // Googleドライブに保存するファイルタイプを選別する正規表現
  const file_regexp = /\.(docx?|xlsx?|txt)$/

  for (const thread of messages) {
    for (const message of thread) {
      const attachments = message.getAttachments()
      for (attachment of attachments) {
        const file_name = attachment.getName()
        if (file_regexp.test(file_name)) {
          save_folder.createFile(attachment)
        }
      }
      message.markRead() // メールを既読にする
    }
  }
}

Googleドライブに請求書を保存するためのフォルダを作成してコード内にある「folder_id」と「to_mail」の部分を変更して実行すれば動作します。

folder_idはGoogleドライブのフォルダのURLのうしろに付いています。

例: https://drive.google.com/drive/folders/1kVqPI0v7cxoug7qpV6Z3BEA6Of2Wuxg7

請求書をGoogleドライブに保存するコードについて

元記事のコードを流用したが、色々修正したので原型をあまりとどめていない。

constを使用していなかったり、for ... of を使用していないなどの問題のある箇所はすべて修正。

Googleドライブに保存するファイルタイプを選別する正規表現もなかったので、こちらを新たに追加した。

// Googleドライブに保存するファイルタイプを選別する正規表現
const file_regexp = /\.(docx?|xlsx?|txt)$/

for (const thread of messages) {
  for (const message of thread) {
    const attachments = message.getAttachments()
    for (attach of attachments) {
      const file_name = attachment.getName()
      if (file_regexp.test(file_name)) {
        save_folder.createFile(file_name)
      }
    }
    message.markRead() // メールを既読にする
  }
}

正規表現でファイルタイプ(拡張子)をチェックしておかないとウィルスが添付されたファイルがGoogleドライブに保存されてしまうので危険です。

「attachment.getName()」でファイル名を取得しているので条件を追加すればファイル名に「請求書」が含まれるものだけGoogleドライブに保存することもできる。

あと元のコードはメール検索のテキストを「+=」で結合していたが半角スペースを入れ忘れると正しく検索されなくなるので、join(' ')に変更している。

conditions.join(' ')は以下のような結果になる。

is:unread has:attachment after:2022/07/06 to:example@gmail.com

参考: Gmail で使用できる検索演算子

トリガーを設定して定期的に実行する

元記事だと記載が漏れていますが、このコードは手動ではなくApps Scriptのトリガーに設定して定期的(1分毎)に実行します。

やり方はApps Scriptのトリガーのページで「トリガーを追加」を選択して作成した「Attachment_to_GDrive」を選択して以下の設定で保存します。

  • Head
  • 時間主導型
  • 分ベースのタイマー
  • 1分おき
トリガーを設定して定期的に実行する

こうすることで1分おきにAttachment_to_GDrive関数が実行されてメールをチェックし、該当の添付ファイルがあればGoogleドライブの指定したフォルダに自動保存するようになります。