GASとGmailとの連携方法

# はじめに
この記事は「[Ateam LifeDesign Advent Calendar 2023](https://qiita.com/advent-calendar/2023/ateam-life-design)」で完走賞を狙って25記事書いているうちの8日目の記事です。今年も完走目指して頑張るぞ！

今日はGASとGmailの連携についてみていきます。

# GASからGmailを操作する方法
GASには、[GmailAppクラス](https://developers.google.com/apps-script/reference/gmail/gmail-app?hl=ja)や[GmailMessagクラス](https://developers.google.com/apps-script/reference/gmail/gmail-message?hl=ja)が用意されており、これらクラスを使ってGmailの操作を簡単に行うことが出来ます。様々な操作ができますが、いくつかよく使うものを紹介しておきます。

## GmailAppクラス

| メソッド名 | 内容 |
|-|-|
|getInboxThreads()| 受信トレイのスレッドを取得します。|
|search(query)| 指定したクエリに一致するメールを検索します。|
|sendEmail(recipient, subject, body)| メールを送信します。|
|getUserLabelByName(name)| 指定した名前のラベルを取得します。|
|createLabel(name)| 新しいラベルを作成します。|


## GmailMessageクラス

| メソッド名 | 内容 |
|-|-|
|getSubject()| メールの件名を取得します。|
|getPlainBody()| メールの本文を取得します（HTMLタグを除いたテキスト）。|
|getAttachments()| メールに添付されたファイルを取得します。|
|markRead()| メールを既読にマークします。|
|markUnread()| メールを未読にマークします。|


# 作るもの
指定したキーワードを含む受信トレイ内のメールを検索し、その情報（件名、送信者、本文）をGoogle Spreadsheetの新しいシートに記入するというGASを作っていきます。一体何に使うものなのかは自分でもよくわからないけどサンプルということで。

# GASを書いていく

```javascript
  const keyword = 'example'; // 検索するキーワード
  var threads = GmailApp.search('in:inbox ' + keyword); // インボックス内でキーワードを含むメールを検索
```

なんとこれだけでGmailから特定のキーワードが含まれるメールのスレッドを取得してくることが可能です。該当のスレッドのサイズが大きすぎて処理できない場合はエラーが返ってくるので、スレッドサイズが不明で、非常に大きくなる可能性がある場合は、`search(query, start, max)`のようなかたちでページング付きで呼び出します。

```javascript
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('EmailData');
  if (!sheet) {
    sheet = spreadsheet.insertSheet('EmailData');
  }

  sheet.clear(); // シートをクリア
```

書き込むためのシートを用意します。今回は「EmailData」という名前のシートに書き込むことにします。シート名を指定してシートを取得しますがもしなかった場合には`insertSheet`を使って新たに「EmailData」というシートを準備します。また`clear()`を実行して過去に書き込まれた内容は一度消えるようにしておきます。

```javascript
  // ヘッダーを設定
  var headers = ['Subject', 'From', 'Body'];
  sheet.appendRow(headers);
```

１行目にヘッダー情報を記入しておきます。`appendRow`を使うことで配列をそのまま行に出力します。

```javascript
  // メールを取得してスプレッドシートに記入
  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    for (var j = 0; j < messages.length; j++) {
      var message = messages[j];
      var subject = message.getSubject();
      var sender = message.getFrom();
      var body = message.getPlainBody(); // HTMLタグを除いたテキストの本文

      var row = [subject, sender, body];
      sheet.appendRow(row);
    }
  }
```

先程取得したメールのスレッドをループで回しながらメッセージ情報を取得していきます。メッセージ内のタイトル、送信者、本文をヘッダー同様に`appendRow`を使い１行ずつ書き込んでいきます。

# 完成品がこちら

## GASのコード

```javascript
function searchAndWriteToSheet() {
  const keyword = 'example'; // 検索するキーワード
  var threads = GmailApp.search('in:inbox ' + keyword); // インボックス内でキーワードを含むメールを検索
  var spreadsheet = SpreadsheetApp.getActiveSpreadsheet();
  var sheet = spreadsheet.getSheetByName('EmailData');
  if (!sheet) {
    sheet = spreadsheet.insertSheet('EmailData');
  }

  sheet.clear(); // シートをクリア

  // ヘッダーを設定
  var headers = ['Subject', 'From', 'Body'];
  sheet.appendRow(headers);

  // メールを取得してスプレッドシートに記入
  for (var i = 0; i < threads.length; i++) {
    var messages = threads[i].getMessages();
    for (var j = 0; j < messages.length; j++) {
      var message = messages[j];
      var subject = message.getSubject();
      var sender = message.getFrom();
      var body = message.getPlainBody(); // HTMLタグを除いたテキストの本文

      var row = [subject, sender, body];
      sheet.appendRow(row);
    }
  }
}
```

## 実行結果

メールボックスの中から「example」というキーワードを含むスレッドを取得してスプレッドシートに記載することができました。

![スクリーンショット 2023-11-26 21.38.41.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/200812/16c8becd-905f-1bab-d356-489a0e125e02.png)


# おまけ
実際作ってみたものの、今回のサンプルの実用性があまりに低かったのでもう一つおまけで作ってみました。Gmailから未読メールの件数を取得して[IncomingWebhookを使ってSlackを送信](https://qiita.com/kakakaori830/private/f3c1a1539b875d933b7a)の方法でSlackに通知するサンプルです。ちょっとは活用イメージが湧きましたか？？
```javascript
function getUnreadEmailsCount() {
  const unreadCount = GmailApp.getInboxUnreadCount() // 未読メールの件数を取得

  if (unreadCount > 0) {
    sendToSlack('未読メールが' + unreadCount + '件あります');
  }
}

function sendToSlack(message) {
  const url = PropertiesService.getScriptProperties().getProperty("TEST_URL");

  const payload = {
      "text": message,
  };
 
  const options = {
      "method" : "post",
      "contentType" : "application/json",
      "payload" : JSON.stringify(payload)
  };
 
  // HTTP リクエストでPOST送信
  UrlFetchApp.fetch(url, options);
}
```

# 最後に
今日はGASとGmailとの連携についてまとめました。今回書いた以外でも例えば

- 自動返信メールの作成
    - 特定の条件に一致するメールに自動で返信する機能。
- カスタムレポートの自動作成
    - メールから情報を抽出し、週次や月次のレポートを作成する機能。
- メールの内容に基づくタスクの作成
    - メールの内容からタスクやリマインダーを自動生成する機能。
- メールのスケジュール配信
    - 特定の日時にメールを予約配信する機能。
- 特定の添付ファイルを含むメールの検知
    - 特定の拡張子を持つ添付ファイルを含むメールを検知して通知する機能。

なども実装することが可能です。いろいろ活用できそうですね！

明日はGASをつかってGoogleドライブを操作する方法をみていきます。