GASで簡単!Gmail自動転送プログラムの作り方

GAS

はじめに

もし、あなたがGmailの自動転送を行いたいと考えている場合、GASを使ってプログラムを作成すれば、手動で行う場合よりも遥かにスムーズに転送が行えるようになります

GASを使ったGmail自動転送プログラムの設定方法を詳しく解説した本記事では、GASを使って簡単にGmailの自動転送設定ができる方法を紹介しています

また、GASの基礎知識から、実際にプログラムを作成するためのステップまでを丁寧に解説しています。

あなたもこの記事を読んで、手間のかかる手動の転送作業から解放され、よりスマートにGmailの転送を行えるようになりましょう!

本記事の対象者

  • 手動でのGmail転送を自動化したい方
  • GASに興味がある方
  • GASの使い方を学びたい方

目標成果物

特定のキーワードを本文に含むメールを受信したら、該当メールを特定の人に転送するプログラムを作成する。

GASの基礎知識

まずは、GASの基本的な使い方を押さえておきましょう。

GASの開き方

まずはスプレッドシートを開きましょう。

ツールバーの「拡張機能」→「Apps Script」を開いてください。

すると、GASのエディターが開き、以下のようなコードになっているはずです。

function myFunction() {
  
}

これが初期画面です。

ここにソースコードを記述することによって、目的の操作を自動的に行うことができるようになります。

GASは基本的にJavaScriptの文法で記述することができます。

ただし、GAS特有のクラスなどが用意されているので、そちらは個別で学習する必要があります。

よく使われるメソッド

ここでは、GAS特有のメソッドで、頻繁に使われるメソッドをざっと学習します。

openById

スプレッドシートIDから該当のスプレッドシートを開きます。

let sheet = SpreadsheetApp.openById('スプレッドシートID').getSheetByName('シート1');

getActive

スプレッドシートのデータをオブジェクト型で取得します。

該当するスプレッドシートがない場合はnullを返します。

let ss = SpreadsheetApp.getActive();

getActiveSheet

現在開いているスプレッドシートのシートデータをオブジェクト型で取得します。

let ss = SpreadsheetApp.getActive();
let sheet = ss.getActiveSheet();

getSheetByName

指定したシート名のシートを取得します。

var errorLogSheet = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("ErrorLog");

getRange

引数はgetRange(行番号, 列番号, 行数, 列数)。

指定したセル範囲をオブジェクトとして取得する。

let data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues();

getDataRange

値が存在する全てのセル範囲を取得する。

セル範囲の値を取得するgetValues()と一緒に使われることが多い。

let ss = SpreadsheetApp.getActive();
let sheet = ss.getActiveSheet();
let values = sheet.getDataRange().getValues();

appendRow

スプレッドシートの最終行に書き込む。

errorLogSheet.appendRow(['2023-05-06', 'メールの送信上限を超えています', '転送先メールアドレス']);

配列で渡したデータが左から1列ずつ書き込まれる。

これらメソッドを覚えておけば、まずまず最初の一歩としては大丈夫かと思います。

それでは、いよいよGmail自動転送のプログラムを書いていきましょう。

Gmail自動転送プログラム

まず最初に、完成版ソースコードをお見せします。

function checkAndForwardEmails() {
  var sheet = SpreadsheetApp.openById('スプレッドシートID').getSheetByName('対応表');
  var data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues();
  var errorLogSheet = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("ErrorLog");

  // 5分前の時刻を取得
  var now = new Date();
  var fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
  var unixtime = Math.floor(fiveMinutesAgo.getTime() / 1000); // ミリ秒を秒に変換し、小数点以下を切り捨てる

  var query = "in:inbox" + " -label:転送済み" + " after:" + unixtime;
  Logger.log(query)
  Logger.log(Utilities.formatDate(new Date( unixtime * 1000 ), "JST", "yyyy/MM/dd HH:mm:ss"));

  // メール検索
  var threads = GmailApp.search(query);
  var label = GmailApp.getUserLabelByName('転送済み');
  Logger.log(label);
  
  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 body = message.getPlainBody();

      // スプレッドシートのA列の文字列を含むメールを検索
      for (var k = 0; k < data.length; k++) {
        try {
          var keyword = data[k][0];
          var email = data[k][1];
          if (body.indexOf(keyword) !== -1) {
            // ログに出力
            Logger.log(keyword);
            Logger.log("Forwarded email to " + email);
            
            // // 該当するメールアドレスに転送
            // message.forward(email);
            
            var body = message.getBody();
            var subject = message.getSubject();
            var forwardedBody = "以下のメールが転送されました:<br>" + "件名: " + subject + "<br>" + "本文: " + body;
          
            GmailApp.sendEmail(email, subject, "", {htmlBody: forwardedBody});
            threads[i].addLabel(label);

            // 1分待機(Gmail APIの制限回避)
            Utilities.sleep(1000);
          }
        } catch (e) {
          errorLogSheet.appendRow([new Date(), email, e.toString()]);
        }
      }
    }
  }
}

少し難しく感じるかもしれませんが、分解していくと、行なっていることは簡単です

それでは、各箇所で何を行なっているか解説します。

ロジック整理

筆者の場合、何かプログラムを書く場合は、まずロジックを整理することから始めます

いきなりソースコードを書こうとしても、見落としや何から実装していけばいいのかわからなくなってしまうためです。

今回は、スプレッドシートに記載したキーワードと転送先メールアドレスの対応表から、キーワードを本文に含むメールを受信した際に対応するメールアドレスに転送するプログラムを作成します。

これを実現するには、以下のようなロジックを組みます。

  • 特定のキーワードと転送先メールアドレスを対応表で対応付けておく
  • 5分前から現在まででA列の特定のキーワードが本文に含まれる受信メールを取得する
  • 対応表のキーワードに対応する転送先メールアドレスに順番に転送する
  • 転送したメールには「転送済み」ラベルを貼る
  • 上記スクリプトを5分おきに実行する

GASでは新規にメールを受信したらスクリプトを実行するというトリガーの設定ができないため、5分ごとに受信メールを確認し転送するようにします

そのため、受信から転送までに最大で5分かかってしまうのですが、これが要件として許容されるのであればこの転送プログラムは有用でしょう。

処理の流れ

ロジックが決まったら、次にどのような処理の流れでソースコードを構成するかを考えます。

ここで決定した流れがそのままコードになります

今回の場合は、以下のような流れになります。

  • 対応表とエラーログ用のスプレッドシート取得
  • 5分前の時刻を取得
  • 5分前から現在までで「転送済み」というラベルが貼られていない受信メールを検索
  • 検索したメールの本文を取得
  • 本文の中に対応表で設定したキーワードを含むメールを抽出
  • 対応する転送先に抽出したメールを転送
  • 転送したメールに「転送済み」ラベルを貼る

また、転送処理の中で何らかのエラーが発生した場合にエラーログ用のシートに「時刻・転送先メールアドレス・エラーメッセージ」を追記するようにします。

これを行うことで、運用時にエラーログシートを確認すれば転送エラーが起きていないかを確認することができます。

あとはこの流れに沿って、順番にコードを書いていくだけです。

このように、一つ一つプログラムを分解していくと、難しそうなコードも簡単に見えるようになります

対応表とエラーログ用のスプレッドシート取得

まずは、スプレッドシートを取得しておきます。

これは、その後の処理でシートの中のデータなどを使うためです。

var sheet = SpreadsheetApp.openById('スプレッドシートID').getSheetByName('対応表');
var data = sheet.getRange(2, 1, sheet.getLastRow()-1, sheet.getLastColumn()).getValues();
var errorLogSheet = SpreadsheetApp.openById("スプレッドシートID").getSheetByName("ErrorLog");

「スプレッドシートID」となっている箇所はお使いのスプレッドシートのIDです。

スプレッドシートのIDは、URLを見るとわかります。

https://docs.google.com/spreadsheets/d/スプレッドシートID/edit#gid=0

上記のような形式になっているので、確認してみてください。

使っているメソッドは最初にご紹介したものばかりですね。

openById()でスプレッドシートを取得し、getSheetByName()でシートを取得しています。

また、データについてはgetRange().getValues()というお馴染みの使い方です。

5分前の時刻を取得

次に、5分前の時刻をUnixtimeで取得します。

これは、後でメール検索に使うためです。

また、Unixtimeに直しているのは、どうやらGmail検索では検索クエリとして文字列の時刻で5分前の検索ができないようだからです。Unixtimeで検索すれば正常に検索できるようです。

// 5分前の時刻を取得
var now = new Date();
var fiveMinutesAgo = new Date(now.getTime() - 5 * 60 * 1000);
var unixtime = Math.floor(fiveMinutesAgo.getTime() / 1000); // ミリ秒を秒に変換し、小数点以下を切り捨てる

メール検索

次に、受信トレイの中で5分前から現在までで「転送済み」のラベルが貼られていないメールを検索します。

var query = "in:inbox" + " -label:転送済み" + " after:" + unixtime;
Logger.log(query)
Logger.log(Utilities.formatDate(new Date( unixtime * 1000 ), "JST", "yyyy/MM/dd HH:mm:ss"));

// メール検索
var threads = GmailApp.search(query);
var label = GmailApp.getUserLabelByName('転送済み');
Logger.log(label);

転送済みのラベルを取得していますが、これは後ほど使うためです。

検索クエリについて、説明しておきます。

「in:inbox」というのは受信トレイの中で、という意味です。

また、「-label:転送済み」はハイフンをつけることで否定を使うことができるので、転送済みのラベルが貼られていないメール、という意味になります。

そして、最後の「” after:” + unixtime」は5分前から現在までで、という意味です。

全て合わせると、「受信トレイの中で、転送済みラベルの貼られていない、5分前から現在までのメール」を検索するということになります。

検索したメールの本文を取得

次に、検索して出てきた複数のメールの本文を順番に取得するコードを書いていきます。

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 body = message.getPlainBody();
    }
}

Gmail.search()の戻り値はメールのスレッドです

あくまで返ってくるのはスレッドなので、そこからメッセージの配列を取り出さなければいけません。

getMessages()でメッセージを取得することができます。

本文を抜き出す際は、getBody()またはgetPlainBody()を使います。

getBody()はHTMLで本文を取得し、getPlainBody()はプレーンテキストで本文を取得します。

本文の中に対応表で設定したキーワードを含むメールを抽出

for (var k = 0; k < data.length; k++) {
  try {
    var keyword = data[k][0];
    var email = data[k][1];
    if (body.indexOf(keyword) !== -1) {
      ...
    } catch (e) {
      errorLogSheet.appendRow([new Date(), email, e.toString()]);
    }
}

dataという変数は何だったかというと、「対応表」というシートから取得データでした。

ここから、キーワードの列と転送先メールアドレスの列のデータを取得しておきます。

var keyword = data[k][0];
var email = data[k][1];

そして、前のステップで既に本文をbodyという変数に取得することはできていますので、あとは本文の中にキーワードが含まれているかを確認するだけです。

これには、indexOf()というメソッドを使います。

indexOf()はJavaScriptの関数で、指定した文字列が含まれるかどうかを判定します。

値が-1になると、指定した文字列が含まれないという意味になります。

なので、これを否定してbody.indexOf(keyword) !== -1とすると、指定文字が含まれるという意味になります。

対応する転送先に抽出したメールを転送

var body = message.getBody();
var subject = message.getSubject();
var forwardedBody = "以下のメールが転送されました:<br>" + "件名: " + subject + "<br>" + "本文: " + body;
          
GmailApp.sendEmail(email, subject, "", {htmlBody: forwardedBody});

最初の2行は、それぞれ本文と件名を転送するメールから抜き出したものです。

3行目のforwardedBody変数には、実際に転送先に送るメールの本文を記述しています。

そして、メールの送信処理が最後の行です。

使い方は以下の通りです。

GmailApp.sendEmail(宛先, 件名, 本文, オプション)

第4引数のオプションには今回はHTMLの本文をつけていますが、他にもCCやBCC、送信元メールアドレス、添付ファイルなどを指定することができます。

転送したメールに「転送済み」ラベルを貼る

threads[i].addLabel(label);

// 1秒待機(Gmail APIの制限回避)
Utilities.sleep(1000);

処理の最後に、転送したメールにラベルを貼るようにします。

こちらは、メール検索のステップで取得しておいた「転送済み」ラベルです。

ラベルを貼る場合はスレッドに対して貼ります。

また、間をおかずに連続で転送してしまうと、Gmailの利用制限に引っかかってしまう可能性があるので、あえて1秒待ってから次の繰り返し処理を行うようにしています。

トリガーの設定

最後にトリガーの設定を行います。

GASの左側メニュー欄にある「トリガー」を選択してください。

右下に「トリガーを追加」というボタンがあるかと思います。

こちらをクリックし、条件を設定していきます。

今回の場合は、以下のように設定します。

  • 実行する関数→「checkAndForwardEmails」
  • 実行するデプロイ→「Head」
  • イベントのソースを選択→「時間手動型」
  • 時間ベースのトリガーのタイプを選択→「分ベースのタイマー」
  • 時間の間隔を選択(時間)→「5分おき」
  • エラー通知設定→「毎日通知を受け取る」

これで保存ボタンを押します。

すると、自動的に5分ごとにスクリプトを実行してくれるようになります。

もし止めたいと思った場合は、設定したトリガーをホバーし、「︙」をクリック後「トリガーを削除」を選択するとトリガーが削除されプログラムが止まります。

動作確認

さて、これで転送プログラムは完成です。

対応表に適当なキーワードと対応する転送先メールアドレスを設定し、プログラムを動かしてみましょう。

対応表は一番上の行にヘッダーを想定しているので、A列に「キーワード」、B列に「転送先メールアドレス」などとしておきましょう。

実際に転送できていれば成功です。

最後に

GASを使ったGmail自動転送プログラムの設定方法をご紹介しましたが、いかがでしたでしょうか?

GASを使えば、手動で転送を行う手間やミスを減らし、スムーズにGmailの転送を行うことができます。

また、GASは多彩な機能を持ち合わせているため、他にもさまざまな自動化プログラムを作成することができます。

今回の記事を参考に、あなたもGASを使った自動化プログラムを作成し、仕事やプライベートの時間を有効活用してみませんか?

もし、GASの開発に関する疑問点や質問がある場合は、ぜひ公式ドキュメントや開発者コミュニティに参加して、より深く理解を深めていただければと思います。

最後に、GASを使ったGmail自動転送プログラムを作成することで、よりスマートな業務効率化が実現できることを願っています。

コメント

タイトルとURLをコピーしました