注意
本記事で実装しているコード及び、レシピ、設定等は、セキュリティリスクを許容している勉強用のサンプルです。実運用される際は、各自でセキュリティ実装を行い、自己責任でお願いします🤲
TL;DR
背景
サードパーティからのGmail送信が規制*1されていく中で、簡易的にGmail送信をできる方法を考えてみました。以下では、iOSのショートカットアプリ(旧 workflowアプリ)とGoogleAppsScript (以下、GAS)を使ってGmailでの送信を実装しています。
試行手順
-
GASとは
-
GASアカウント取得
- GASの導入を丁寧に解説していただいている記事がございましたので、本記事では割愛させていただきます。
-
プロジェクトの作成
-
コードコピー
-
サンプルコード を新規プロジェクトのコード.gsにコピーしてください。(コード名はお好きに)
-
サンプルコード を新規プロジェクトのコード.gsにコピーしてください。(コード名はお好きに)
-
環境変数設定(スクリプトのプロパティ)
-
ウェブアプリケーションの公開
-
公開範囲の設定を、リスク*3をご理解の上、 "全員(匿名ユーザを含む)"で公開にするとショートカットアプリからのHTTP(S)リクエストを受けることができます。
- 公開後、URLが表示されるので、コピーしてメモしておいてください。
- 今回は実装までの最短手順を示しているため、全体公開にしてますが、本来であれば、Restlet Client等のテストツール使用し、検証さることを推奨します。
-
認証
- 上記の公開範囲の設定の途中で以下のポップアップが表示される可能性があります。
- これは、コード内部で
MailApp.sendEmail
使用してメール送信を実装しているため表示されています。 - 本スクリプトからGoogleアカウントへメール関連の認可の可否が尋ねられるので、確認してください。*2
- 上記の公開範囲の設定の途中で以下のポップアップが表示される可能性があります。
-
-
ショートカットアプリのレシピ作成
- サンプルレシピをiPhoneのショートカットアプリで読み込んでください。
-
iOS側の環境変数設定
-
準備完了
- 以上で、サーバ/クライアントの準備は終わりました。ショートカットアプリからレシピをタップし、結果でsuccesと出ればメールが飛んでいるはずです。
解説
全体構成
- トリガーは、iPhoneのウィジェットのタップにより実行
- ショートカットアプリにて、メッセージの入力、JSONリクエストの組立を行い、 GAS側の公開URLへHTTP(S)のPOSTリクエストで実施。
- GAS側でJSONからパラメタ取得、ハッシュチェックを実施、Gmail送信apiをコール。
- Gmailからスクリプトのプロパティで設定した送信先へメールが飛ぶ
コード
- PropertiesService.getScriptProperties().getProperty
- プライベートキーをコードに書きたくなかったので、スクリプトのプロパティに変数として設定しておき、getすることでコードの公開時に消す等の煩雑な作業を無くしました。setコマンドもあるので、ちょっとしたパラメタはスプレッドシートでは、なくてもいいかもしれません。
- doPost(e)
- 本コードのメイン関数。GASのお作法としてfunction名をdoPostにすることで、POSTメソッドを受け取った際にはこの関数が呼び出される。仮引数eは、クライアントから渡されたオブジェクトを指す。doGetと記載するとGETメソッド時の処理を書ける。
- jsonParse(e,parseName)
- GASではPOSTで受け取ったオブジェクトを
Content-Type
で判断せず、一律FileUploadクラスとして扱っているため、一度まとめてparams
の箱に入れて、その後対象パラメタに絞り取得している。
- GASではPOSTで受け取ったオブジェクトを
- tokenCHK(auth)
- JSONのauthパラメタを取得、現在日時とパスフレーズを足してハッシュ化。通信経路上で盗聴したリクエストを再送し、サービスダウンを狙うリプレイ攻撃対策として、現在時間をクライアント、サーバ双方で計算するようにしました。
- toGmail(mailBody)
- JSONのmailbodyパラメタから取得した値を仮引数として受けて、
MailApp
クラスを使いメール送信を実施している。今回のサンプルでは、送信先メールアドレスやメールタイトルは、固定にしていますが、実装次第では可変にすることもできると思います。
- JSONのmailbodyパラメタから取得した値を仮引数として受けて、
ショートカットレシピ
- レシピを眺めれば日本語で書いてあるので、基本説明不要かと思いますが、サンプルコード同様に公開することを前提に書いていたのでプライベートキーについてはリマインダーを読み込むことで実現しています。
残課題
- URLとパスフレーズの2つで認証としているが、URL自体は通信経路で盗聴されていれば、誰でも取得できるものなので、認証強度が低い。
- 不正攻撃への検知の仕組みがない。
まとめ
サービスとしては車輪の再発明でしたが、個人的にJSON解析や残課題はあれど全体公開をする際の留意する点などを考えることができたという意味では、勉強にはなりました。その中で、WEBAPIで実装すべきセキュリティ観点って意外と日本語では、まとまってないなと感じました。広義ではAPIもwebサービスなので、参考にすべき資料はいっぱいあるのですがジャストでこれというものがないという印象。(ググり力不足かもしれません)
余談
- 今回クライアント側に使用した、iOSのショートカットアプリ、便利でいいのですがアプリ名が汎用的過ぎてググるのに苦労します。もっとユニークな名前を付けてほしかったです 笑
- コードを書いた時間<ショートカットのレシピ作成時間<この記事の執筆時間
- もっと記事をサクッと書けるようになりたい。。。
コード実装時に参考にさせていただいた記事
Qiita - スプレッドシートで覚えるブロックチェーン |「もしかして渡した値」「入れ替わってる!?」
Google Apps ScriptのdoPostでJSONなパラメータのPOSTリクエストを受ける
Qiita - 【GoogleAppsScript】doPost のリクエストパラメータでHTTPヘッダを取得することはできない
Google Apps Scriptをウェブアプリケーションとして公開する手順
1:workflow標準のレシピでも以前はGmail連携はできていましたが、左記の事情により現状連携ができなくなっているみたいですGoogle、個人情報へのサードパーティーアプリからのアクセス制限を強化
2:認可時に表示された(認証した)Googleアカウントを GASの送信元としてメールは送信します
3:ここでは、iOSのアプリからのアクセスを許容するため、公開範囲を全体にしています。多少のセキュリティ実装はあれど、ご自分のgmailを不特定多数がアクセスできるインターネット上に晒すことに繋がります。セキュリティリスク(不正送信、なりすまし等)のご理解の上、ご使用ください。