Для того, чтобы проверить код отправки почты в нашей бэкэнде GCP, я отправляю электронное письмо на почтовый ящик GMail и пытаюсь проверить его прибытие. Текущий механизм аутентификации в GMail API довольно стандартен, вставлен из документации по GMail API и встроен в функцию:
def authenticate():
"""Authenticates to the Gmail API using data in credentials.json,
returning the service instance for use in queries etc."""
store = file.Storage('token.json')
creds = store.get()
if not creds or creds.invalid:
flow = client.flow_from_clientsecrets(CRED_FILE_PATH, SCOPES)
creds = tools.run_flow(flow, store)
service = build('gmail', 'v1', http=creds.authorize(Http()))
return service
CRED_FILE_PATH
указывает на загруженный файл учетных данных для службы. Отсутствие файла token.json
вызывает его повторное создание после взаимодействия аутентификации через окно браузера, как и истечение срока действия токена.
Это интеграционный тест, который должен выполняться без головы (то есть без какого-либо взаимодействия). Когда требуется повторная аутентификация, тест в настоящее время вызывает исключение, когда поток аутентификации начинает обращаться к sys.argv
, что означает, что он видит аргументы для pytest
!
Я пытался выяснить, как надежно аутентифицироваться, используя механизм, который не требует взаимодействия с пользователем (такой как ключ API). Ничто в документации или в Stackoverflow не может ответить на этот вопрос.
Более поздняя попытка использует файл ключа из учетной записи службы с делегированием GMail, чтобы избежать интерактивных потоков Oauth2.
def authenticate():
"""Authenticates to the Gmail API using data in g_suite_access.json,
returning the service instance for use in queries etc."""
main_cred = service_account.Credentials.from_service_account_file(
CRED_FILE_PATH, scopes=SCOPES)
# Establish limited credential to minimise any damage.
credentials = main_cred.with_subject(GMAIL_USER)
service = build('gmail', 'v1', credentials=credentials)
return service
При попытке использовать этот сервис с
response = service.users().messages().list(userId='me',
q=f'subject:{subject}').execute()
Я получаю:
google.auth.exceptions.RefreshError:
('unauthorized_client: Client is unauthorized to retrieve access tokens using this method.',
'{\n "error": "unauthorized_client",\n "error_description": "Client is unauthorized to retrieve access tokens using this method."\n}')
У меня такое ощущение, что есть нечто фундаментальное, чего я не понимаю.