Правильный способ использования учетной записи службы Google Apps Marketplace для подключения к Gmail IMAP и другим службам
Одна из функций нашего приложения Marketplace использует доступ к учетной записи Gmail пользователя через IMAP. Мы используем библиотеки google-api-java-client и google-oauth-java-client и код, подобный этому примеру, в проекте java-gmail-imap следующим образом:
GoogleCredential credential = new GoogleCredential.Builder().setTransport(HTTP_TRANSPORT)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId(SERVICE_ACCOUNT_ID)
.setServiceAccountScopes(Arrays.asList(GMAIL_SCOPE))
.setServiceAccountPrivateKey(PRIVATE_KEY)
.setServiceAccountUser(emailAddress)
.build();
credential.refreshToken();
Затем мы используем код на основе примеров по адресу https://code.google.com/p/google-mail-oauth2-tools чтобы установить соединение IMAP, например
IMAPStore imapStore = OAuth2Authenticator.connectToImap("imap.googlemail.com",
993, emailAddress, credential.getAccessToken(), false);
В большинстве случаев это работает правильно, однако мы видим, что для небольшого, но значительного числа запросов звонок в Google был сделан refreshToken()
завершается с ошибкой HTTP 500 и ответом HTML, где обычно возвращается JSON, например
<p class="large"><b>500.</b> <ins>That's an error.</ins></p>
<p class="large">The server could not process your request.
<ins>That's all we know.</ins></p>
Адвокат Google сообщил нам, что мы обновляем токены, которые не поддерживаются для учетных записей служб, и мы должны использовать подход, подобный приведенному в этом примере.
Тем не менее, кажется, что без вызова refreshToken
затем accessToken
не заполняется на объекте учетных данных, а затем это приводит к NullPointerException
когда мы звоним OAuth2Authenticator.connectToImap
Из источника для GoogleCredential
казалось executeRefreshToken()
переопределяется для обработки учетных записей служб, т. е. вместо обновления он просто запрашивает новый токен, а затем этот бит кода в Credential
затем обрабатывает заполнение токена доступа:
TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
setFromTokenResponse(tokenResponse); ....
Мы не были уверены, нужно ли нам приложить наш призыв к refreshToken()
в цикле повтора для обхода прерывистых 500 ошибок или необходимости внесения других изменений в наш код, чтобы следовать рекомендованному подходу для этого сценария.
Кто-нибудь может посоветовать?
1 ответ
Я использую пример кода java-gmail-imap в производственном процессе (но он используется только для отображения папки входящих сообщений на нашем портале университета, поэтому не требуется много взаимодействия, которое потребовало бы от меня повторного использования одного и того же токена обновления, например).
В зависимости от вашего использования, мне интересно, если в вашем случае вступает в игру какое-то регулирование (я читал в местах, где Gmail может иногда ограничивать доступ).
В других местах я видел, как API Google говорили о повторных попытках с использованием экспоненциального алгоритма отката.
Вы должны быть немного осторожнее, сравнивая использование OAuth 2.0 с другими API Google Service и Gmail. Gmail отличается тем, что использует XOAUTH2. Тем не менее, я видел другие API Google, которые, кажется, нуждаются в вызове refreshToken. Документация немного неясна и говорит что-то вроде " Обновите токен доступа, если это необходимо " (как вы говорите, это не работает без этого шага, но я не экспериментировал с повторным использованием токенов обновления через учетные данные.setRefreshToken(String refreshToken)).
Мне было бы интересно услышать, как вы поживаете.