Чтобы проверить код отправки тестового письма в нашем бэкэнде GCP, я отправляю электронное письмо в почтовый ящик GMail и пытаюсь проверить его получение. Текущий механизм аутентификации в API GMail довольно стандартный, вставлен из документации API GMail и встроен в функцию:
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}')
У меня такое чувство, что я не понимаю чего-то фундаментального.
Я действительно подумал об этом, но поскольку мы захотим использовать службы Gmail API для других целей позже, это просто решит проблему в будущем.
По иронии судьбы, при дальнейшем изучении решения IMAP у меня возникли проблемы с аутентификацией с помощью IMAP, и дальнейшие исследования привели меня к этот вопрос, где ответ ... использовать аутентификацию OAuth2 !!
Ну, это только если вы отключите «доступ для менее безопасных приложений», как там сказано. Так что технически это не препятствие для проверки получения электронной почты - просто нужно изменить этот параметр, чтобы разрешить. Но, поскольку вам в любом случае понадобится GMail API позже, это явно не постоянное решение, а, возможно, временное решение. IMAP полностью работает - я перемещаю содержимое почтовых ящиков Gmail в другое место, используя его.
Да, теперь у меня есть резервное решение IMAP, но на данный момент мы договорились, что это может быть тест интеграции, запускаемый вручную. Нам не нужно проверять наши каналы электронной почты каждую минуту, но было бы неплохо знать, что все работает, например, после выпуска нового поставщика. Я все еще надеюсь, что награда затянется, но я не задерживаю дыхание.
- Не пугайтесь, но все такие вопросы приветствуются. Теперь я отказался от решения IMAP в пользу flow_from_client_secrets
- если мы работаем в интерактивном режиме, тестер может подтвердить правильные учетные данные для аутентификации.
Идентификатор gmail, который вы пытаетесь использовать, это идентификатор gsuite или простой идентификатор gmail (@ gmail.com)?
Это G-suite (наш собственный домен - одна ошибка заключалась в попытке войти в систему под псевдонимом домена, что не сработало).
Я пробовал запустить ваш код, и он работает абсолютно нормально. Пожалуйста, проверьте две вещи: 1. Если вы авторизуете правильные области. 2. Я обычно видел, что эта ошибка возникает, когда при авторизации учетной записи службы отсутствуют области. Правильно ли вы выполнили это - developers.google.com/admin-sdk/directory/v1/guides/delegati на?
@holdenweb у тебя была возможность это проверить?
Да, очень полезно. Как вы и подозревали, авторизация учетной записи службы не была правильно определена.
Большой! Однако пропустил награду :)
Я считаю, что необходимо написать ответ, чтобы потребовать награду, и был только один ответ, когда награда истекла. Сожалею!
Ага, все в порядке. Спасибо
Учетная запись службы должна быть авторизована, иначе она не может получить доступ к электронной почте для домена.
"Client is unauthorized to retrieve access tokens using this method"
Означает, что вы не авторизовали его должным образом; проверьте Делегирование полномочий на уровне домена учетной записи службы
Источник: Клиент не авторизован для получения токенов доступа с помощью этого метода Gmail API C#
Почему вы не можете использовать IMAP-доступ к учетной записи Gmail для выполнения этого теста интеграции? Я понимаю, что это не то, с чем вы хотели получить помощь, но кажется, что это намного проще для достижения цели интеграционного теста, как описано.