在 Android 中使用 Gmail API 发送带附件的电子邮件(execute() 挂起)

Sending email with attachments using Gmail API in Android (execute() hangs)

只要附件很小,一切似乎都可以正常工作。
但是,当我尝试附加一个更大的文件(例如 7MB)时,Sendexecute() 方法只是挂起。
我尝试查看文档,如果我理解正确,我应该使用实际执行 uploadSend API,但是,我不知道应该在哪里提供这些参数。
这是电子邮件生成方法:

public MimeMessage toMimeMessage(String from, Context context) throws MessagingException {
    Properties props = new Properties();
    Session session = Session.getDefaultInstance(props, null);

    MimeMessage mimeMessage = new MimeMessage(session);

    mimeMessage.setFrom(new InternetAddress(from));
    mimeMessage.addRecipient(javax.mail.Message.RecipientType.TO, new InternetAddress(recipient));
    mimeMessage.setSubject(subject);

    MimeBodyPart mimeBodyText = new MimeBodyPart();
    mimeBodyText.setContent(body,"text/html");
    mimeBodyText.setHeader("Content-Type","text/plain; charset="UTF-8"");

    Multipart mp = new MimeMultipart();
    mp.addBodyPart(mimeBodyText);

    if (attachments != null && attachments.size() > 0) {
        MimeBodyPart mimeBodyAttachments = new MimeBodyPart();
        for (Uri uri : attachments) {
            String fileName = UriUtils.getFileName(uri, context);
            String mimeType = UriUtils.getMimeType(uri, context);
            Log.d(TAG,"Generating file info, uri=" + uri.getPath() +", mimeType=" + mimeType);
            FileInputStream is = UriUtils.generateFileInfo(context, uri, mimeType);
            if (is == null) {
                throw new MessagingException("Failed to get file for uri=" + uri.getPath());
            }
            try
            {
                DataSource source = new ByteArrayDataSource(is, mimeType);
                mimeBodyAttachments.setDataHandler(new DataHandler(source));
                mimeBodyAttachments.setFileName(fileName);
                mimeBodyAttachments.setHeader("Content-Type", mimeType +"; name="" + fileName +""");
            } catch (IOException e) {
                throw new MessagingException(e.getMessage());
            }
        }
        mimeBodyAttachments.setHeader("Content-Transfer-Encoding","base64");
        mimeBodyAttachments.setDisposition(MimeBodyPart.ATTACHMENT);
        mp.addBodyPart(mimeBodyAttachments);
    }

    mimeMessage.setContent(mp);

    return mimeMessage;
}

.

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

后跟:

MimeMessage mimeMessage = email.toMimeMessage(userId, context);
Message message = createMessageWithEmail(mimeMessage);
Gmail.Users.Messages messages = service.users().messages();
Gmail.Users.Messages.Send send = messages.send(userId, message);
send.execute(); // method hangs when using large attachment

相关讨论

  • 我希望你在 AsyncTask 中运行它。如果不是这就是冻结的原因。
  • 我正在异步运行,函数挂起,我没有得到 ANR
  • 定义"挂起"...显然通过慢速互联网发送 (7 * 1.333 N)MB 数据需要一些时间...
  • 我调用 execute 并没有返回(等待 20 分钟就足够了?)这不是互联网问题

正如您所提到的,我认为您正在达到允许的邮件大小的上限。我不认为(如果我错了,请有人纠正我)Java Gmail API 客户端对超过此大小的消息有任何内置支持,因此由您来实现它。

在底层,messages.send-方法会产生一个常规的 http POST 请求:

POST https://www.googleapis.com/gmail/v1/users/{USER_ID}/messages/send
Content-Type: application/json
Authorization: Bearer {ACCESS_TOKEN}

{
 "raw":"{MESSAGE_URL_SAFE_BASE64_ENCODED}"
}

这仅适用于您发现的总大小约为 5 mb 的情况。如果您想使用 35 mb 的最大限制,您需要执行以下操作:

POST https://www.googleapis.com/upload/gmail/v1/users/{USER_ID}/messages/send?uploadType=multipart
Content-Type: message/rfc822
Authorization: Bearer {ACCESS_TOKEN}

"{MESSAGE_IN_RFC822_FORMAT}"

注意 URL 中的 uploaduploadType=multipart URL 参数、message/rfc822Content-Type 和请求正文中的 message non-encoded。这个答案可能会给你一些启发。

所以您可能需要绕过(再次,如果我错了,请有人纠正我)Java 客户端并使用其他一些库自己发出常规的 http 请求。

相关讨论

  • 我在库本身中发现了一个 API,它看起来应该支持 \\'upload\\',这是它的签名: send(java.lang.String userId, com.google.api.services.gmail.model.Message content, com.google.api.client.http.AbstractInputStreamContent mediaContent) 正如你所看到的那样,它得到了 AbstractInputStreamContent 尝试一下,不幸的是它不是记录在案并且很难理解它的使用(对于单个和多个附件)

以上是在 Android 中使用 Gmail API 发送带附件的电子邮件(execute() 挂起)的全部内容。
THE END
分享
二维码
< <上一篇
下一篇>>