ASi

Gmail を API で読む

Google API OAuth 2.0 クライアントのIDを得る

  • https://console.cloud.google.com/apis/library/gmail.googleapis.comgoogle アカウントでログインしてアクセス。このアカウントはクライアントのアカウントであって、読みたいメールのアカウントではない。
  • "有効にする" 押下。
  • プロジエクトを選択してください。と出る場合は、"作成" 押下。しばらく待つ。
  • 改めて、"有効にする" 押下。

"認証情報を作成" 押下

  • 使用するAPI として Gmail API
  • API を呼び出す場所 として、その他のUI (WindowsCLI ツールなど)
  • アクセスするデータの種類 として ユーザデータ
  • OAuth クライアント ID を作成 押下
  • ユーザに表示するサービス名入力
  • 次へ
  • これで完了。client_id, client_secret の書かれた JSONのダウンロードはここでも後でも可。

特定のGmailアカウントへのアクセスをクライアントに許可する

  • 作成したクライアントIDで 特定のGmailアカウントのauthを求める URLを作成。

https://accounts.google.com/o/oauth2/auth?client_id=NNNNNNNNNNNN-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&redirect_uri=urn:ietf:wg:oauth:2.0:oob&scope=https://www.googleapis.com/auth/gmail.readonly&response_type=code

scope はやりたい事で変わる。ここでは読むだけを指定。

  • Webブラウザでアクセスし、アクセスしたいGmailアカウントでログインし、許可する。code を得る

4/xxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__-_xxxxxxx

  • code を使って refresh_token を得る

この時点で access_token も得られるが、すぐ expire する。基本的には refresh_token を使うことになる。

curl https://accounts.google.com/o/oauth2/token -d "code=4/xxxxxx_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx__-_xxxxxxx&client_id=NNNNNNNNNNNN-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com&client_secret=xxxxxxxxxxxxxxxxxxxxxxxx&redirect_uri=urn:ietf:wg:oauth:2.0:oob&grant_type=authorization_code"

{
  "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "expires_in": 3600,
"refresh_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "scope": "https://www.googleapis.com/auth/gmail.readonly",
  "token_type": "Bearer"
}

refresh して access_token を得る

(
CLIENT_ID=NNNNNNNNNNNN-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com
CLIENT_SECRET=xxxxxxxxxxxxxxxxxxxxxxxx
REFRESH_TOKEN=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

curl -d "refresh_token=$REFRESH_TOKEN" -d "client_id=$CLIENT_ID" -d "client_secret=$CLIENT_SECRET" -d "grant_type=refresh_token" https://www.googleapis.com/oauth2/v4/token
)

{
  "access_token": "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx",
  "expires_in": 3600,
  "scope": "https://www.googleapis.com/auth/gmail.readonly",
  "token_type": "Bearer"
}

得た access_token を使って API 発行

curl -H 'Authorization: Bearer xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' https://www.googleapis.com/gmail/v1/users/someone@gmail.com/messages

in PHP & HTTP

public static function getGmailAccessToken(){
    $CLIENT_ID = 'NNNNNNNNNNNN-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx.apps.googleusercontent.com';
    $CLIENT_SECRET = 'xxxxxxxxxxxxxxxxxxxxxxxx';
    $REFRESH_TOKEN = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';
    $headers = [
    ];
    $post = [
        "client_id" => $CLIENT_ID,
        "client_secret" => $CLIENT_SECRET,
        "grant_type" => "refresh_token",
        "refresh_token" => $REFRESH_TOKEN
    ];
    $http = new HttpSocket();
    $response = $http->post(
        'https://www.googleapis.com/oauth2/v4/token',
        $post, ['header' => $headers]
    );
    return json_decode($response['body'], true)['access_token'];
}

/**
 * @return array 
 *  <pre>
 *  {
 *   "messages": [
 *     {
 *       "id": "xxxxxxxxxxxxxxxx",
 *       "threadId": "xxxxxxxxxxxxxxxx"
 *     },
 *   ],
 *   ...
 *   "resultSizeEstimate": 8
 *  }
 *  </pre>
 */
public static function getGmailList(){
    $headers = [
        'Authorization' => 'Bearer '.static::getGmailAccessToken()
    ];
    $http = new HttpSocket();
    $response = $http->get(
        'https://www.googleapis.com/gmail/v1/users/someone@gmail.com/messages',
        null, ['header' => $headers]
        );
    return json_decode($response['body'], true);
}

public static function getGmailMessage($id){
    $headers = [
        'Authorization' => 'Bearer '.static::getGmailAccessToken()
    ];
    $http = new HttpSocket();
    $response = $http->get(
        'https://www.googleapis.com/gmail/v1/users/someone@gmail.com/messages/'.$id,
        null, ['header' => $headers]
        );
    //CakeLog::debug(print_r($response['body'],true));
    return json_decode($response['body'], true);
}

/**
 * @param $entries getGmailList()['messages'] を与えられる
 */
public static function readGmails($entries){
    foreach ($entries as $entry){
        $mail = static::getGmailMessage($entry['id']);
        
        if (array_key_exists('parts', $mail['payload'])){
            // multi part の場合
            // 本来さらに content-type などの確認もいるだろう
            foreach ($mail['payload']['parts'] as $part){
                // url un safe に戻す
                $data = strtr($part['body']['data'], '-_', '+/');
                
                $mailtext =  base64_decode($data);
                
                // あとはやりたい処理を
            }
            
        }else if (array_key_exists('data', $mail['payload']['body'])){
            // url un safe に戻す
            $data = strtr($mail['payload']['body']['data'], '-_', '+/');
                
            $mailtext =  base64_decode($data);
            
            // あとはやりたい処理を
        }
    }
}