首页 > 解决方案 > com.google.android.gms.auth.UserRecoverableAuthException:NeedPermission

问题描述

在 Android 中使用 OAuth2.0 发送带有 GMail 的邮件,引发异常 com.google.android.gms.auth.UserRecoverableAuthException: Need Permission for business G-suit 帐户,并且可以正常使用普通 gmail 帐户

如下所示初始化 Google API 客户端。

GoogleAccountCredential mCredential;
String[] SCOPES = {
    GmailScopes.GMAIL_LABELS,
    GmailScopes.GMAIL_COMPOSE,
    GmailScopes.GMAIL_INSERT,
    GmailScopes.GMAIL_MODIFY,
    GmailScopes.GMAIL_READONLY,
    GmailScopes.MAIL_GOOGLE_COM
};

初始化凭证和服务对象。

mCredential = GoogleAccountCredential.usingOAuth2(
  getApplicationContext(), Arrays.asList(SCOPES))
  .setBackOff(new ExponentialBackOff());

// 使用 GMail OAuth 发送邮件的异步任务

 private class MakeRequestTask extends AsyncTask {
        private com.google.api.services.gmail.Gmail mService = null;
        private Exception mLastError = null;
        private View view = sendFabButton;

        public MakeRequestTask(GoogleAccountCredential credential) {
            HttpTransport transport = AndroidHttp.newCompatibleTransport();
            JsonFactory jsonFactory = JacksonFactory.getDefaultInstance();
            mService = new com.google.api.services.gmail.Gmail.Builder(
                    transport, jsonFactory, credential)
                    .setApplicationName(getResources().getString(R.string.app_name))
                    .build();
        }

        @Override
        protected String doInBackground(Void... params) {
            try {
                return getDataFromApi();
            } catch (Exception e) {
                mLastError = e;
                cancel(true);
                return null;
            }
        }

        private String getDataFromApi() throws IOException {
            // getting Values for to Address, from Address, Subject and Body
            String user = "me";
            String to = Utils.getString(edtToAddress);
            String from = mCredential.getSelectedAccountName();
            String subject = Utils.getString(edtSubject);
            String body = Utils.getString(edtMessage);
            MimeMessage mimeMessage;
            String response = "";
            try {
                mimeMessage = createEmail(to, from, subject, body);
                response = sendMessage(mService, user, mimeMessage);
            } catch (MessagingException e) {
                e.printStackTrace();
            }
            return response;
        }

        // Method to send email
        private String sendMessage(Gmail service,
                                   String userId,
                                   MimeMessage email)
                throws MessagingException, IOException {
            Message message = createMessageWithEmail(email);
            // GMail's official method to send email with oauth2.0
            message = service.users().messages().send(userId, message).execute();

            System.out.println("Message id: " + message.getId());
            System.out.println(message.toPrettyString());
            return message.getId();
        }

        // Method to create email Params
        private 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);
            InternetAddress tAddress = new InternetAddress(to);
            InternetAddress fAddress = new InternetAddress(from);

            email.setFrom(fAddress);
            email.addRecipient(javax.mail.Message.RecipientType.TO, tAddress);
            email.setSubject(subject);

            // Create Multipart object and add MimeBodyPart objects to this object
            Multipart multipart = new MimeMultipart();

            // Changed for adding attachment and text
            // This line is used for sending only text messages through mail
            // email.setText(bodyText);

            BodyPart textBody = new MimeBodyPart();
            textBody.setText(bodyText);
            multipart.addBodyPart(textBody);

            if (!(activity.fileName.equals(""))) {
                // Create new MimeBodyPart object and set DataHandler object to this object
                MimeBodyPart attachmentBody = new MimeBodyPart();
                String filename = activity.fileName; // change accordingly
                DataSource source = new FileDataSource(filename);
                attachmentBody.setDataHandler(new DataHandler(source));
                attachmentBody.setFileName(filename);
                multipart.addBodyPart(attachmentBody);
            }

            // Set the multipart object to the message object
            email.setContent(multipart);
            return email;
        }

        private Message createMessageWithEmail(MimeMessage email)
                throws MessagingException, IOException {
            ByteArrayOutputStream bytes = new ByteArrayOutputStream();
            email.writeTo(bytes);
            String encodedEmail = Base64.encodeBase64URLSafeString(bytes.toByteArray());
            Message message = new Message();
            message.setRaw(encodedEmail);
            return message;
        }

        @Override
        protected void onPreExecute() {
            mProgress.show();
        }

        @Override
        protected void onPostExecute(String output) {
            mProgress.hide();
            if (output == null || output.length() == 0) {
                showMessage(view, "No results returned.");
            } else {
                showMessage(view, output);
            }
        }

        @Override
        protected void onCancelled() {
            mProgress.hide();
            if (mLastError != null) {
                if (mLastError instanceof GooglePlayServicesAvailabilityIOException) {
                    showGooglePlayServicesAvailabilityErrorDialog(
                            ((GooglePlayServicesAvailabilityIOException) mLastError)
                                    .getConnectionStatusCode());
                } else if (mLastError instanceof UserRecoverableAuthIOException) {
                    startActivityForResult(
                            ((UserRecoverableAuthIOException) mLastError).getIntent(),
                            Utils.REQUEST_AUTHORIZATION);
                } else {
                    showMessage(view, "The following error occurred:\n" + mLastError.getMessage());
                    Log.v("Error", mLastError.getMessage());
                }
            } else {
                showMessage(view, "Request Cancelled.");
            }
        }
    }

如果是商业帐户,它正在转移到 oncancelled() 方法并抛出

com.google.android.gms.auth.UserRecoverableAuthException:NeedPermission

标签: androidgoogle-oauthgmail-api

解决方案


您的身份验证令牌已过期,您需要再次向 Google 进行身份验证。捕获 UserRecoverableAuthException 并在 Exception 对象上调用 getIntent 以获取身份验证 Intent。然后再次启动 Activity 进行身份验证。参考

try {
    // Your code
    ...
} catch (UserRecoverableAuthIOException e) {
    startActivityForResult(e.getIntent(), REQUEST_AUTHORIZATION);
}

推荐阅读