Gmailでメール受信時に、フィルタでアーカイブしてもモバイルのGmailアプリに通知させる

#きっかけ
僕はプライベートでもよくGmailを使うのですが、フィルタでの自動振り分けを多用しています。
メールマガジンのような定期的な物はラベルを付けてアーカイブし、受信トレイには人とのやり取りだけを残したい為です。
ですが、Gmailはアーカイブしたメールに関しては、未読であってもモバイルに通知してくれないのです。
（Androidなら通知来るんでしょうか…？）

プライベート利用だけであればあまり問題はありませんでした、気がついた時に読めばいいメールばかりです。
ですが仕事となるとそうは行きません。
Redmineの通知に圧迫されて、取引先の方々とのメールを追いかけるのも一苦労… なんてこともしばしば。
ですが通知してもらわないと困るので、フィルタでアーカイブするわけにはいきません…

#通知させる（させたかった）
結論から言うと（僕には）無理だったので、ここから先はどうやって妥協点まで持っていったかというお話です。
自分でどうこうする前に軽く調べてみたんですが、
「通知させたいならアーカイブしなけりゃいいじゃん」とか
「アーカイブの存在価値が分からない」とか…
**アーカイブしない**というのがゴールの情報ばかりでした。
「そもそもこの話あまり需要ないのかもしれない」と思いながら以下書いていきます。

#妥協案を考える
上記の通り、どうやらアーカイブしたものに関してはどうやっても
通知はしてくれないようだったので、妥協案を考えました。要するに、
**1. モバイルに通知が来て**
**2. 受信トレイも散らからない**
という状況にさえなれば良いのです。

そこで、**受信ボックスに入って通知された後に自動でアーカイブする**ことにしました。

#実現する
実現には**Google Apps Script (GAS)**を使用します。
ごく単純で、20行程でやりたいことは出来ています。
***※ラベルの付与は、Gmailのフィルタでやっています。***

##下準備

スクリプト作成前に、GoogleDriveにGoogle Apps Scriptを接続します。
作成するスクリプトは、ドライブに保存されることとなります。

[マイドライブ \- Google ドライブ](https://drive.google.com/drive/my-drive)

**1. 適当なディレクトリのファイルが無いところを右クリックして、[その他]-[アプリを追加]をクリックします。**
**2. 右上の検索ボックスに「script」と入力し、Enterで確定します。**
**3. 「Google Apps Script」の「接続」をクリックします。**
**4. ドライブに戻って右クリックすると、[その他] の中に [Google Apps Script] という項目が追加されているはずです。**

---
**1.**
![2017-02-22_23h18_14.png](https://qiita-image-store.s3.amazonaws.com/0/164392/b4c9ff07-3587-8309-eb9d-db1c45c9ac59.png)

---
**2.**
![aaaa.png](https://qiita-image-store.s3.amazonaws.com/0/164392/417ed7a2-e583-a8d6-7693-3afb23685701.png)

---
**3.**
![2017-02-22_23h22_13.png](https://qiita-image-store.s3.amazonaws.com/0/164392/e2bfd27d-cb42-49b5-3e85-db9d7641671c.png)

---
**4.**
![2017-02-22_23h23_47.png](https://qiita-image-store.s3.amazonaws.com/0/164392/5ef8ff45-5f49-3e50-81ad-ece4d5e13516.png)

##スクリプトの作成
上記 **4** の手順のように、適当なディレクトリで右クリックし、[その他]から[Google Apps Script]をクリックします。
まずはプロジェクトを保存します。[ファイル]から[保存]で、先程のディレクトリにスクリプトファイルが作られます。

以下はスクリプト本文です。

```java:MailArchiver
function MailArchiver() {
  // 取得するスレッド数
  var maxThreadsCount = 30;
  
  // 受信ボックス内のスレッドを取得
  var inboxThreads = GmailApp.search("in:inbox is:read -has:nouserlabels", 0, maxThreadsCount);
  Logger.log("Finded threads : " + inboxThreads.length);
  
  var archivedCount = 0;
  
  // アーカイブの処理
  for(var i = 0; i < inboxThreads.length; i++){
      GmailApp.moveThreadToArchive(inboxThreads[i]);
      Logger.log("This thread archive : " + inboxThreads[i].getFirstMessageSubject());
      archivedCount++;
  }
  
  Logger.log("Archived Threads : " + archivedCount);
}
```


ここで重要なのは、

```java:
var inboxThreads = GmailApp.search("in:inbox is:read -has:nouserlabels", 0, maxThreadsCount);
```

```java:
GmailApp.moveThreadToArchive(inboxThreads[i]);
```

この二行だけです。

###GmailApp.search(query, start, max);

```java:
inboxThreads = GmailApp.search("in:inbox is:read -has:nouserlabels", 0, maxThreadsCount);
```
この行ではスレッドの取得をしています。
Google Apps Scriptでは、様々なGoogle Appsサービスに対して多数のメソッドが用意されています。
以下でリファレンスが確認できます。

[Class GmailApp  \|  Apps Script  \|  Google Developers](https://developers.google.com/apps-script/reference/gmail/gmail-app)

**GmailApp.search** は引数に **query, start, max** を渡してやると、戻り値にGmailThread[]を返してくれます。

- **query**は検索条件
- **start**は検索を開始するスレッド番号
- **max**は一回の実行での取得最大値

検索するときは当然頭から（最新から）検索してほしいので、**start**には**0**を設定しています。
**max**には**30**を設定しているので、1回の実行で最大30件がアーカイブされることになります。

**query**には検索の条件が入ります。
この条件には、Gmailの検索バーに入力するように**検索演算子**がそのまま使えます。
今回の場合、**in:inbox is:read -has:nouserlabels**を設定していますが、これはそれぞれ

- **in:inbox** : 受信トレイにあるアイテム
- **is:read** : 既読のアイテム
- **has:nouserlabels** : ラベルの付いていないアイテム

という意味になります。
スクリプト本文では **has:nouserlabels** には **-(マイナス)** 記号がついていますが、
これは、「マイナスの次に来る条件を検索から除く」という意味です。
即ち**-has:nouserlabels**という文は、**ラベルの付いていないアイテムを除く**となり、
すべて合わせると、**「受信ボックス内で、既読で、ラベルが付いているアイテムを取得」**となります。

検索演算子については、以下で詳しく確認できます。

[Gmail で使用できる検索演算子 \- Gmail ヘルプ](https://support.google.com/mail/answer/7190?hl=ja)

###GmailApp.moveThreadToArchive(thread);

```java:
GmailApp.moveThreadToArchive(inboxThreads[i]);
```
この行では、読んで字のごとくスレッドをアーカイブしています。
GmailApp.searchで取得したGmailThreadの配列をfor文で回し、
取得したすべてをアーカイブしています。

##実行
記述が完了したら実行しましょう。
ツールバーの[▶]ボタンをクリックすると実行できます。
※ 当然ですが、実行すると未読でラベルがついているものはアーカイブされてしまいますのでご注意ください。

![2017-02-23_01h18_03.png](https://qiita-image-store.s3.amazonaws.com/0/164392/dba65882-6aa6-747e-9020-6d1f9c2d8202.png)

初回の実行には承認が必要です。
[許可を確認] → [許可] をクリックします。

![2017-02-23_01h23_37.png](https://qiita-image-store.s3.amazonaws.com/0/164392/8f29f4a0-8844-f022-b788-4bb471a48aa7.png)

![2017-02-23_01h25_08.png](https://qiita-image-store.s3.amazonaws.com/0/164392/6f76d220-5149-9181-c5a1-fbf044ed3c54.png)


承認後、もう一度[▶]ボタンで実行されます。

##ログの確認
実行時にアーカイブされたものがあれば、ログに記述されているはずです。
ログはスクリプトの編集画面で```Ctrl+Enter```を押すと開けます。
![新規キャンバス.png](https://qiita-image-store.s3.amazonaws.com/0/164392/5572d34a-dbd0-5112-3401-592f6fef227a.png)

##トリガーの追加
現時点では、毎回手動実行しないといけないので全く意味がありません。
トリガーを設定して、自動で実行するようにします。
**1. ツールバーの時計のマークをクリックします。**
**2. 「トリガーが設定されていません。今すぐ追加するには～」をクリックします。**
**3. タイマーを「分タイマー」「1分ごと」に設定し、保存します。**

**1.**
![2017-02-23_01h40_19.png](https://qiita-image-store.s3.amazonaws.com/0/164392/46453c71-e13a-2f45-391f-d49d92f21c6d.png)

---

**2.**
![2017-02-23_01h42_55.png](https://qiita-image-store.s3.amazonaws.com/0/164392/3d192a57-59fa-212c-35c1-fe75020ffd73.png)

---

**3.**
![2017-02-23_01h43_18.png](https://qiita-image-store.s3.amazonaws.com/0/164392/e814316a-8f71-9af7-d9ef-9cd900bedc2f.png)

![2017-02-23_01h43_25.png](https://qiita-image-store.s3.amazonaws.com/0/164392/4c6e8e66-32a8-38ea-c907-aca345402ac1.png)

これで1分ごとに、既読されたラベル付きメールが、随時自動でアーカイブされます。

#まとめ
手順を一つずつ追っていったので割と長くなってしまいましたが、以上です。
ちなみに「通知来たら未読でもアーカイブすればいいじゃん！」と思われた方もいるかもしれませんが、
モバイルへ通知後、未読の状態でアーカイブしても**バッヂは消えてしまう**のです…
通知が来たらすぐに確認する方は、未読でもアーカイブしてもいいかもしれませんね。

回りくどい手法ですし「手動でアーカイブすればいいじゃん」って思う方もいるかもしれませんが、
僕にとっては自動でアーカイブしてくれるのは意味のあることなので、一先ず満足しています。

「もっと簡単にできるよ！」という方がいらっしゃいましたら、ぜひご教示ください…