Google Apps Scriptで、Gmailで受信したメールをLINEに転送する

# この記事の内容でできること

タイトルの通りですが、Google Apps ScriptでGmailで受信したメールをLINEに転送する方法についてまとめています。

- 指定した送信元からのメールを、LINEに転送する
- 画像ファイル（jpegかpng）が添付されている場合は、画像ファイルも転送する
- この記事のコードでは、特定の送信元から送られたメールを転送しています。転送済みかどうかを識別するために、対象のメールを取得する際に未読（is:unread）であることを条件に指定し、処理後に既読にしています

# LINE通知のためのトークンID発行

- https://notify-bot.line.me/ja/
にアクセスする

- 右上の「ログイン」からLINEアカウントでログイン

- 右上のユーザー名をクリックして、「マイページ」を開く

- 「アクセストークンの発行(開発者向け)」の「トークンを発行する」ボタンから、トークン名と通知先を指定すると、トークンIDを発行できます。

（注）トークンIDは発行時のみ表示されて、閉じてしまうと再表示できないので、表示されたトークンIDは控えておいてください。

# Google Apps Scriptのコード

Google Apps Scriptを新規作成して、コードに以下の内容を張り付けて下さい。

```js
// LINEへのメッセージ送信
function sendLine(lineToken, msg){
  var payload = {'message' :   msg};
  var options ={
    "method"  : "post",
    "payload" : payload,
    "headers" : {"Authorization" : "Bearer "+ lineToken}  
  };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}

// LINEへのメッセージ送信（添付ファイル付き）
function sendLineWithFile(lineToken, msg, file){
  var payload = {
    'message' :   msg,
    'imageFile': file
  };
  var options ={
    "method"  : "post",
    "payload" : payload,
    "headers" : {"Authorization" : "Bearer "+ lineToken}
  };
  UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}

// GmailのメッセージをLINEに転送
function forwardMessage(lineToken, mailMsg) {
  var message = "\n[件名]" + mailMsg.getSubject()
    + "\n\n[本文]" + mailMsg.getBody();
  Logger.log(message);

  let atchs = mailMsg.getAttachments();
  if (atchs.length > 0) {
    var contentType = atchs[0].getContentType();

    if (contentType == "image/jpeg" || contentType == "image/png") {
      Logger.log("send line with image file");
      file = atchs[0].getAs(contentType);
      sendLineWithFile(lineToken, message, file);
    } else {
      sendLine(lineToken, message);
    }
  } else {
    sendLine(lineToken, message);
  }
}

// Gmailから指定された条件でメールを検索して、対象のメールを転送
function forward(lineToken, mailConds) {
  var myThreads = GmailApp.search(mailConds);

  for(var i=0; i<myThreads.length; i++){
    var myMsgs = GmailApp.getMessagesForThread(myThreads[i]);

    for (var j=0; j<myMsgs.length; j++) {
      forwardMessage(lineToken, myMsgs[j]);
    }

    myThreads[i].markRead();
  }
}

// メールの転送
function main() {
  var lineToken = "xxxxxxxxxxxxxxxxxxxxxxx"; // LINEトークンID
  var mailConds = '(from:hoge@gmail.com is:unread)';

  forward(lineToken, mailConds);
}
```

### 修正が必要な個所

```js
var lineToken = "xxxxxxxxxxxxxxxxxxxxxxx"; // LINEトークンID
```
この部分に、発行したLINEのトークンIDを指定してください。

```js
var mailConds = '(from:hoge@gmail.com is:unread)';
```
転送するメールの条件を指定してください。
このコードでは、「hoge@gmail.com」から送られてきたメール、を条件にしています。
この記事のコードのロジックでは、転送済みかどうかを識別するために「既読かどうか」で識別しています。そのため、「is:unread」はつけて下さい。
転送後に、

```js
myThreads[i].markRead();
```
で既読にしています。

### 実行方法
main関数を実行して下さい。
トリガーでmain関数を指定すれば、定期的に自動実行させることができます。

転送したいメールの種類が複数ある（対象のメールの条件や転送先のLINEグループが違う）場合は、main関数と同じような関数を作れば、プロジェクトごと複製しなくても複数種類のメールの転送を実現できます。

# 制限事項（注意事項）

- jpeg, png以外の添付ファイルは転送できません（LINEのAPIが対応していない）
- 複数の画像ファイルが添付されていても、1つのファイルしか転送できません（私個人の用途ではファイル1つ転送できれば十分だったので。。必要なら修正してください）
- jpegファイルの転送は動作確認済みですが、pngは動作未確認です（私個人の用途では。。以下略）
- 転送済みかどうかを識別するために「既読かどうか」で判断しています。そのため、転送前に既読にしてしまうと、転送されません。
    - 私の場合は、Gmail側のフィルタで、対象のメールを受信時にアーカイブする（受信トレイをスキップする）ことで、先に既読にしてしまうことを避けています
    - 転送済みを表すラベルを作って、それで処理するという方法もありだと思います（メール検索時にはそのラベルがついていない、ということを条件にして、転送後にラベルを付ける）。