GAS(Google App Script)は使用用途によっては便利らしいという話で、今回はGmailを受信したらWebhook経由でDiscordに通知するようにしたという記事です。
仕様
雑に仕様を書くと、5分ごとにGASを動かして受信メールを確認します。このとき、検索機能を使って「checked」というラベルがついていないものをすべてWebhookを使ってDiscordに飛ばします。
そして、飛ばしたメールには「checked」ラベルを付与します。
簡単に言えば、新たに受信したメールをDiscordに送信するというもので、送信したかしてないかの確認は「checked」というラベルを用いるという話。
コード
function sendWebhook(message){ const url = "https://discord.com/api/webhooks/xxxxxxxxxxxTOKENxxxxxx" const webhookMsg = { "username": "Gmail自動投稿", "tts": false, "embeds": [ { "title": message.getSubject(), "description": message.getPlainBody(), "color": 0x3ea8ff, } ] } const param = { "method": "POST", "headers": { 'Content-type': "application/json" }, "payload": JSON.stringify(webhookMsg) } UrlFetchApp.fetch(url, param); } function getGmail() { // 「checked」というラベルを取得(なければ作成) var checkedLabel = GmailApp.getUserLabelByName("checked"); if (!checkedLabel) { checkedLabel = GmailApp.createLabel("checked"); } // ラベルがついていないメールスレッドを取得 var threads = GmailApp.search("-label:checked"); // スレッドを処理 for (var i = 0; i < threads.length; i++) { var thread = threads[i]; // スレッドを出力(スレッド内の最初のメールの件名と内容を取得) var message = thread.getMessages()[0]; sendWebhook(message); // 「checked」ラベルを付ける thread.addLabel(checkedLabel); } }
多少ChatGPTのちからを借りつつ書きましたが、リファレンス読みながら頑張りました。とりあえず、処理の仕組みをざっと解説していきます。
実行するのはgetGmail
関数です。
まず、GmailApp.getUserLabelByName("checked")
でラベルがあるか確認しています。なければGmailApp.createLabel
で作成しています。これは誤って誰かがラベルごと消したとき用の処理ですが、まあ、消したら全部のメールをDiscordに送りつけてくるので、これやるなら「いつ以降のメールだけ送る」という処理を追加すべきですね。
そして、GmailApp.search
を用いてcheckedラベルがついていないメールを検索し、ヒットしたメール(スレッド)をthreads
配列に突っ込んでいます。
for
ループでは、配列の中身をWebhookで送る用のsendWebhook
関数に投げています。具体的には、スレッドはメールの返信を含めた一連の流れが格納されている構造体なので、スレッドの最初のメール(message)だけを取り出して、sendWebhook
関数に投げています。
そして、sendWebhook
が完了すれば、addLabel
でそのスレッドにchecked
のラベルを付与しています。
では、sendWebhook
の中身ですが、こちらは至って単純です。DiscordでWebhookのトークン(URL)を発行して、そこにめがけてJSONを送りつけるだけです。スレッドも構造体ですが、メッセージも構造体なので、メッセージからgetSubject
でタイトルとgetPlainBody
で本文を抜き取って、それぞれDiscordのEmbedのTitleとDescriptionに格納しています。
ちなみにgetPlainBody
ではHTMLコンテツを取得しません。
他にメッセージから取り出せる内容は以下のとおりです。
関数 | 機能 |
---|---|
getCc() |
CCをカンマ区切りで取得する |
getDate() |
メッセージの日時を取得する |
getFrom() |
送信者を取得する |
getHeader(name) |
name で指定したヘッダー名の値を取得する |
getRawContent() |
メッセージの生(未加工)の情報を取得する |
getAttachments() |
メッセージのすべての添付ファイルを取得する |
ちょっとした問題点
基本的にこのメアドにメールがそんなに届くことがないのに、時折届くメールはそこそこ重要であり、サークルの人たちにも共有しないといけないのでこのスクリプトを作ったという経緯があります。メールが届いていることを把握させればいいので問題は無いのですが、このスクリプト、返信などは無視するはずです。
もし、返信も受け付けたいとか、ラベルで管理は避けたいのであれば、例えば、タイムスタンプで前回の実行からの差分だけを出力するようにしたり、スレッドの更新も受け付けれるようにしてみてください。気が向いたら改良します。