SVX日記
2023-08-21(Mon) MaveでOAuth2.0認証でGmailをPOP/SMTPする
アクセストークンでPOP/SMTPアクセスできたが、有効期限が1時間しかないので、そのためにリフレッシュトークンを使うのではないか? ということで、アレコレしてみたら、実際そうだった。
 *** oauth2.rb.1st   2023-08-18 22:02:21.385069207 +0900
 --- oauth2  2023-08-21 23:02:08.486091221 +0900
 ***************
 *** 9,17 ****
   if(ARGV.size == 0)
     warn <<USAGE
   Usage:
 !   $ ./oauth2.rb client_secret_xxxx.json > auth.html
     $ google-chrome auth.html
 !   $ ./oauth2.rb client_secret_xxxx.json 'http://localhost/?code=xxxx'
   USAGE
     exit(1)
   end
 --- 9,18 ----
   if(ARGV.size == 0)
     warn <<USAGE
   Usage:
 !   $ ./oauth2 client_secret_xxxx.json > auth.html
     $ google-chrome auth.html
 !   $ ./oauth2 client_secret_xxxx.json 'http://localhost/?code=xxxx' > refresh_token.json
 !   $ ./oauth2 client_secret_xxxx.json refresh_token.json > access_token.json
   USAGE
     exit(1)
   end
 ***************
 *** 21,26 ****
 --- 22,32 ----
         cs = JSON.parse(fh.read)
     }
   end
 + rt = nil; if((it = ARGV[1]) =~ /^refresh/)
 +   open(it) {|fh|
 +       rt = JSON.parse(fh.read)
 +   }
 + end
   
   if(ARGV.size == 1 and cs)
     auth_uri = 'https://accounts.google.com/o/oauth2/auth'
 ***************
 *** 45,50 ****
 --- 51,67 ----
     }
     auth_response = Net::HTTP.post_form(URI(auth_uri), auth_params)
     puts(auth_response.body)
 + 
 + elsif(ARGV.size == 2 and cs and rt)
 +   auth_uri = 'https://accounts.google.com/o/oauth2/token'
 +   auth_params = {
 +       client_id:      cs['installed']['client_id'],
 +       client_secret:  cs['installed']['client_secret'],
 +       refresh_token:  rt['refresh_token'],
 +       grant_type:     'refresh_token',
 +   }
 +   auth_response = Net::HTTP.post_form(URI(auth_uri), auth_params)
 +   puts(auth_response.body)
   
   else
     warn('Invalid.')$ ./oauth2 client_secret_xxxx.json refresh_token.json > access_token.json #---------------------------------------------------------------
 #
 #   メールアカウント「gmail」の設定
 #
 account = {}
 account[:NAME]              = 'Gmail'                           # アカウント名(必須)
 account[:ENABLE]            = false                             # 有効/無効(必須)
 
 account[:USER_ADDRESS]      = 'taro-yamada@gmail.com'           # メールアドレス(必須)
 
 account[:POP_SERVER]        = 'pop.gmail.com'                   # メール受信(POP)サーバ
 account[:POP_PORT]          = 995
 account[:POP_ACCOUNT]       = 'taro-yamada'                     #  受信アカウント
 account[:POP_PASSWORD]      = 'Bearer ' + `./get_access_token access_token.json`.chomp
 account[:POP_AUTHTYPE]      = :oauth2
 account[:POP_OVER_SSL]      = true                              #  SSL を使う
 account[:POP_SSL_VERIFY]    = OpenSSL::SSL::VERIFY_PEER         #  証明書を検証する
 account[:POP_SSL_CERTS]     = '/etc/pki/tls/certs/ca-bundle.crt'
 
 account[:SMTP_SERVER]       = 'smtp.gmail.com'                  # メール送信(SMTP)サーバ
 account[:SMTP_PORT]         = 587                               # 587(submission), 465(SMTP over SSL)
 account[:SMTP_ACCOUNT]      = account[:POP_ACCOUNT]
 account[:SMTP_PASSWORD]     = account[:POP_PASSWORD]
 account[:SMTP_AUTHTYPE]     = :oauth2
 account[:SMTP_STARTTLS]     = true                              #  STARTTLS を使う
 account[:SMTP_OVER_TLS]     = false                             #  TLS を使う
 account[:SMTP_TLS_VERIFY]   = OpenSSL::SSL::VERIFY_PEER         #  証明書を検証する
 account[:SMTP_TLS_CERTS]    = '/etc/pki/tls/certs/ca-bundle.crt'
 
 @configs[:ACCOUNTS] << account
 
 # 定期的にアクセストークンをリフレッシュする必要がある
 # ./oauth2 client_secret_xxxx.json refresh_token.json > access_token.jsonconfig内にファイルから読む処理が入っているので、cron等でaccess_token.jsonを更新してもMaveの起動中は更新されず、再起動する必要があるが、再起動は瞬時にできるので特段の対策はなし。そもそも、Maverickとして使う場合はmave_fetchからpopされるので問題ないし。
      def initialize(addr, port = nil, isapop = false)
        @address = addr
        @ssl_params = POP3.ssl_params
        @port = port
        @apop = isapop
 +      if(isapop == :oauth2)
 +        @apop = false
 +        @oauth2 = true
 +      end[ツッコミを入れる]