gmail を送信するために、OAuthで権限をもらう。
Gmail でSMTPを使うには、OAuth利用が必要になる。 less secure apps ( 安全性の低いアプリ)
は非推奨になった。
git clone git@github.com:takuya/ruby-oauth-google-gmail.git bundle install bundle exec ruby oauth-gmail-localhost.rb
準備
- OAuthについて
- client_secret
- access_token
- refresh_token
OAuth について
Google のアプリはOAuthで使うのが基本形になってる。
OAuthは3者間認証。
アプリは、ユーザーに許可を求める。 ユーザーはGoogleにからアプリへの許可を出していいか訊かれる ユーザーが許可するとアプリに許可が出る。
単純だけど、中央にGoogleがいるのでそこで許可設定・権限設定が可能になる。
ユーザの代理をしたいアプリを作る。
アプリ識別 client_secret/client_id スコープ https://mail.google.com
このアプリに、ユーザから許可を出す
アクセス用一時パスワード access_token 一時パスワード発行用キー refresh_token
アプリは、ユーザからAccess Tokenを貰って代理として振る舞う。Access Token はGoogle から発行される。Google はユーザの許可をとってアクセス権を付与して発行する。
Access Token は3600秒の時間制限。有効期限が切れたら、Refreshトークンを使って再取得する。再取得の際は許可済みなので、ユーザーの許可はいらない
ユーザが許可を取り消していたら、refresh token を使った再取得で失敗する。アプリはAccess Token を取れないので、ユーザの代理はできなくなる。よってアプリから権限を剥奪できる。
スコープは権限。スコープでユーザからアプリに許可する権限範囲を決める。
アプリのClient Secret の発行
Google Console にアクセスして、アプリを作る。
アプリの作成手順は、次の通り
- プロジェクトを作る
- 使いたいAPIを有効にする
- OAuth 同意画面を作る
- アプリIDを作る
アプリのIDはClient IDと呼ばれる。ここではプログラム(シェルスクリプト)からアクセスするのでデスクトップクライアントを作る。
プロジェクトを作る
名前を決めるだけでいい。スコープはOAuth時に指定できるし、後で変更できるので空欄でいい。
使いたいAPIを有効にする。
ライブラリから使いたいAPI、Gmailを指定する。指定なしでOAuthしてもメールアドレス取得ができたはず。
OAuth同意画面。
「外部」「内部」を選べる。Gsuiteの場合は内部を選んでおくと無難。
テスト設定は、テストユーザを作ってテスト設定にしておくと無難。自分だけが使いたいときは基本的にテスト。
ここの設定をミスると、同意画面表示でエラーになるので、権限(テスト・内部・外部)に注意する。
JSONの取得(アプリIDの取得)
アプリを作るとclient_secret_xxxxx.json
が作成されるのでダウンロードする。
ダウンロードは後から行えないので注意する。
あとでダウンロードしたらClient_Secretが含まれないので、意味がない
ダウンロードしそこねたら、シークレットの再生成を押してJSONを再発行する。
手作業でコピペしてもいいけど、JSONは手作業で編集するとミスが多いのでダウンロードするほうが無難。
ユーザ・ログインをしてキーをもらう
サンプルを元に、スクリプトを作っておいたので、ログインしてアプリにユーザのアクセストークンを渡す。
git clone git@github.com:takuya/ruby-oauth-google-gmail.git bundle install bundle exec ruby oauth-gmail-localhost.rb
アクセストークンは、 tokens.yml に保存する。キーはメールアドレスなので保存用にユーザ名が必要。
トークンを使ってアクセスする
たとえば、Gmail Api にアクセスしてラベル一覧を取得する。
puts "####" puts "Test Access Gmail Api as User(#{user_id})" service = Google::Apis::GmailV1::GmailService.new service.client_options.application_name = APPLICATION_NAME service.authorization = credentials result = service.list_user_labels user_id puts "Get Gmail Labels" puts "Labels:" puts "No labels found" if result.labels.empty? result.labels.each { |label| puts "- #{label.name}" }
これでラベル一覧が取得できればOK
リフレッシュトークン
トークンの更新は自動的に行われる。
refresh token を指定して、 credentials.refresh!
を呼び出せば、アクセストークンが更新されて保存される。
有効期限関係なく、何度更新しても大丈夫なので、気にせず使える。
メモ
認証・認可
この記事は、「敢えて」認証認可という用語を使っていません。認可という用語は日常語から離れてているため、イメージが湧きづらい語だからです。また認証も使っていません。認証は日常で使われすぎていて、意味範囲が広すぎて理解の妨げになるためです。
認証では、誰が誰の何を認証するかを含めて語らなくてはいけません。ログインで十分です。
認可では、誰が誰の権限を認可するかを含めて語らなくてはいけません。権限と許可で十分です。
なぜなら、Google , Google アカウント、アプリの3者しか登場人物がおらず、イメージは湧きやすいからです。日常語で意味が曖昧な熟語をあえて使う必要はないと考えます。