Попытка отправить электронную почту через учетную запись службы, получая com.гуглить.прикладной программный интерфейс.клиент.автор.что OAuth2.TokenResponseException: 401 Несанкционированное
у меня есть учетная запись Google Apps. Я пытаюсь просто отправить электронное письмо от имени пользователя, используя учетную запись службы.
я перерыла весь интернет и ничего не работает и я почти в убыток.
я следовал руководствам Java, и я все еще продолжаю получать com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
Почему этот фрагмент кода дает мне 401 несанкционированный?
JsonFactory JSON_FACTORY = JacksonFactory.getDefaultInstance();
HttpTransport httpTransport = GoogleNetHttpTransport.newTrustedTransport();
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("something@something-something.iam.gserviceaccount.com")
.setServiceAccountPrivateKeyFromP12File(new File("path/to/file/myProject.p12"))
.setServiceAccountScopes(GmailScopes.all())
.setServiceAccountUser("user@mydomain.org")
.build();
Gmail gmailService = new Gmail.Builder(httpTransport, JSON_FACTORY, credential)
.setApplicationName("My App") // DOES IT MATTER WHAT THIS IS SET TO?
.build();
MimeMessage mimeMessage = createEmail("myemail@gmail.com", "user@mydomain.org", "Testing", "hey");
sendMessage(gmailService, "me", mimeMessage);
эти методы в основном копировать / вставить из документации Googles:
/**
* Create a MimeMessage using the parameters provided.
*
* @param to email address of the receiver
* @param from email address of the sender, the mailbox account
* @param subject subject of the email
* @param bodyText body text of the email
* @return the MimeMessage to be used to send email
* @throws MessagingException
*/
public static MimeMessage createEmail(String to,
String from,
String subject,
String bodyText)
throws MessagingException {
Properties props = new Properties();
Session session = Session.getDefaultInstance(props, null);
MimeMessage email = new MimeMessage(session);
email.setFrom(new InternetAddress(from));
email.addRecipient(javax.mail.Message.RecipientType.TO,
new InternetAddress(to));
email.setSubject(subject);
email.setText(bodyText);
return email;
}
/**
* Send an email from the user's mailbox to its recipient.
*
* @param service Authorized Gmail API instance.
* @param userId User's email address. The special value "me"
* can be used to indicate the authenticated user.
* @param email Email to be sent.
* @throws MessagingException
* @throws IOException
*/
public static void sendMessage(Gmail service, String userId, MimeMessage email)
throws MessagingException, IOException {
Message message = createMessageWithEmail(email);
System.out.println("userId = " + userId);
message = service.users().messages().send(userId, message).execute();
System.out.println("Message id: " + message.getId());
System.out.println(message.toPrettyString());
}
/**
* Create a Message from an email
*
* @param email Email to be set to raw of message
* @return Message containing base64url encoded email.
* @throws IOException
* @throws MessagingException
*/
public static Message createMessageWithEmail(MimeMessage email)
throws MessagingException, IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
email.writeTo(baos);
String encodedEmail = Base64.encodeBase64URLSafeString(baos.toByteArray());
Message message = new Message();
message.setRaw(encodedEmail);
return message;
}
Я просто это трассировка стека:
com.google.api.client.auth.oauth2.TokenResponseException: 401 Unauthorized
at com.google.api.client.auth.oauth2.TokenResponseException.from(TokenResponseException.java:105)
at com.google.api.client.auth.oauth2.TokenRequest.executeUnparsed(TokenRequest.java:287)
at com.google.api.client.auth.oauth2.TokenRequest.execute(TokenRequest.java:307)
at com.google.api.client.googleapis.auth.oauth2.GoogleCredential.executeRefreshToken(GoogleCredential.java:384)
at com.google.api.client.auth.oauth2.Credential.refreshToken(Credential.java:489)
at com.google.api.client.auth.oauth2.Credential.intercept(Credential.java:217)
at com.google.api.client.http.HttpRequest.execute(HttpRequest.java:859)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:419)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.executeUnparsed(AbstractGoogleClientRequest.java:352)
at com.google.api.client.googleapis.services.AbstractGoogleClientRequest.execute(AbstractGoogleClientRequest.java:469)
at com.my.services.NotificationServiceTest.testGmailCredential(NotificationServiceTest.java:96)
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:497)
at org.junit.runners.model.FrameworkMethod.runReflectiveCall(FrameworkMethod.java:50)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:47)
at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:17)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:325)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:78)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:57)
at org.junit.runners.ParentRunner.run(ParentRunner.java:290)
at org.junit.runners.ParentRunner.schedule(ParentRunner.java:71)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:288)
at org.junit.runners.ParentRunner.access0(ParentRunner.java:58)
at org.junit.runners.ParentRunner.evaluate(ParentRunner.java:268)
at org.junit.runners.ParentRunner.run(ParentRunner.java:363)
at org.eclipse.jdt.internal.junit4.runner.JUnit4TestReference.run(JUnit4TestReference.java:86)
at org.eclipse.jdt.internal.junit.runner.TestExecution.run(TestExecution.java:38)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:459)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.runTests(RemoteTestRunner.java:675)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.run(RemoteTestRunner.java:382)
at org.eclipse.jdt.internal.junit.runner.RemoteTestRunner.main(RemoteTestRunner.java:192)
у меня есть учетная запись службы, созданная и настроенная на делегирование домена, и вот скриншот моих областей клиентского доступа к API:
что я упускаю, что я вам 401 несанкционированный?
3 ответов
после длительного, но полезный телефонный звонок с поддержкой Google, мы, наконец, выследили, что если я изменил GmailScopes.all()
к явным областям ниже, тогда это сработало.
Collection<String> SCOPES
= Collections.unmodifiableCollection(
Arrays.asList(
new String[]{
GmailScopes.GMAIL_COMPOSE,
GmailScopes.GMAIL_SEND
}));
парень поддержки не был уверен на 100%, но он подумал, что, возможно, поскольку у моего пользователя не было доступа ко всем областям gmail, и я указывал GmailScopes.all()
что это была ошибка с 401 Unauthorized, прежде чем даже проверить, какую область я пытался использовать.
посмотри здесь, кажется, у вас еще нет маркера доступа! добавьте refeshToken в свой код:
GoogleCredential credential = new GoogleCredential.Builder()
.setTransport(httpTransport)
.setJsonFactory(JSON_FACTORY)
.setServiceAccountId("something@something-something.iam.gserviceaccount.com")
.setServiceAccountPrivateKeyFromP12File(new File("path/to/file/myProject.p12"))
.setServiceAccountScopes(GmailScopes.all())
.setServiceAccountUser("user@mydomain.org")
.build();
credential.refreshToken();
наиболее распространенными причинами ошибок при выполнении вызовов API с помощью маркера доступа являются:
- истекший токен доступа (наиболее распространенный)
- разработчик случайно отключил API (uncommon)
- пользователь отзывает токен (редко)
иногда в теле ответа HTTP 4xx существует больше объяснений. В клиенте Java, например, вы должны зарегистрировать ошибку, потому что это поможет в устранении неполадок:
try {
// Make your Google API call
} catch (GoogleJsonResponseException e) {
GoogleJsonError error = e.getDetails();
// Print out the message and errors
}
вы могли возьмите существующий код и сделайте вызов API здесь всякий раз, когда вы получаете HTTP 4xx и регистрируете этот ответ. Это даст полезную информацию.
если маркер недопустим, вы можете выполнить следующие действия.
- удалите маркер доступа из хранилища данных или базы данных.
- используйте токен обновления, чтобы получить новый токен доступа (если вы используете токен обновления)
- попробуйте сделать вызов API еще раз. Если это сработает, ты молодец! Если нет ...
- Проверьте маркер доступа к API tokenInfo
- если он все еще недействителен, сделайте полный reauth
вы можете отлаживать все с помощью folowwing этой ссылка. У него даже есть учебное видео!