Allow writeTo to accept a list of attachments to send
* The default is to send all attachments, of course, but with smartSend, we need to exclude the original ones or they will be duplicated * Another CL in Exchange is required to fix the bug Bug: 7005505 Change-Id: I0e8bab2fb53dd4d60c82f2ef9a525ff7b015f2eb
This commit is contained in:
parent
22e9efd442
commit
77d166b8d1
|
@ -16,9 +16,7 @@
|
||||||
|
|
||||||
package com.android.emailcommon.internet;
|
package com.android.emailcommon.internet;
|
||||||
|
|
||||||
import android.content.ContentUris;
|
|
||||||
import android.content.Context;
|
import android.content.Context;
|
||||||
import android.database.Cursor;
|
|
||||||
import android.net.Uri;
|
import android.net.Uri;
|
||||||
import android.util.Base64;
|
import android.util.Base64;
|
||||||
import android.util.Base64OutputStream;
|
import android.util.Base64OutputStream;
|
||||||
|
@ -40,7 +38,9 @@ import java.io.OutputStream;
|
||||||
import java.io.OutputStreamWriter;
|
import java.io.OutputStreamWriter;
|
||||||
import java.io.Writer;
|
import java.io.Writer;
|
||||||
import java.text.SimpleDateFormat;
|
import java.text.SimpleDateFormat;
|
||||||
|
import java.util.Arrays;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.List;
|
||||||
import java.util.Locale;
|
import java.util.Locale;
|
||||||
import java.util.regex.Matcher;
|
import java.util.regex.Matcher;
|
||||||
import java.util.regex.Pattern;
|
import java.util.regex.Pattern;
|
||||||
|
@ -55,9 +55,6 @@ public class Rfc822Output {
|
||||||
private static final SimpleDateFormat DATE_FORMAT =
|
private static final SimpleDateFormat DATE_FORMAT =
|
||||||
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
|
new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
|
||||||
|
|
||||||
private static final String WHERE_NOT_SMART_FORWARD = "(" + Attachment.FLAGS + "&" +
|
|
||||||
Attachment.FLAG_SMART_FORWARD + ")=0";
|
|
||||||
|
|
||||||
/** A less-than-perfect pattern to pull out <body> content */
|
/** A less-than-perfect pattern to pull out <body> content */
|
||||||
private static final Pattern BODY_PATTERN = Pattern.compile(
|
private static final Pattern BODY_PATTERN = Pattern.compile(
|
||||||
"(?:<\\s*body[^>]*>)(.*)(?:<\\s*/\\s*body\\s*>)",
|
"(?:<\\s*body[^>]*>)(.*)(?:<\\s*/\\s*body\\s*>)",
|
||||||
|
@ -111,9 +108,16 @@ public class Rfc822Output {
|
||||||
* @param messageId the message to write out
|
* @param messageId the message to write out
|
||||||
* @param out the output stream to write the message to
|
* @param out the output stream to write the message to
|
||||||
* @param useSmartReply whether or not quoted text is appended to a reply/forward
|
* @param useSmartReply whether or not quoted text is appended to a reply/forward
|
||||||
|
* @param a list of attachments to send (or null if retrieved from the message itself)
|
||||||
*/
|
*/
|
||||||
public static void writeTo(Context context, long messageId, OutputStream out,
|
public static void writeTo(Context context, long messageId, OutputStream out,
|
||||||
boolean useSmartReply, boolean sendBcc) throws IOException, MessagingException {
|
boolean useSmartReply, boolean sendBcc) throws IOException, MessagingException {
|
||||||
|
writeTo(context, messageId, out, useSmartReply, sendBcc, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public static void writeTo(Context context, long messageId, OutputStream out,
|
||||||
|
boolean useSmartReply, boolean sendBcc, List<Attachment> attachments)
|
||||||
|
throws IOException, MessagingException {
|
||||||
Message message = Message.restoreMessageWithId(context, messageId);
|
Message message = Message.restoreMessageWithId(context, messageId);
|
||||||
if (message == null) {
|
if (message == null) {
|
||||||
// throw something?
|
// throw something?
|
||||||
|
@ -148,59 +152,53 @@ public class Rfc822Output {
|
||||||
Body body = Body.restoreBodyWithMessageId(context, message.mId);
|
Body body = Body.restoreBodyWithMessageId(context, message.mId);
|
||||||
String[] bodyText = buildBodyText(body, message.mFlags, useSmartReply);
|
String[] bodyText = buildBodyText(body, message.mFlags, useSmartReply);
|
||||||
|
|
||||||
Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, messageId);
|
// If a list of attachments hasn't been passed in, build one from the message
|
||||||
Cursor attachmentsCursor = context.getContentResolver().query(uri,
|
if (attachments == null) {
|
||||||
Attachment.CONTENT_PROJECTION, WHERE_NOT_SMART_FORWARD, null, null);
|
attachments =
|
||||||
|
Arrays.asList(Attachment.restoreAttachmentsWithMessageId(context, messageId));
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
boolean multipart = attachments.size() > 0;
|
||||||
int attachmentCount = attachmentsCursor.getCount();
|
String multipartBoundary = null;
|
||||||
boolean multipart = attachmentCount > 0;
|
String multipartType = "mixed";
|
||||||
String multipartBoundary = null;
|
|
||||||
String multipartType = "mixed";
|
|
||||||
|
|
||||||
// Simplified case for no multipart - just emit text and be done.
|
// Simplified case for no multipart - just emit text and be done.
|
||||||
if (!multipart) {
|
if (!multipart) {
|
||||||
writeTextWithHeaders(writer, stream, bodyText);
|
writeTextWithHeaders(writer, stream, bodyText);
|
||||||
} else {
|
} else {
|
||||||
// continue with multipart headers, then into multipart body
|
// continue with multipart headers, then into multipart body
|
||||||
multipartBoundary = getNextBoundary();
|
multipartBoundary = getNextBoundary();
|
||||||
|
|
||||||
// Move to the first attachment; this must succeed because multipart is true
|
// Move to the first attachment; this must succeed because multipart is true
|
||||||
attachmentsCursor.moveToFirst();
|
if (attachments.size() == 1) {
|
||||||
if (attachmentCount == 1) {
|
// If we've got one attachment and it's an ics "attachment", we want to send
|
||||||
// If we've got one attachment and it's an ics "attachment", we want to send
|
// this as multipart/alternative instead of multipart/mixed
|
||||||
// this as multipart/alternative instead of multipart/mixed
|
int flags = attachments.get(0).mFlags;
|
||||||
int flags = attachmentsCursor.getInt(Attachment.CONTENT_FLAGS_COLUMN);
|
if ((flags & Attachment.FLAG_ICS_ALTERNATIVE_PART) != 0) {
|
||||||
if ((flags & Attachment.FLAG_ICS_ALTERNATIVE_PART) != 0) {
|
multipartType = "alternative";
|
||||||
multipartType = "alternative";
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
writeHeader(writer, "Content-Type",
|
|
||||||
"multipart/" + multipartType + "; boundary=\"" + multipartBoundary + "\"");
|
|
||||||
// Finish headers and prepare for body section(s)
|
|
||||||
writer.write("\r\n");
|
|
||||||
|
|
||||||
// first multipart element is the body
|
|
||||||
if (bodyText[INDEX_BODY_TEXT] != null || bodyText[INDEX_BODY_HTML] != null) {
|
|
||||||
writeBoundary(writer, multipartBoundary, false);
|
|
||||||
writeTextWithHeaders(writer, stream, bodyText);
|
|
||||||
}
|
|
||||||
|
|
||||||
// Write out the attachments until we run out
|
|
||||||
do {
|
|
||||||
writeBoundary(writer, multipartBoundary, false);
|
|
||||||
Attachment attachment =
|
|
||||||
Attachment.getContent(attachmentsCursor, Attachment.class);
|
|
||||||
writeOneAttachment(context, writer, stream, attachment);
|
|
||||||
writer.write("\r\n");
|
|
||||||
} while (attachmentsCursor.moveToNext());
|
|
||||||
|
|
||||||
// end of multipart section
|
|
||||||
writeBoundary(writer, multipartBoundary, true);
|
|
||||||
}
|
}
|
||||||
} finally {
|
|
||||||
attachmentsCursor.close();
|
writeHeader(writer, "Content-Type",
|
||||||
|
"multipart/" + multipartType + "; boundary=\"" + multipartBoundary + "\"");
|
||||||
|
// Finish headers and prepare for body section(s)
|
||||||
|
writer.write("\r\n");
|
||||||
|
|
||||||
|
// first multipart element is the body
|
||||||
|
if (bodyText[INDEX_BODY_TEXT] != null || bodyText[INDEX_BODY_HTML] != null) {
|
||||||
|
writeBoundary(writer, multipartBoundary, false);
|
||||||
|
writeTextWithHeaders(writer, stream, bodyText);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Write out the attachments until we run out
|
||||||
|
for (Attachment att: attachments) {
|
||||||
|
writeBoundary(writer, multipartBoundary, false);
|
||||||
|
writeOneAttachment(context, writer, stream, att);
|
||||||
|
writer.write("\r\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
// end of multipart section
|
||||||
|
writeBoundary(writer, multipartBoundary, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
writer.flush();
|
writer.flush();
|
||||||
|
|
Loading…
Reference in New Issue