サービスアカウントでGoogle Work SpaceのGroupメールを扱いたいが認証が上手くいかない問題
解決したいこと
会社で使用しているGoogle Work SpaceのGroupのメールをサービスアカウント経由で操作したいのですが、認証がうまくいきません。
HttpError 400エラーが出ており、認証情報や権限が足りていないように感じるのですが、原因特定ができずに困っております。会社で使用しているGCPなので権限の申請も何度もできないため、原因と解決策をある程度絞って対応したいので、アドバイスいただきたいです。
特にIAMの権限が影響しそうですがよくわからないので、以下現状に関係しそうなことを記載します。
最終的にやりたいことは、 サービスアカウントを使用して、Gmailを扱いたい。 それだけです。
よろしくお願いいたします。
<現状のIAM権限>
操作しているユーザーのロール(私)
- 編集者
- サービスアカウント管理者
自分で試したこと
- Gmailapiの有効化、確認済
- ユーザーアカウントで認証→Gmailの取得成功、確認済。
サービスアカウントkeyのjsonファイルは以下のような状態です。(一部書き換えてます)
{
"type": "service_account",
"project_id": “my-project”,
"private_key_id": “12345678xxxxxxxxxxxx”,
"private_key": "-----BEGIN PRIVATE KEY-----\nxxxxxxxxxxxxxxxxxxxxxxxx=\n-----END PRIVATE KEY-----\n",
"client_email": “my-service-account@my-project.iam.gserviceaccount.com",
"client_id": “12345678901234567890”,
"auth_uri": "https://accounts.google.com/o/oauth2/auth",
"token_uri": "https://oauth2.googleapis.com/token",
"auth_provider_x509_cert_url": "https://www.googleapis.com/oauth2/v1/certs",
"client_x509_cert_url": "https://www.googleapis.com/robot/v1/metadata/x509/my-project%40vmy-project.iam.gserviceaccount.com"
}
実行しているpythonコードです。
例として、以下ではコメントアウトしている1.User Account Verで実行するとメールは取得できます。
from pprint import pprint
from googleapiclient.errors import HttpError
from googleapiclient.discovery import build
from google.oauth2.service_account import Credentials
# from google.oauth2.credentials import Credentials #ユーザーアカウントで使用する場合
MAXRESULT= 100 #取得する最大件数
SCOPE = ['https://www.googleapis.com/auth/gmail.readonly']
user_key = '../user_token.json'
sa_key = '../service_account_token.json'
query = "company_group@company.co.jp" #(取得するメールのグループを指定する)
### 1.User Account Ver ユーザーアカウントではメールが取れます----------
# creds = Credentials.from_authorized_user_file(user_key, SCOPE)
### 2.Service Account Ver ----------
creds = Credentials.from_service_account_file(sa_key, scopes=SCOPE)
try:
# Call the Gmail API
service = build('gmail', 'v1', credentials=creds)
results = service.users().labels().list(userId='me').execute()
labels = results.get('labels', [])
# 認証情報のトークンを確認する
print("cred.token: {}\ncreds.valid: {}".format(creds.token, creds.valid))
if not labels:
print('No labels found.')
### メールIDの一覧を取得する(最大100件)
messageIDlist = service.users().messages().list(userId="me", maxResults=MAXRESULT, q=query).execute()
mes = messageIDlist["messages"]
print("mes_id:{}".format(mes[0]['id']))
pprint(service.users().messages().get(userId="me", id=mes[0]['id']).execute())
except HttpError as error:
# TODO(developer) - Handle errors from gmail API.
print(f'An error occurred: {error}')
発生している問題・エラー
An error occurred: <HttpError 400 when requesting https://gmail.googleapis.com/gmail/v1/users/me/labels?alt=json returned "Precondition check failed.". Details: "[{'message': 'Precondition check failed.', 'domain': 'global', 'reason': 'failedPrecondition'}]">
"https://gmail.googleapis.com/gmail/v1/users/me/labels?alt=json"
を開くと以下のメッセージが表示されてます。
{
"error": {
"code": 401,
"message": "Request is missing required authentication credential. Expected OAuth 2 access token, login cookie or other valid authentication credential. See https://developers.google.com/identity/sign-in/web/devconsole-project.",
"errors": [
{
"message": "Login Required.",
"domain": "global",
"reason": "required",
"location": "Authorization",
"locationType": "header"
}
],
"status": "UNAUTHENTICATED",
"details": [
{
"@type": "type.googleapis.com/google.rpc.ErrorInfo",
"reason": "CREDENTIALS_MISSING",
"domain": "googleapis.com",
"metadata": {
"method": "caribou.api.proto.MailboxService.ListLabels",
"service": "gmail.googleapis.com"
}
}
]
}
}
その他にも必要な情報がありましたら追記しますので、コメントいただけると幸いです。
どうぞよろしくお願いします。