【GAS】GoogleアラートメールをLINEに自動通知する

GASDate,forEach,getMessage,getPlainBody,gmail,GmailApp.search,join,match,Parser,push,UrlFetchApp,トリガー

Google Apps Scriptを使ってGoogleアラートメールの内容を定期的にLINEに通知するボットを作成します。

必要な作業

実行するには下記の3つの作業を行う必要があります。

  • Googleアラートメールの内容を取得するプログラムを記述する
  • LINE Notify APIを使ってLINEに通知するプログラムを記述する
  • 定期的にGASプログラムを実行する

それぞれの記述、作業方法を解説します。

Googleアラートメールの内容を取得するプログラムを記述する

前準備:Parserライブラリの導入

今回のスクリプトではParserライブラリを使用します。下記で紹介するスクリプトを実行するにはParserライブラリのインストールが必要になるので、事前にParserライブラリを導入してください。

エディタ左部の「ライブラリ」の「+」ボタンをクリック

ポップアップの「スクリプトID」欄にParserライブラリのIDを入力し「検索」をクリック

*2022年7月現在は下記のIDでした。アップデートで変更になるので最新のIDを調べて入力してみてください。

1Mc8BthYthXx6CoIz90-JiSzSafVnT6U3t0z_W3hLTAX5ek4w0G_EIrNw

Parserライブラリであることを確認し、「追加」ボタンをクリック

スクリプト全体像

function getGoogleAlert(){

  //Google AlertのURLを格納する配列
  let array = [];

  //「googlealerts-noreply@google.com」からの受信を検索条件に指定して抽出命令 
  let query = 'from:googlealerts-noreply@google.com';

  //Gmailの履歴からマッチするメールを一覧化、いったん最新から3件のメールを取得
  let threads = GmailApp.search(query,0,3);

  //一覧化したメールの件数分繰り返し 
  threads.forEach(function(thread) {

    // スレッド内のメール一覧を取得
    let messages = thread.getMessages();

    // メールを一つずつ取り出す
    messages.forEach(function(message) {

      // メール本文の取得
      let plainBody = message.getPlainBody();
      //リダイレクト先のURLを取得 ⇒ Parserライブラリのiterateメソッドを使うことで、単一のメール内に含まれるURLで配列を作成
      let urls =Parser.data(plainBody).from('<https://www.google.com/url?rct=j&sa=t&url=').to('&ct=ga').iterate();

      for(let url of urls){  // URLごとに反復処理
        if(!url.match('%')){  //デコードが必要なURLは処理しない
          array.push(url); //受信日とURLの組を配列に追加
        }
      }
    });
  });

  console.log(array);

}
実行結果

[ 'https://www.corporate-legal.jp/matomes/4927’, 'https://exawizards.com/archives/20404’, 'https://www.realmadrid.com/ja/news/2022/08/15/fitness-and-ball-work-to-start-the-week’, 'https://jp.reuters.com/article/idJP00093500_20220815_05720220815’, 'https://www.famitsu.com/news/prtimes/202208/15272220.html’, 'https://portalcripto.com.br/ja/zkspace-lanca-hoje-a-colecao-nft-james-rodriguez-zurda/’, 'https://entabe.jp/50224/morinaga-releases-biscuits-and-cookies-in-goddess-package’, 'https://www.walkerplus.com/article/1097307/’, 'https://korepo.com/archives/1164307’, 'https://news.livedoor.com/article/detail/22673432/’, 'https://apple-geeks.com/safari-cookie-iphone-mac-85741’, 'https://www.kodomo.or.jp/information/20220813_1884.php’, 'https://www.wowkorea.jp/news/enter/2022/0813/10359818.html’, 'https://www.appbank.net/2022/08/13/casual-food/2279015.php’, 'https://www.arqtricolor.com/ultimas/time-japones-contrata-por-emprestimo-atacante-formado-na-base-do-sao-paulo/’ ]

条件指定をしてメールをスレッド化

  //「googlealerts-noreply@google.com」からの受信を検索条件に指定して抽出命令 
  let query = 'from:googlealerts-noreply@google.com';

  //Gmailの履歴からマッチするメールを一覧化、いったん最新から3件のメールを取得
  let threads = GmailApp.search(query,0,3);

GmailApp.search(query [,start ,num])

  • query(必須):検索条件 ※検索窓で検索する時と同様に指定が可能
  • start(任意):インデックス開始位置(「0」または指定しなければ最新から取得)
  • num(任意):スレッドの最大取得数
  • 戻り値:検索条件にマッチするメールのスレッド(GmailThreadオブジェクト)の配列

GmailApp.searchメソッド(query) で検索条件を指定してメールをスレッド化(検索条件で抽出)してくれます。上記のスクリプトの場合、queryfrom:googlealerts-noreply@google.comを指定しているので、「googlealerts-noreply@google.comから送られたメール」という条件ということになります。

これはメールボックスで下記のように検索しているのと同じ状況です。

ちなみに現在は「Cookie」という条件でGoogleアラートメールが飛ぶように設定してあります。

また、開始位置とスレッド件数にも引数を指定しているので、「上記のスレッドのうち最新3件」という指定をしました。

スレッド・メール件数だけ本文の反復処理

  //一覧化したメールの件数分繰り返し 
  threads.forEach(function(thread) {

    // スレッド内のメール一覧を取得
    let messages = thread.getMessages();

    // メールを一つずつ取り出す
    messages.forEach(function(message) {

      // メール本文の取得
      let plainBody = message.getPlainBody();

各メール本文のURLを取得したいのでスレッド・メールの件数分反復処理を実行します。

GmailThread.getMessages()

  • 戻り値:GmailThreadに含まれるメッセージの配列

GmailMessage.getPlainBody()

  • 戻り値:GmailMessageに含まれる本文(HTMLは含まずテキストのみを取得)

アラートで通知されている記事のURLのみを取得して配列化

      //リダイレクト先のURLを取得 ⇒ Parserライブラリのiterateメソッドを使うことで、単一のメール内に含まれるURLで配列を作成
      let urls = Parser.data(plainBody).from('<https://www.google.com/url?rct=j&sa=t&url=').to('&ct=ga').iterate();

getPlainBodyメソッドで取得した値はメール本文の文字列です。今回はGoogleアラートメールですが、メールの内容によってこの部分の処理はかなり変わってくるので、メールの内容と実行ログを突き合わせて情報を取得するための記述を見定めてください。

最新メールの内容と実行ログの一部に対応する箇所とURLの記述が確認できたので、この個所の記述内容を確認して抽出処理を検討していきます。

条件指定したメールと実行ログの一部、記事とリンクがそれぞれ対応している

挿入されているリンク部分の記述を確認してみると、処理の対象にできそうな規則性がありそうです。今回は記事のリンクである https://~xxx.com/xxx を取得したいのでリンクを挟んでい<https://www.google.com/url?rct=j&sa=t&url= &ct=ga を条件指定できそうです。

//記事①
<https://www.google.com/url?rct=j&sa=t&url=https://www.corporate-legal.jp/matomes/4927&ct=ga&cd=CAEYACoTMzIxNjkxMTAwMzYzNTkxNjU0ODIcMjVlOTc5NDgwMDAzNWNmMzpjby5qcDpqYTpKUA&usg=AOvVaw3E0CfYx3mqe5utxJB7voUE>

//記事②
<https://www.google.com/url?rct=j&sa=t&url=https://exawizards.com/archives/20404&ct=ga&cd=CAEYASoTMzIxNjkxMTAwMzYzNTkxNjU0ODIcMjVlOTc5NDgwMDAzNWNmMzpjby5qcDpqYTpKUA&usg=AOvVaw2mgqxcYheXF5vHPWB3KNEC>

//記事③
<https://www.google.com/url?rct=j&sa=t&url=https://www.realmadrid.com/ja/news/2022/08/15/fitness-and-ball-work-to-start-the-week&ct=ga&cd=CAEYAioTMzIxNjkxMTAwMzYzNTkxNjU0ODIcMjVlOTc5NDgwMDAzNWNmMzpjby5qcDpqYTpKUA&usg=AOvVaw0JTJwrVtcbK3pPu66TheFq>

matchメソッド等でも同様の処理はできますが、今回のような「○○という記述に挟まれた文字列を取得する」という条件を指定する場合はParserライブラリが便利です。

Parser.data(plainBody).from(…).to(…).iterate()の記述で、plainBody内で条件に該当する文字列を要素とした配列を取得できました。

これでGoogleアラートメール取得の処理は大丈夫そうですね。

LINE Notify APIを使ってLINEに通知するプログラムを記述する

LINE Notifyを使うには通知を送るトークルーム専用のトークンを発行しなければなりません。トークン発行から通知を送る基本的な方法については下記の記事でご紹介しています。

通知用のトークルーム(グループ)を作成しトークンを発行

「Googleアラート」というグループを作成しトークンを発行しました。ここのグループ名やトークン名はなんでも問題ありません。

Gmailで取得した情報をLINEメッセージで通知を送る

自動トリガーを設定する前に先ほど取得したメールの情報をLINEに通知してみます。

Gmai情報を取得した関数 getGoogleAlert() で最後に作成した記事URLの配列 array を返り値として設定しておき、LINE通知用の関数 notifyLine() を新たに作成して関数内で呼び出します。

function getGoogleAlert(){
 ・・・

  return array;

}

function notifyLine(){

  let array = getGoogleAlert();

  //通知用に5つのURLごとの配列に格納し直す
  let notifyUrls = [];

  for(let i = 0; 0 < array.length; i){
    notifyUrls.push(array.splice(i, 5));
  }

  const token = '★★★発行したトークン★★★';
  let lineNotifyApi = 'https://notify-api.line.me/api/notify';

  for(let notify of notifyUrls){

    let message = '\n' + notify.join('\n');

    const options =
    {
        "method"  : "post",
        "payload" : {"message": message},
        "headers" : {"Authorization":"Bearer " + token}
    };

    UrlFetchApp.fetch(lineNotifyApi, options);

  }
}

記述内容はこちらの記事の解説とほぼ同様ですが、LINEではメッセージ1つにつき5つのURLまでしかカード表示されないため、下記のように splitメソッドを使って5つのURLごとの二次元配列に変形してそのURLの塊ごとにAPIを呼び出すようにしています。通知を送るだけであれば必須の処理ではありません。

  let array = getGoogleAlert();

  //通知用に5つのURLごとの配列に格納し直す
  let notifyUrls = [];

  for(let i = 0; 0 < array.length; i){
    notifyUrls.push(array.splice(i, 5));
  }

URLを5個ずつ送ることができました。

トリガーをセットして定期的にメール処理のGASプログラムを実行する

最後にこのスクリプトを最新で受信したメールを通知するように変更&定期実行されるようにトリガーを設定します。

メール処理するスクリプトを用意

最新で受信したGoogleアラートメールだけを処理するようにスクリプトに変更を加えます。

変更前のスクリプト

  //「googlealerts-noreply@google.com」からの受信を検索条件に指定して抽出命令 
  let query = 'from:googlealerts-noreply@google.com';

  //Gmailの履歴からマッチするメールを一覧化、いったん最新から3件のメールを取得
  let threads = GmailApp.search(query,0,3);

変更後のスクリプト

  //現在時刻を取得
  let today = new Date();
  //現在時刻と別参照で同じ時刻のDateオブジェクトを作成
  let yesterday = new Date(today);
    yesterday.setDate(today.getDate()-1);

  //「googlealerts-noreply@google.com」からの昨日~本日にかけての受信を検索条件に指定して抽出命令 
  let query = `from:(googlealerts-noreply@google.com) after:${yesterday} before:${today}`;

  //Gmailの履歴からマッチするメールをスレッド化
  let threads = GmailApp.search(query);

メールの処理が定期実行されるようにトリガーを設定

エディタ画面の左メニューバーからトリガーを設定します。

「トリガーを追加」をクリック

実行したい関数を選択し、「時間主導型」で「日付ベースのタイマー」より時間を設定すれば指定した時間帯にLINE通知を実行してくれます。Googleアラートは毎日7時くらいに受信するので、「8時~9時」を選択しました。

これで作業は終了です。

トリガーの実行結果

次の日以降、無事にGoogleアラートの内容がLINEに通知されるようになりました。

まとめ

GASを使ってGoogleアラートの通知をLINEに送る方法をご紹介しました。

この記事を書いた人

てつお
広告代理店出身、事業会社でWebマーケティングや開発の仕事をしている26歳です。プロフィール詳細はこちら
■Google広告認定資格|Google アナリティクス個人認定資格(GAIQ)|TOEIC920点