GASからGmailで受信している特定のメールをLINEに送る

この記事は [マイナビ Advent Calendar 2019](https://qiita.com/advent-calendar/2019/mynavi) 23日目の記事となります。

#目的
Gmailで受信している重要なメールを
Google Apps Script(GAS)とLINEのMessaging APIを使いLINEに通知されるようにすることです。

#きっかけ
Gmailの受信メールの中で早めに気付きたいメールがあり（今回の例では火災時の通知メール）
LINEに通知が届くようにすれば、便利だなと感じ作成しました。

#開発

開発工程として大きく分けて

- LINE側の設定
- GASの開発
- 本番導入（トリガーの設定）

がありますのでそれぞれ説明させていただきます。

##LINE側の設定
サーバーからLINEにメッセージを送信するために [Messaging API] (https://developers.line.biz/ja/services/messaging-api/)が必要になります。

Messaging APIで出来ることは2つあります。

- プッシュメッセージを送る
- 応答メッセージを送る<br>※対話botなど作る場合は必要

フリープランでは 2019/12 時点で一月1,000通まで送信可能となります。
https://www.linebiz.com/lineat_migration/


今回はプッシュメッセージを送ることについて記載します。

下記に従い登録していきます。※LINE Developerアカウントがない場合はアカウント登録から
https://developers.line.biz/ja/docs/messaging-api/getting-started/

###プロバイダーの作成

LINE Developerにログイン、下記の順で登録します。

1. サイドメニューのプロバイダーをクリック
2. 作成をクリック
3. プロバイダー名を入力<br>
※アプリを提供する会社、クライアント、ブランド、またはその他の組織の名前が適切
4. 作成をクリック

###チャネルの作成

作成したプロバイダのチャネル設定のタブから Messaging API をクリック、
下記が必須なので任意のものを入力していきます。

- チャネル名
- チャネル説明
- 大業種
- 小業種
- メールアドレス

規約に同意し作成をクリック、チャネルが作成されます。

###ユーザーID, アクセストークンの発行

プッシュメッセージを送るためにチャネルのユーザーID, アクセストークンが必要になります。
ユーザーIDはチャネル作成時に付与されてますので、アクセストークンの発行をここで行います。

先ほど作成したチャネルの中から Messaging API設定のタブをクリック
最下部のチャネルアクセストークンの発行をクリックで発行されます。

##GASの開発

```notification.js
function main() {
  const gmailSearchString = "dummy@co.jp"; //Gmailで検索する際の文字列を入れる

  //メール内容を取得
  const threads = GmailApp.search(gmailSearchString, 0, 1); //最新の一件
  const latestMail = GmailApp.getMessagesForThreads(threads)[0][0];
 
  const mailBody = latestMail.getPlainBody(); //メール本文
  const mailId = latestMail.getId(); //メールID
  
  // シートに同じメールがある場合は処理終わり
  if(isExistMailInSheet(mailId)){
    return;
  }
  
  const response = LINEMessagingApiPush(mailBody);
  //response.getContentText("UTF-8"); //デバッグ用、正常なら空の配列が返る
  
  writeMailInSheet(latestMail);
}

// シートにメールが存在するか
function isExistMailInSheet(mailId){
  const sqlTarget = SpreadSheetsSQL.open("(SpreadSheetのID)", "SpreadSheetのシート名");
  const data = sqlTarget.select(["メールID"]).filter('メールID = ' + mailId).result();

  if(data.length >= 1){
    return true;
  }
  
  return false;
}

// シートにデータの書き込み
function writeMailInSheet(mail){
  const sheet = SpreadsheetApp.getActive().getSheetByName("火災メール一覧");
  sheet.insertRowAfter(1); //空行の差し込み

  sheet.getRange("A2").setValue(mail.getId()); //メールID
  sheet.getRange("B2").setValue(mail.getDate()); //送信日時
  sheet.getRange("C2").setValue(mail.getPlainBody()); //メール本文
}

//LINE通知
function LINEMessagingApiPush(text) {
  const accessToken = "(LINE DevelopersのChannel Access Token)"
  const to = "(LINE DevelopersのuserID)"
  
  const url = "https://api.line.me/v2/bot/message/push";
  const headers = {
    "Content-Type" : "application/json; charset=UTF-8",
    'Authorization': 'Bearer ' + accessToken,
  };

  const postData = {
    "to" : to,
    "messages" : [
      {
        'type':'text',
        'text':text,
      }
    ]
  };

  const options = {
    "method" : "post",
    "headers" : headers,
    "payload" : JSON.stringify(postData)
  };

  return UrlFetchApp.fetch(url, options);
}
```

処理内容

1. 検索条件に合致した1件のメールを取得
2. 過去に送信済みの場合は処理終了
3. LINEにpush送信
4. スプレッドシートに送信データ書き込み

今回スプレッドシートをDBとして扱い過去に送信済みのものの管理を行いました。
2.の重複チェックについてSpreadSheetSQLのライブラリを使用させていただきました。

参考にさせていただいた記事：
https://qiita.com/kazinoue/items/1e8ed4aebfb5c3c886db
https://qiita.com/roana0229/items/fea931fcabc57f193620
https://qiita.com/n_oshiumi/items/a1a02e03093825f41e01

##本番導入（トリガーの設定）
GASのトリガーは出来るだけリアルタイムで設定したいので、1分間隔で設定しました。
<img width="400px" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60091/ff2642d1-36e3-86c5-09d0-e34510438a65.png">
こんなに短い間隔で設定できるGASすごい。

#結果
LINE DeveloperのチャネルのMessaging API設定にあるQRコードから
友達登録を行い、GASを動かします。

<img width="250px" alt="" src="https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/60091/d8e0cb44-5b7f-7c4f-8397-f0a975bd67a8.png">
これで現場に早く向かえるぞ…
火の元にはお気をつけください。