GmailをLINE Notifyを使用してLINEに転送する
やりたいこと
Gmailで特定のラベルがついたメールを、自動でLINEに転送して通知させたい。
きっかけ
家族と一緒に生活している中で、水道代や電気代のお知らせメールなどを私が一元管理していたのですが、重要なメールなども基本的には家族内で共有しておきたいと思い、自動でGmailに転送したら楽だなと思ったためです。
みんなのためにも「これ知らないんだけど!!」が起こりづらい環境構築をしておきましょう。
使用するもの
- Google Apps Script(GAS)
- LINE Notifiy API
- Gmail
- 上記に必要なアカウント
LINE Notify API
LINEが提供している通知をしてくれるサービス。
LINE Messaging API(いわゆるbot)も考えたのですが通知だけなのでLINE Notify APIで十分かと思います。Google App Script
通称GAS。
Microsoft OfficeでいうVBAのようなもの。
スプレッドシートやGmailなど、さまざまなGoogleサービスを連携して使用することができる。
Webスクレイピングもできる模様。
事前準備
アカウントの作成は割愛。
GmailからLINEに通知するラベルを作成
転送するメールを絞るために転送するメールにラベルをつけておきます。
今回は自分で管理するように既にラベルをつけていて家
というラベルにしています。
あと、実装方法にもよりますが転送済みのメールを再度転送させないために通知済み
ラベルも作成しておきます。
Gmailで転送したいメールのラベルに自動振り分け
転送したメールをわざわざ手動でラベルつけていたら自動化の意味がないので、自動で振り分けしてもらえるようにGmailで設定しておきます。
検索からフィルタを作るでも良いと思います。
自分は水道や電気などのメールのドメインをOR
でフィルタをかけて、ヒットしたものにはラベルをつけています。
LINE Notify APIトークンの発行
- LINE Notify APIにアクセスしてログイン。
- マイページから
トークンを発行する
からトークンの作成。
- トークン名とトークルームを選択。
今回はグループで送りたかったのでLINEでグループを作成しておいてそれを設定しました。
- 発行されたトークンを控える。
実装
GASでの実装になります。
自分もGAS自体は初めてだったのですがJavascriptはかじっていたので難しくはなかったです。
スクリプトファイルの生成はいくつかあるみたいですが、
Googleドライブから新規
> その他
> Google Apps Script
がわかりやすい気がしました。
Editorが立ち上がるのでそこに書いていきます。
今回書いたプログラム。
const HOME_LABEL = '家';
const READ_LABEL = '通知済み';
const BODY_MAX_LENGTH = 300;
function main() {
const newMessages = fetchHomeMail();
newMessages.forEach(message => {
sendLine(message);
});
}
/** LINEヘ送信 */
function sendLine(message) {
const lineToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
const payload = { 'message': message };
const options = {
"method": "post",
"headers": { "Authorization": "Bearer " + lineToken },
"payload": payload
};
UrlFetchApp.fetch("https://notify-api.line.me/api/notify", options);
}
/** メールを取得 */
function fetchHomeMail() {
const sendLabel = GmailApp.getUserLabelByName(READ_LABEL);
const searchTerms = Utilities.formatString("label:%s -label:%s", HOME_LABEL, READ_LABEL);
//取得
const fetchedThreads = GmailApp.search(searchTerms);
const fetchedMessages = GmailApp.getMessagesForThreads(fetchedThreads);
const sendMessages = [];
// 送信メッセージ配列に詰める
fetchedMessages.forEach(message => {
sendMessages.push(gmailToString(message[message.length - 1]));
});
// 通知済みラベルを追加
fetchedThreads.forEach(thread => {
thread.addLabel(sendLabel);
});
// LINE用に配列の順番を反転させる
return sendMessages.reverse();
}
/** メールの整形 */
function gmailToString(mail) {
const mailFrom = mail.getFrom();
const subject = mail.getSubject();
const body = mail.getPlainBody().slice(0, BODY_MAX_LENGTH);
return Utilities.formatString("\n%s\n\n件名:\n%s\n\n内容:\n%s", mailFrom, subject, body);
}
割と見たまんまな気がします。
sendLine(message)
の引数にlineToken
を追加するとか、fetchHomeMail()
の引数に検索条件を渡すのもありかと思います。
メール取得
メールの取得してLINEに送信するメッセージを返しています。
↓通知済みのラベルを定義
const sendLabel = GmailApp.getUserLabelByName(READ_LABEL);
↓転送したいメールの検索条件
const searchTerms = Utilities.formatString("label:%s -label:%s", HOME_LABEL, READ_LABEL);
今回は label:家 -label:通知済み
にして通知済み
になっていない家
のラベルがついたメールを検索しています。
自分はGmail上でも確認したくて未読/既読状態を保持するためにラベルを使用しましたが、未読なら未転送の判定にして、転送したメールは既読にする方法もありかなと思います。
↓メールを取得して転送メッセージに変換
//取得
const fetchedThreads = GmailApp.search(searchTerms);
const fetchedMessages = GmailApp.getMessagesForThreads(fetchedThreads);
const sendMessages = [];
// 送信メッセージ配列に詰める
fetchedMessages.forEach(message => {
sendMessages.push(gmailToString(message[message.length - 1]));
});
message[message.length - 1]
なのは、返信なども含めてスレッドになっているのですが、今回は基本お知らせメールを転送したいので最新のメッセージのみを詰めています。
全部渡したい場合はさらにforEachとか必要になると思います。
// 通知済みラベルを追加
fetchedThreads.forEach(thread => {
thread.addLabel(sendLabel);
});
// LINE用に配列の順番を反転させる
return sendMessages.reverse();
}
あとは通知済みラベルを付与して再度転送しないようにする処理と、
LINEは古いメッセージが上、新しいメッセージが下なので、配列の順序を反転させています。
LINEヘ送信
LINEヘ送信する文字列を受け取ってLINEへ送信しています。
先ほど取得したAPIトークンを渡しています。
const lineToken = PropertiesService.getScriptProperties().getProperty('LINE_TOKEN');
こちらはプロジェクトプロパティにトークンを格納していて、そこから取得しています。
プロジェクトの設定
からスクリプト プロパティで設定ができます。
別にセキュアな保管ではないのですがトークンやAPIキーはハードコーディング避けたいのでこれを活用しました。
あとはmainでメールを取得する関数を実行して、forEachでLINEに送信しています
定期実行
プログラムができたのであとは定期実行をさせるだけです。
-
トリガー
からトリガーを追加
。 - 実行したい関数を選択(今回では
main
)。 - トリガーを今回は
時間手動型
にして分ベース
、15分
おきにしました。
メールの取得頻度はこれくらいで十分かと思います。
これで15分おきにメールを取得して、未転送のメールはLINEに通知してくれるようになりました。
所感
GASを始めて触りましたがほぼJavascriptだったので簡単でした。
ネットの情報も結構転がっているので、もっと調べれば他のことにもできそう。
Discussion