Правильный способ использования учетной записи службы 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)).

Мне было бы интересно услышать, как вы поживаете.

Другие вопросы по тегам