在 Android 中使用 Gmail API 发送带附件的电子邮件(execute() 挂起)
Sending email with attachments using Gmail API in Android (execute() hangs)
只要附件很小,似乎一切正常。
但是,当我尝试附加一个更大的文件(例如 7MB)时,Send
的 execute()
方法挂起。
我试图查看文档,如果我理解正确,我应该使用 send
API which actually performs upload
但是,我不知道应该在哪里提供这些参数。
这是电子邮件生成方法:
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
如您所述,我认为您达到了允许的邮件大小上限。我不认为(如果我错了,请有人纠正我)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中的upload
,uploadType=multipart
中的URL参数,message/rfc822
中的Content-Type
和message non-encoded
中的请求体。 This answer 可能会有所启发。
因此您可能需要绕过(再次强调,如果我错了,请有人纠正我)Java 客户端并使用其他一些库自己发出常规的 http 请求。
只要附件很小,似乎一切正常。
但是,当我尝试附加一个更大的文件(例如 7MB)时,Send
的 execute()
方法挂起。
我试图查看文档,如果我理解正确,我应该使用 send
API which actually performs upload
但是,我不知道应该在哪里提供这些参数。
这是电子邮件生成方法:
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
如您所述,我认为您达到了允许的邮件大小上限。我不认为(如果我错了,请有人纠正我)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中的upload
,uploadType=multipart
中的URL参数,message/rfc822
中的Content-Type
和message non-encoded
中的请求体。 This answer 可能会有所启发。
因此您可能需要绕过(再次强调,如果我错了,请有人纠正我)Java 客户端并使用其他一些库自己发出常规的 http 请求。