我们的 Marketplace 应用程序的一项功能是通过 IMAP 访问用户的 Gmail 帐户。我们在 java-gmail-imap 项目中使用了 google-api-java-client 和 google-oauth-java-client 库和类似于此示例的代码,如下所示:
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
thenaccessToken
不会填充在凭证对象上,然后这会导致NullPointerException
我们调用OAuth2Authenticator.connectToImap
从源代码来看,GoogleCredential
它似乎executeRefreshToken()
被覆盖以处理服务帐户,即它不是执行刷新,而是简单地请求一个新令牌,然后这段代码Credential
处理填充访问令牌:
TokenResponse tokenResponse = executeRefreshToken();
if (tokenResponse != null) {
setFromTokenResponse(tokenResponse); ....
我们不确定是否需要将调用包含refreshToken()
在重试循环中以解决间歇性 500 错误,或者是否需要对代码进行其他更改以遵循针对此场景的推荐方法。
任何人都可以建议吗?