GAS(Google Apps Scripts)写経 受信メールを利用してGoogle Chatスペースに投稿してみた

はじめに

昨年に続きGoogle Apps Scriptsのブログを書きます。

Google Workspaceで作業を自動化をするときに利用するGoogle Apps Scripts(以下、GAS)。慣れてしまうととても便利なツールです。インターネットや書籍で情報が多いので簡単にやりたいことや困った時の答えが見つかります。

ブログのネタを探していたとき、「社内周知をGoogle Chatスペースに転送できないか?」と思い立ち、調べてみました。すると、私がやりたかったことがすでにブログで紹介されていたので写経してみました。(その方法を参考にしてスクリプトを作成してみました。)


参考にしたブログはこちらです。

Google Apps Script(GAS)で業務効率化「Gmailで受信した特定のメールをChatスペースへ連携する」
https://you-wind.net/gws/post-305/
上記ブログを基に私がやってみた内容をご紹介します。なお、説明文作成の一部はChat GPTを活用しています。

GASの目的

社内周知はこれまでメールで行っていましたが、社員の入社タイミングに関わらず全社員が同じ情報を共有できるように、Google Chatスペースへ全社向け周知メールを転送する仕組みをGASを使って実現します。

(そもそも「過去の全社周知を共有する必要があるのか」、「社内ポータルを活用すればよいのでは?」などのご意見もあるかもしれませんが、今回はブログのネタとして取り上げているため、その点については考慮しないことにします。)

GASで実現するのに必要なもの

以下を利用します。
  • Gmailの設定
    • 全社向けメーリングリスト宛に届いた受信メールにラベルを付ける
  • メール転記用のスプレッドシートを用意する
  • GASで以下2つのスクリプトを作成する
    • メール→スプレッドシート転記用のスクリプト
    • スプレッドシート→Chatスペース投稿用のスクリプト

やってみた

いざ、トライ。

Gmailのラベル付与

Gmailの受信メールにラベルを付与する設定は説明を省略します。

スプレッドシート作成

スプレッドシートを作成して、A列~F列の1行目に以下を設定します。

A~F列
date,from,subject,message,id,result

GASでスプレッドシートを指定する方法はいくつかありますが、今回はIDを利用します。作成したスプレッドシートのURLよりIDの文字列をコピーして任意の場所に保管します。

例:
https://docs.google.com/spreadsheets/d/<ここがID>/edit

GAS作成

以下2つのスクリプトを作成します。
  1. メール→スプレッドシート転記用のスクリプト
  2. スプレッドシート→Chatスペース投稿用のスクリプト
1.メール→スプレッドシート転記用のスクリプト
GASはGmailで受信したメールから特定のラベルを検索し、新しいメールがあればその情報をスプレッドシートに転記します。

//Gmailから対象ラベルのメールデータを取得
const getMails = () => {
  const query = "label:<Gmailに設定したラベル名>";
 //Gmailで検索する対象のメールをスレッド単位で5件取得
  const start = 0;
  const end = 5;
  const threads = GmailApp.search(query, start, end);
  const messageForThreads = GmailApp.getMessagesForThreads(threads);
 //スプレッドシートに転記するデータを格納するための空の配列   let values = [];

  //転記先スプレッドシートを定義
  //スプレッドシートID
  const spreadsheet = SpreadsheetApp.openById('<スプレッドシートのID>');
  //スプレッドシート名
  const listSheet = spreadsheet.getSheetByName('<スプレッドシートのシート名>');
 //スプレッドシートの最後の行番号を取得(データを転記する位置)
  const listLastRow = listSheet.getLastRow();
//スプレッドシートの2行目から最終行まで、A~E列のデータを取得
  const ids = listSheet.getRange(2, 5, listLastRow).getValues().flat();

//forEachループ文にて、取得したスレッドを順番に読み込み //1番目のメッセージを取り出してメッセージのidがスプレッドシートのid列に存在しない場合、
//メッセージの「受信した日付」,「送信元アドレス」,「件名」,「本文」,「メッセージid」を取得
  messageForThreads.forEach(messages => {
    const message = messages[0];
 //メールのIDを取得
    const id = message.getId();
 //メールIDがスプレッドシートに存在しない場合のみ、処理を続ける
    if (!ids.includes(id)){
   //転記するために必要な情報を1つの配列 record として格納する
      const record = [
   //メールの受信日
        message.getDate(),
   //メールの送信者
        message.getFrom(),
    //メールの件名
        message.getSubject(),
     //メールの本文(文字列の上限は32767文字)
        message.getPlainBody().slice(0,32767),
    //メールのID
        message.getId()
      ];
//上記で作成したrecordvalues配列に追加
      values.push(record);
    }
  });
//取得した値をスプレッドシートへ書き込み
//values配列に転記するデータがある場合のみ、スプレッドシートに書き込みを行う
  if(values.length > 0){
//listSheet.getRange(listLastRow + 1, 1, values.length, values[0].length):最後の行の次の行からvalues配列のデータをスプレッドシートに書き込み
 //values.lengthはデータの行数、values[0].length はデータの列数
//setValues(values)で配列の内容をスプレッドシートに書き込み
    listSheet.getRange(listLastRow + 1, 1, values.length, values[0].length).setValues(values);
  }
}

2.スプレッドシート→Chatスペース投稿用のスクリプト
スプレッドシートの内容をGoogle ChatスペースにWebhookを使って投稿します。

//スプレッドシートを参照してメッセージ作成
const setMessageAndSend = () => {
 //スプレッドシートID
  const spreadsheet = SpreadsheetApp.openById('<スプレッドシートのID>');
 //スプレッドシートのシート名
  const listSheet = spreadsheet.getSheetByName('<スプレッドシートのシート名>');
 //最終行番号
  const lastRow = listSheet.getLastRow();
 //最終列番号
  const lastColumn = listSheet.getLastColumn();
 //2行目から開始する
  const startRow = 2;
 //1列目から開始する
  const startColumn = 1;
 //スプレッドシートの2行目から最終行までのデータ範囲を取得
  const dataRange = listSheet.getRange(startRow, startColumn, lastRow-1, lastColumn);
 //セルに表示されている値を配列形式で取得
  const data = dataRange.getDisplayValues();
//各行をループ。スプレッドシート6列目(F列)の値が空の場合、該当行のデータでChatスペースに投稿するメッセージを生成
  data.forEach((row, i) => {
    if (!row[5]){
   //メッセージには、送信日時、送信者、件名、本文を記載する
      let chattext = "【送信日時】\n"+row[0]+"\n"+"【送信者】\n"+row[1]+"\n"+"【件名】\n"+row[2]+"\n"+"【本文】\n"+row[3]+"\n";
   //メッセージ送信後、6列目に「TRUE」と設定してその行を処理済みとする
      const result = "TRUE";
      listSheet.getRange(i+2, 6).setValue(result);
      //chatPushMessagesでGoogleChatへメッセージを送信
      chatPushMessages(chattext);
    }
  });
}

//チャットスペース(Webhook)へ連携
//Google Chat の Webhook URLを定義
  const WEBHOOK_URL = 'https://chat.googleapis.com/v1/spaces/<スペースのWebhookIDなど>';
// Google Chat へメッセージを送信
const chatPushMessages = (chattext) => {
// chattextのデータを利用してGoogle Chatへメッセージを作成
  const message = {'text' : chattext};
// Webhook経由でGoogle Chat APIへPostリクエストでメッセージ投稿する内容を定義
  const options = {
    'payload' : JSON.stringify(message),
    'method' : 'POST',
    'contentType' : 'application/json',
    'muteHttpExceptions' : true    
  }
//UrlFetchApp.fetchを使ってGoogle ChatスペースのWebhookにHTTPリクエストを送信
//optionsに定義したPOSTメソッドでメッセージをChatに投稿
  UrlFetchApp.fetch(WEBHOOK_URL,options);
}

GASのトリガー設定

作成したGASにトリガーを設定して定期的にスクリプトを実行します。

実際の動作
Google Chatスペースより「【テスト】全社周知」を検索してご確認ください。

検索方法
Chat→チャットを新規作成→「スペースをブラウジング」より【テスト】全社周知」を検索


さいごに

今回はGASを利用してGmailの検索結果から該当するデータをスプレッドシートに記載してそのデータを基にGoogle Chatスペースに投稿してみました。Google Chatスペースの投稿にWebhookが利用できるので他にも使い方はできそうですね。それでは。

おまけ
石井さんからGASのプロパティサービスにメールID保存しといて通知済みフラグ立てとくと、スプレッドシート無しでも同じようなこと出来ると教えていただきました。
Google Workspace > Apps Script > ガイド
プロパティ サービス 
https://developers.google.com/apps-script/guides/properties?hl=ja
今度こちらで挑戦してみようと思います。


コメント

このブログの人気の投稿

ProxmoxでLet's Encryptを使用した証明書セットアップをやってみた

AIと共に「考える」エンジニアに!

ルーティングって何で必要で、何してるの?を React Routerで理解する