Gmailの添付ファイルを自動でGoogle Driveに保存　をGAS(Google Apps Script)で実装 

初投稿です。

<h2>やりたいこと</h2>
<h3>Gmailで条件検索したメールの添付ファイルを、Google Driveに自動で保存</h3>
他担当者が、取引先からの請求書を都度印刷→経理ソフトで入力していましたが、印刷を省いてPDFファイルを表示しながら入力する環境を目指すため、Gmailのメールを添付ファイル(請求書はPDFですが今回は添付ファイルななんでも保存)をGoogle Driveに保存するスクリプトを実装しました。
新規性に乏しい無い内容ですが、初投稿ということと、多少つまづいた点を含め、記載しておきます。

<h2>実装の流れ</h2>
1. コーディング：Gmailを条件検索(今回は from,日付,添付あり を条件)し、検索結果を取得
2. コーディング：検索結果から添付をGoogle Driveへ順次保存
3. 実行トリガー設定：時間をトリガーとして1日に1回実行する

コード以下を参照させていただきました。ほぼ丸々コピー。
[テレビ局で働く独学プログラマー　Gmailの添付ファイルをgoogle driveに保存する](https://mtomo661.hatenablog.jp/entry/2019/04/14/020614)

<h2>1. Gmailを条件で検索(今回は from,日付,添付あり を条件)し、検索結果を取得</h2>

```js:SaveGmailAttachToDrive.gs
  //メール検索用の日付計算
  var now = new Date();
  var today = new Date(now.getFullYear(), now.getMonth(), now.getDate()); //こうすることで0時0分0秒となる
  var yesterday = new Date(today.getFullYear(), today.getMonth(), today.getDate() - 1);  
  var strYesterday = Utilities.formatDate(yesterday, "JST", "yyyy/MM/dd");

  //メール検索キーワードの作成
  var condition = '';
//  condition  += ' is:unread'  //未読
//  condition += ' subject:添付やで';  //件名
  condition += ' has:attachment';  //添付あり
  condition += ' after:' + strYesterday;  //今日(昨日より後)
  condition += ' from:' + 'メールアドレス'; //差出人

  //Gmailで検索
  var searchMail = GmailApp.search(condition);
  var messeges = GmailApp.getMessagesForThreads(searchMail); //検索結果を配列で取得
```


<h2>2. Gmailを条件で検索(今回は from,日付,添付あり を条件)し、検索結果を取得</h2>
メールの検索結果の配列は2次元の為、2重ループで取り出します

```js:SaveGmailAttachToDrive.gs
  var hozon_folder = DriveApp.getFolderById('GoogleDriveのFolderID');
  for(var i = 0; i < messeges.length; i++) { //検索結果を一つずつ取り出す
    for(var j = 0; j < messeges[i].length; j++) { //スレッドの場合ここを複数回実行
      var attach = messeges[i][j].getAttachments();
      var day = messeges[i][j].getDate(); //取り出したメールの日付を取得
      var strDay = Utilities.formatDate(day , "JST", "yyyy_MM_dd");
      if (day > today){ //★★メールが今日以降か再度チェック
        for(var k = 0; k < attach.length; k++){
          var filename = strDay + '_' + attach[k].getName();
          hozon_folder.createFile(attach[k]);
          var file = hozon_folder.getFilesByName(attach[k].getName())
          file.next().setName(filename);
        }
      }
    }
    messeges[i][0].markRead();
  }
```

<h3>はまったポイント</h3>
メールの検索結果はメール単位でなく、スレッド単位でした。
つまり、1.の処理で今日のメールのみ取得していると思いきや、以下画像ように、Gmailの検索結果で数字が表示される場合は、スレッド内に複数のメールが含まれており、今日より以前のメールも含まれている可能性が高い。
![Gmail検索結果スレッド](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/543473/2bed3e42-ee91-1ae5-8197-ab3eecf07500.png)

ということで、スレッドからメッセージを取り出した後も日付を判定する処理を加えてます。


<h2>3. 実行トリガー設定：時間をトリガーとして1日に1回実行する</h2>
実行日の添付ファイルをチェックするので、23～24時で毎日実行でセットしました。
トリガーの設定は以下の参照ください
[GAS ビギナーが GAS を使いこなすために知るべきこと 10 選](https://qiita.com/tanabee/items/2c51681396fe12b6a0e4#%E3%83%88%E3%83%AA%E3%82%AC%E3%83%BC)


<h2>おわり</h2>
Google Driveに保存したファイルは、Google Drive↔Synology NAS Cloud Sync↔DropBoxでDropbBox同期させ他ユーザも閲覧可能にしています。
Gmail→DropBox直接保存も考えましたが、以下消去法により今回の実装をしました。

* IFTTT：Gmailをトリガーとした連携が終了していた
* zaiper：有料範囲があるから面倒、手を出したくない
* MS Flow：実装可能が、サービスの継続が不安
* DropBox APIの利用：DropBoxでトークンを取得する際、DropBox内の既存のフォルダを対象としたAPIを利用する場合、無駄にAPI使われないかDropBox側でチェック入るっぽい([参照](https://www.dropbox.com/developers/reference/developer-guide))。 今回は既存のフォルダを使うつもりだったので無し。


初投稿でした。他にもGASで色々実装しているので、その周り寄稿できればと思います。