サクッとGAS(google app script)で指定ラベルのGmailをslackに通知

だいぶ昔に書いた、GASで指定ラベルのメールをslackに通知するスクリプトを久々使う事になったので、
更新しました。

https://gist.github.com/matsuyoro/c53d82017b2763633e5b

サクッと簡易的にできますが、このGASの設定で自動で既読になったりするのでご注意を。

---

## 用意するもの

* gmailのラベル設定

こういうの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/0cf363fa-1af0-ae92-95a4-4d406d26ad82.png)

* slackの通知先の部屋

こういうの
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/61b02c97-adee-f29d-5c58-a2b42eb20511.png)


* slackのwebhookURL
slackのwebhook URLはこちらから発行可能 →　`https://api.slack.com/apps/{あなたの Slack App ID}/incoming-webhooks`



## で、


```javascript:gmail2slack.gs
// slackのwebhook URLはこちらから発行可能 → https://api.slack.com/apps/{あなたの Slack App ID}/incoming-webhooks
var postUrl = "https://hooks.slack.com/services/xxxxxxxxxxx";

// 通知したいslackのチャネル（部屋）
var postChannel = "#n_app_review";

// 抽出元のGmailのラベル
var checkLabel = "TO_ME";

function myFunction() {
  
  // 未読の指定ラベル を検索
  var threads = GmailApp.search('is:unread label:' + checkLabel);  
  
  var count = threads.length;
  Logger.log("対象件数:" + threads.length); 
  
  for(var i = 0; i < count; i++) {
    
    var lastDate = threads[i].getLastMessageDate();
    var datetime = lastDate.getFullYear() + "/" + (lastDate.getMonth() + 1) + "/" + lastDate.getDate()
    + " " + lastDate.getHours() + ":" + lastDate.getMinutes() + ":" + lastDate.getSeconds();
    
    var messages = threads[i].getMessages();
    
    //同じ件名で、ネストされたメッセージを個別に
    if(messages.length > 0){
      for(var j = 0; j < messages.length ; j++){
        
        // 簡易的に、brタグを改行に
        var brTagStripped = messages[j].getBody().replace(/(<br>|<br \/>)/gi, '\n');
        
        // 簡易的に、HTMLメールのタグを解除
        var stripped = brTagStripped.replace(/(<([^>]+)>)/ig,"");
        
        var postMessage = " 件名：[" + threads[i].getFirstMessageSubject() + "]" + "本文```" +  stripped + "```";
        Logger.log(datetime + postMessage);

        // 対象のメールを1通を既読に。
        messages[j].markRead();
        
        //slackに通知
        sendHttpPost(postMessage);
       
      }
    }
    
    // 対象のメールを既読にする
    // NOTE: 同じ件名でネストされているものはすべて既読になります。
    // threads[i].markRead();
    
  }
}

function sendHttpPost(message, username)
{
  var jsonData =
      {
        "channel" : postChannel,
        "username" : username,
        "text" : message
      };
  var payload = JSON.stringify(jsonData);
  var options =
      {
        "method" : "post",
        "contentType" : "application/json",
        "payload" : payload
      };
  
  UrlFetchApp.fetch(postUrl, options);
}
```

その後、
このスクリプトを[GASのタイマー設定](https://script.google.com/home/triggers)で５分毎等に設定し、メールを拾って対象ラベルのものがあればSlackの指定の部屋に通知します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/71ac1f53-e569-d1d6-ed2d-a67a69ec00b0.png)



## ポイント＆課題

* ポイントは、同じ件名でやり取りしているメールなどは、１つにまとまって扱われるので、
```threads[i].markRead();```　ではなく、 ```messages[j].markRead();```で１通ずつ既読にするようにしています。


![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/37406/af1d8abd-018f-0c26-11fe-6862639cf5b9.png)

* 改善点：HTMLメールのタグ解除が簡易的な正規表現なので、ものによって崩れます。あとhtmlタグを解除する前に、改行コードも変換しておき、改行だけ残るようにしています。

---

僕は、Androidアプリの新規レビュー通知をslackに流すため、
利用しています。
slackにレビュー通知する連携アプリは結構ありますが、
無料でアカウントに紐づく**全アプリ**のレビュー通知するのは見つからず。
メールから拾う方法で対応してみました。

アプリ数が多いと、アプリIDを一個一個取得して設定するのも大変なので、
何気に便利です。

iOSは、新規レビューの通知設定（レビューの編集は通知できる）がAppStoreConnect上で見つからなかったので、
AppStoreConnectAPIで、頑張ってアプリID取得してやる方法と取ろうと思います。
（まだやっていない。。汗）