Cache attachments on send
Cache attachments in a email directory when sending to allow sending to succeed when the content provider has a permission Bug: 7381557 Change-Id: Icf9faead2048de237228625f998b42feade48978
This commit is contained in:
parent
3e2fdd33e3
commit
9a95253846
|
@ -18,6 +18,7 @@ package com.android.emailcommon.internet;
|
|||
|
||||
import android.content.Context;
|
||||
import android.net.Uri;
|
||||
import android.text.TextUtils;
|
||||
import android.util.Base64;
|
||||
import android.util.Base64OutputStream;
|
||||
|
||||
|
@ -27,11 +28,14 @@ import com.android.emailcommon.provider.EmailContent.Attachment;
|
|||
import com.android.emailcommon.provider.EmailContent.Body;
|
||||
import com.android.emailcommon.provider.EmailContent.Message;
|
||||
|
||||
import com.android.mail.utils.LogUtils;
|
||||
|
||||
import org.apache.commons.io.IOUtils;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -49,6 +53,7 @@ import java.util.regex.Pattern;
|
|||
* Utility class to output RFC 822 messages from provider email messages
|
||||
*/
|
||||
public class Rfc822Output {
|
||||
private static final String TAG = "Email";
|
||||
|
||||
// In MIME, en_US-like date format should be used. In other words "MMM" should be encoded to
|
||||
// "Jan", not the other localized format like "Ene" (meaning January in locale es).
|
||||
|
@ -233,9 +238,25 @@ public class Rfc822Output {
|
|||
if (attachment.mContentBytes != null) {
|
||||
inStream = new ByteArrayInputStream(attachment.mContentBytes);
|
||||
} else {
|
||||
// try to open the file
|
||||
Uri fileUri = Uri.parse(attachment.getContentUri());
|
||||
inStream = context.getContentResolver().openInputStream(fileUri);
|
||||
// First try the cached file
|
||||
final String cachedFile = attachment.getCachedFilePath();
|
||||
if (!TextUtils.isEmpty(cachedFile)) {
|
||||
try {
|
||||
inStream = new FileInputStream(cachedFile);
|
||||
} catch (IOException e) {
|
||||
// Couldn't open the cached file, fall back to the original content uri
|
||||
inStream = null;
|
||||
|
||||
LogUtils.d(TAG, "Rfc822Output#writeOneAttachment(), failed to load" +
|
||||
"cached file, falling back to: %s", attachment.getContentUri());
|
||||
}
|
||||
}
|
||||
|
||||
if (inStream == null) {
|
||||
// try to open the file
|
||||
final Uri fileUri = Uri.parse(attachment.getContentUri());
|
||||
inStream = context.getContentResolver().openInputStream(fileUri);
|
||||
}
|
||||
}
|
||||
// switch to output stream for base64 text output
|
||||
writer.flush();
|
||||
|
@ -254,8 +275,12 @@ public class Rfc822Output {
|
|||
}
|
||||
catch (FileNotFoundException fnfe) {
|
||||
// Ignore this - empty file is OK
|
||||
LogUtils.e(TAG, fnfe, "Rfc822Output#writeOneAttachment(), FileNotFoundException" +
|
||||
"when sending attachment");
|
||||
}
|
||||
catch (IOException ioe) {
|
||||
LogUtils.e(TAG, ioe, "Rfc822Output#writeOneAttachment(), IOException" +
|
||||
"when sending attachment");
|
||||
throw new MessagingException("Invalid attachment.", ioe);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1150,6 +1150,8 @@ public abstract class EmailContent {
|
|||
// The location of the loaded attachment (probably a file)
|
||||
@SuppressWarnings("hiding")
|
||||
public static final String CONTENT_URI = "contentUri";
|
||||
// The cached location of the attachment
|
||||
public static final String CACHED_FILE = "cachedFile";
|
||||
// A foreign key into the Message table (the message owning this attachment)
|
||||
public static final String MESSAGE_KEY = "messageKey";
|
||||
// The location of the attachment on the server side
|
||||
|
@ -1200,6 +1202,7 @@ public abstract class EmailContent {
|
|||
public long mSize;
|
||||
public String mContentId;
|
||||
private String mContentUri;
|
||||
private String mCachedFile;
|
||||
public long mMessageKey;
|
||||
public String mLocation;
|
||||
public String mEncoding;
|
||||
|
@ -1217,23 +1220,25 @@ public abstract class EmailContent {
|
|||
public static final int CONTENT_SIZE_COLUMN = 3;
|
||||
public static final int CONTENT_CONTENT_ID_COLUMN = 4;
|
||||
public static final int CONTENT_CONTENT_URI_COLUMN = 5;
|
||||
public static final int CONTENT_MESSAGE_ID_COLUMN = 6;
|
||||
public static final int CONTENT_LOCATION_COLUMN = 7;
|
||||
public static final int CONTENT_ENCODING_COLUMN = 8;
|
||||
public static final int CONTENT_CONTENT_COLUMN = 9; // Not currently used
|
||||
public static final int CONTENT_FLAGS_COLUMN = 10;
|
||||
public static final int CONTENT_CONTENT_BYTES_COLUMN = 11;
|
||||
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 12;
|
||||
public static final int CONTENT_UI_STATE_COLUMN = 13;
|
||||
public static final int CONTENT_UI_DESTINATION_COLUMN = 14;
|
||||
public static final int CONTENT_UI_DOWNLOADED_SIZE_COLUMN = 15;
|
||||
public static final int CONTENT_CACHED_FILE_COLUMN = 6;
|
||||
public static final int CONTENT_MESSAGE_ID_COLUMN = 7;
|
||||
public static final int CONTENT_LOCATION_COLUMN = 8;
|
||||
public static final int CONTENT_ENCODING_COLUMN = 9;
|
||||
public static final int CONTENT_CONTENT_COLUMN = 10; // Not currently used
|
||||
public static final int CONTENT_FLAGS_COLUMN = 11;
|
||||
public static final int CONTENT_CONTENT_BYTES_COLUMN = 12;
|
||||
public static final int CONTENT_ACCOUNT_KEY_COLUMN = 13;
|
||||
public static final int CONTENT_UI_STATE_COLUMN = 14;
|
||||
public static final int CONTENT_UI_DESTINATION_COLUMN = 15;
|
||||
public static final int CONTENT_UI_DOWNLOADED_SIZE_COLUMN = 16;
|
||||
public static final String[] CONTENT_PROJECTION = new String[] {
|
||||
RECORD_ID, AttachmentColumns.FILENAME, AttachmentColumns.MIME_TYPE,
|
||||
AttachmentColumns.SIZE, AttachmentColumns.CONTENT_ID, AttachmentColumns.CONTENT_URI,
|
||||
AttachmentColumns.MESSAGE_KEY, AttachmentColumns.LOCATION, AttachmentColumns.ENCODING,
|
||||
AttachmentColumns.CONTENT, AttachmentColumns.FLAGS, AttachmentColumns.CONTENT_BYTES,
|
||||
AttachmentColumns.ACCOUNT_KEY, AttachmentColumns.UI_STATE,
|
||||
AttachmentColumns.UI_DESTINATION, AttachmentColumns.UI_DOWNLOADED_SIZE
|
||||
AttachmentColumns.CACHED_FILE, AttachmentColumns.MESSAGE_KEY,
|
||||
AttachmentColumns.LOCATION, AttachmentColumns.ENCODING, AttachmentColumns.CONTENT,
|
||||
AttachmentColumns.FLAGS, AttachmentColumns.CONTENT_BYTES, AttachmentColumns.ACCOUNT_KEY,
|
||||
AttachmentColumns.UI_STATE, AttachmentColumns.UI_DESTINATION,
|
||||
AttachmentColumns.UI_DOWNLOADED_SIZE
|
||||
};
|
||||
|
||||
// All attachments with an empty URI, regardless of mailbox
|
||||
|
@ -1275,6 +1280,14 @@ public abstract class EmailContent {
|
|||
mBaseUri = CONTENT_URI;
|
||||
}
|
||||
|
||||
public void setCachedFilePath(String cachedFile) {
|
||||
mCachedFile = cachedFile;
|
||||
}
|
||||
|
||||
public String getCachedFilePath() {
|
||||
return mCachedFile;
|
||||
}
|
||||
|
||||
public void setContentUri(String contentUri) {
|
||||
mContentUri = contentUri;
|
||||
}
|
||||
|
@ -1376,6 +1389,7 @@ public abstract class EmailContent {
|
|||
mSize = cursor.getLong(CONTENT_SIZE_COLUMN);
|
||||
mContentId = cursor.getString(CONTENT_CONTENT_ID_COLUMN);
|
||||
mContentUri = cursor.getString(CONTENT_CONTENT_URI_COLUMN);
|
||||
mCachedFile = cursor.getString(CONTENT_CACHED_FILE_COLUMN);
|
||||
mMessageKey = cursor.getLong(CONTENT_MESSAGE_ID_COLUMN);
|
||||
mLocation = cursor.getString(CONTENT_LOCATION_COLUMN);
|
||||
mEncoding = cursor.getString(CONTENT_ENCODING_COLUMN);
|
||||
|
@ -1396,6 +1410,7 @@ public abstract class EmailContent {
|
|||
values.put(AttachmentColumns.SIZE, mSize);
|
||||
values.put(AttachmentColumns.CONTENT_ID, mContentId);
|
||||
values.put(AttachmentColumns.CONTENT_URI, mContentUri);
|
||||
values.put(AttachmentColumns.CACHED_FILE, mCachedFile);
|
||||
values.put(AttachmentColumns.MESSAGE_KEY, mMessageKey);
|
||||
values.put(AttachmentColumns.LOCATION, mLocation);
|
||||
values.put(AttachmentColumns.ENCODING, mEncoding);
|
||||
|
@ -1423,6 +1438,7 @@ public abstract class EmailContent {
|
|||
dest.writeLong(mSize);
|
||||
dest.writeString(mContentId);
|
||||
dest.writeString(mContentUri);
|
||||
dest.writeString(mCachedFile);
|
||||
dest.writeLong(mMessageKey);
|
||||
dest.writeString(mLocation);
|
||||
dest.writeString(mEncoding);
|
||||
|
@ -1448,6 +1464,7 @@ public abstract class EmailContent {
|
|||
mSize = in.readLong();
|
||||
mContentId = in.readString();
|
||||
mContentUri = in.readString();
|
||||
mCachedFile = in.readString();
|
||||
mMessageKey = in.readLong();
|
||||
mLocation = in.readString();
|
||||
mEncoding = in.readString();
|
||||
|
@ -1482,9 +1499,10 @@ public abstract class EmailContent {
|
|||
@Override
|
||||
public String toString() {
|
||||
return "[" + mFileName + ", " + mMimeType + ", " + mSize + ", " + mContentId + ", "
|
||||
+ mContentUri + ", " + mMessageKey + ", " + mLocation + ", " + mEncoding + ", "
|
||||
+ mFlags + ", " + mContentBytes + ", " + mAccountKey + "," + mUiState + ","
|
||||
+ mUiDestination + "," + mUiDownloadedSize + "]";
|
||||
+ mContentUri + ", " + mCachedFile + ", " + mMessageKey + ", "
|
||||
+ mLocation + ", " + mEncoding + ", " + mFlags + ", " + mContentBytes + ", "
|
||||
+ mAccountKey + "," + mUiState + "," + mUiDestination + ","
|
||||
+ mUiDownloadedSize + "]";
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -58,6 +58,10 @@ public class AttachmentUtilities {
|
|||
public static final String SIZE = "_size";
|
||||
}
|
||||
|
||||
private static final String[] ATTACHMENT_CACHED_FILE_PROJECTION = new String[] {
|
||||
AttachmentColumns.CACHED_FILE
|
||||
};
|
||||
|
||||
/**
|
||||
* The MIME type(s) of attachments we're willing to send via attachments.
|
||||
*
|
||||
|
@ -299,6 +303,34 @@ public class AttachmentUtilities {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a message, find all attachments and delete associated cached
|
||||
* attachment files.
|
||||
* @param context
|
||||
* @param accountId the account for the message
|
||||
* @param messageId the message
|
||||
*/
|
||||
public static void deleteAllCachedAttachmentFiles(Context context, long accountId,
|
||||
long messageId) {
|
||||
final Uri uri = ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, messageId);
|
||||
final Cursor c = context.getContentResolver().query(uri, ATTACHMENT_CACHED_FILE_PROJECTION,
|
||||
null, null, null);
|
||||
try {
|
||||
while (c.moveToNext()) {
|
||||
final String fileName = c.getString(0);
|
||||
if (!TextUtils.isEmpty(fileName)) {
|
||||
final File cachedFile = new File(fileName);
|
||||
// Note, delete() throws no exceptions for basic FS errors (e.g. file not found)
|
||||
// it just returns false, which we ignore, and proceed to the next file.
|
||||
// This entire loop is best-effort only.
|
||||
cachedFile.delete();
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
c.close();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* In support of deleting a mailbox, find all messages and delete their attachments.
|
||||
*
|
||||
|
|
|
@ -57,6 +57,7 @@ import com.android.emailcommon.provider.ProviderUnavailableException;
|
|||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileDescriptor;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
@ -744,14 +745,30 @@ public class Utility {
|
|||
} else if (attachment.mContentBytes != null) {
|
||||
return true;
|
||||
} else {
|
||||
String contentUri = attachment.getContentUri();
|
||||
final String cachedFile = attachment.getCachedFilePath();
|
||||
// Try the cached file first
|
||||
if (!TextUtils.isEmpty(cachedFile)) {
|
||||
try {
|
||||
final InputStream inStream = new FileInputStream(cachedFile);
|
||||
try {
|
||||
inStream.close();
|
||||
} catch (IOException e) {
|
||||
// Nothing to be done if can't close the stream
|
||||
}
|
||||
return true;
|
||||
} catch (FileNotFoundException e) {
|
||||
// We weren't able to open the file, try the content uri below
|
||||
}
|
||||
}
|
||||
final String contentUri = attachment.getContentUri();
|
||||
if (TextUtils.isEmpty(contentUri)) {
|
||||
return false;
|
||||
}
|
||||
try {
|
||||
Uri fileUri = Uri.parse(contentUri);
|
||||
final Uri fileUri = Uri.parse(contentUri);
|
||||
try {
|
||||
InputStream inStream = context.getContentResolver().openInputStream(fileUri);
|
||||
final InputStream inStream =
|
||||
context.getContentResolver().openInputStream(fileUri);
|
||||
try {
|
||||
inStream.close();
|
||||
} catch (IOException e) {
|
||||
|
|
|
@ -132,8 +132,9 @@ public final class DBHelper {
|
|||
// Version 104&105: add syncData to Message
|
||||
// Version 106: Add certificate to HostAuth
|
||||
// Version 107: Add a SEEN column to the message table
|
||||
// Version 108: Add a cachedFile column to the attachments table
|
||||
|
||||
public static final int DATABASE_VERSION = 107;
|
||||
public static final int DATABASE_VERSION = 108;
|
||||
|
||||
// Any changes to the database format *must* include update-in-place code.
|
||||
// Original version: 2
|
||||
|
@ -453,7 +454,8 @@ public final class DBHelper {
|
|||
+ AttachmentColumns.ACCOUNT_KEY + " integer, "
|
||||
+ AttachmentColumns.UI_STATE + " integer, "
|
||||
+ AttachmentColumns.UI_DESTINATION + " integer, "
|
||||
+ AttachmentColumns.UI_DOWNLOADED_SIZE + " integer"
|
||||
+ AttachmentColumns.UI_DOWNLOADED_SIZE + " integer, "
|
||||
+ AttachmentColumns.CACHED_FILE + " text"
|
||||
+ ");";
|
||||
db.execSQL("create table " + Attachment.TABLE_NAME + s);
|
||||
db.execSQL(createIndex(Attachment.TABLE_NAME, AttachmentColumns.MESSAGE_KEY));
|
||||
|
@ -1028,6 +1030,17 @@ public final class DBHelper {
|
|||
}
|
||||
oldVersion = 107;
|
||||
}
|
||||
if (oldVersion == 107) {
|
||||
try {
|
||||
db.execSQL("alter table " + Attachment.TABLE_NAME
|
||||
+ " add column " + Attachment.CACHED_FILE +" text" + ";");
|
||||
oldVersion = 108;
|
||||
} catch (SQLException e) {
|
||||
// Shouldn't be needed unless we're debugging and interrupt the process
|
||||
Log.w(TAG, "Exception upgrading EmailProvider.db from v107 to v108", e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -88,6 +88,7 @@ import com.android.mail.providers.UIProvider.ConversationPriority;
|
|||
import com.android.mail.providers.UIProvider.ConversationSendingState;
|
||||
import com.android.mail.providers.UIProvider.DraftType;
|
||||
import com.android.mail.providers.UIProvider.Swipe;
|
||||
import com.android.mail.utils.AttachmentUtils;
|
||||
import com.android.mail.utils.LogUtils;
|
||||
import com.android.mail.utils.MatrixCursorWithCachedColumns;
|
||||
import com.android.mail.utils.MatrixCursorWithExtra;
|
||||
|
@ -3529,12 +3530,16 @@ outer:
|
|||
* Convert a UIProvider attachment to an EmailProvider attachment (for sending); we only need
|
||||
* a few of the fields
|
||||
* @param uiAtt the UIProvider attachment to convert
|
||||
* @param cachedFile the path to the cached file to
|
||||
* @return the EmailProvider attachment
|
||||
*/
|
||||
// TODO(pwestbro): once the Attachment contains the cached uri, the second parameter can be
|
||||
// removed
|
||||
private static Attachment convertUiAttachmentToAttachment(
|
||||
com.android.mail.providers.Attachment uiAtt) {
|
||||
Attachment att = new Attachment();
|
||||
com.android.mail.providers.Attachment uiAtt, String cachedFile) {
|
||||
final Attachment att = new Attachment();
|
||||
att.setContentUri(uiAtt.contentUri.toString());
|
||||
att.setCachedFilePath(cachedFile);
|
||||
att.mFileName = uiAtt.getName();
|
||||
att.mMimeType = uiAtt.getContentType();
|
||||
att.mSize = uiAtt.size;
|
||||
|
@ -3624,10 +3629,11 @@ outer:
|
|||
* @param values the content values that represent message fields
|
||||
* @return the uri of the newly created message
|
||||
*/
|
||||
private Uri uiSaveMessage(Message msg, Mailbox mailbox, ContentValues values) {
|
||||
Context context = getContext();
|
||||
private Uri uiSaveMessage(Message msg, Mailbox mailbox, ContentValues values,
|
||||
Bundle attachmentFds) {
|
||||
final Context context = getContext();
|
||||
// Fill in the message
|
||||
Account account = Account.restoreAccountWithId(context, mailbox.mAccountKey);
|
||||
final Account account = Account.restoreAccountWithId(context, mailbox.mAccountKey);
|
||||
if (account == null) return null;
|
||||
msg.mFrom = account.mEmailAddress;
|
||||
msg.mTimeStamp = System.currentTimeMillis();
|
||||
|
@ -3643,10 +3649,11 @@ outer:
|
|||
msg.mFlagLoaded = Message.FLAG_LOADED_COMPLETE;
|
||||
msg.mFlagRead = true;
|
||||
msg.mFlagSeen = true;
|
||||
Integer quoteStartPos = values.getAsInteger(UIProvider.MessageColumns.QUOTE_START_POS);
|
||||
final Integer quoteStartPos =
|
||||
values.getAsInteger(UIProvider.MessageColumns.QUOTE_START_POS);
|
||||
msg.mQuotedTextStartPos = quoteStartPos == null ? 0 : quoteStartPos;
|
||||
int flags = 0;
|
||||
int draftType = values.getAsInteger(UIProvider.MessageColumns.DRAFT_TYPE);
|
||||
final int draftType = values.getAsInteger(UIProvider.MessageColumns.DRAFT_TYPE);
|
||||
switch(draftType) {
|
||||
case DraftType.FORWARD:
|
||||
flags |= Message.FLAG_TYPE_FORWARD;
|
||||
|
@ -3674,7 +3681,7 @@ outer:
|
|||
msg.mDraftInfo = draftInfo;
|
||||
msg.mFlags = flags;
|
||||
|
||||
String ref = values.getAsString(UIProvider.MessageColumns.REF_MESSAGE_ID);
|
||||
final String ref = values.getAsString(UIProvider.MessageColumns.REF_MESSAGE_ID);
|
||||
if (ref != null && msg.mQuotedTextStartPos >= 0) {
|
||||
String refId = Uri.parse(ref).getLastPathSegment();
|
||||
try {
|
||||
|
@ -3686,24 +3693,24 @@ outer:
|
|||
}
|
||||
|
||||
// Get attachments from the ContentValues
|
||||
List<com.android.mail.providers.Attachment> uiAtts =
|
||||
final List<com.android.mail.providers.Attachment> uiAtts =
|
||||
com.android.mail.providers.Attachment.fromJSONArray(
|
||||
values.getAsString(UIProvider.MessageColumns.ATTACHMENTS));
|
||||
ArrayList<Attachment> atts = new ArrayList<Attachment>();
|
||||
final ArrayList<Attachment> atts = new ArrayList<Attachment>();
|
||||
boolean hasUnloadedAttachments = false;
|
||||
for (com.android.mail.providers.Attachment uiAtt: uiAtts) {
|
||||
Uri attUri = uiAtt.uri;
|
||||
final Uri attUri = uiAtt.uri;
|
||||
if (attUri != null && attUri.getAuthority().equals(EmailContent.AUTHORITY)) {
|
||||
// If it's one of ours, retrieve the attachment and add it to the list
|
||||
long attId = Long.parseLong(attUri.getLastPathSegment());
|
||||
Attachment att = Attachment.restoreAttachmentWithId(context, attId);
|
||||
final long attId = Long.parseLong(attUri.getLastPathSegment());
|
||||
final Attachment att = Attachment.restoreAttachmentWithId(context, attId);
|
||||
if (att != null) {
|
||||
// We must clone the attachment into a new one for this message; easiest to
|
||||
// use a parcel here
|
||||
Parcel p = Parcel.obtain();
|
||||
final Parcel p = Parcel.obtain();
|
||||
att.writeToParcel(p, 0);
|
||||
p.setDataPosition(0);
|
||||
Attachment attClone = new Attachment(p);
|
||||
final Attachment attClone = new Attachment(p);
|
||||
p.recycle();
|
||||
// Clear the messageKey (this is going to be a new attachment)
|
||||
attClone.mMessageKey = 0;
|
||||
|
@ -3717,8 +3724,13 @@ outer:
|
|||
atts.add(attClone);
|
||||
}
|
||||
} else {
|
||||
// Cache the attachment. This will allow us to send it, if the permissions are
|
||||
// revoked
|
||||
final String cachedFileUri =
|
||||
AttachmentUtils.cacheAttachmentUri(context, uiAtt, attachmentFds);
|
||||
|
||||
// Convert external attachment to one of ours and add to the list
|
||||
atts.add(convertUiAttachmentToAttachment(uiAtt));
|
||||
atts.add(convertUiAttachmentToAttachment(uiAtt, cachedFileUri));
|
||||
}
|
||||
}
|
||||
if (!atts.isEmpty()) {
|
||||
|
@ -3734,7 +3746,8 @@ outer:
|
|||
} else {
|
||||
// This is tricky due to how messages/attachments are saved; rather than putz with
|
||||
// what's changed, we'll delete/re-add them
|
||||
ArrayList<ContentProviderOperation> ops = new ArrayList<ContentProviderOperation>();
|
||||
final ArrayList<ContentProviderOperation> ops =
|
||||
new ArrayList<ContentProviderOperation>();
|
||||
// Delete all existing attachments
|
||||
ops.add(ContentProviderOperation.newDelete(
|
||||
ContentUris.withAppendedId(Attachment.MESSAGE_ID_URI, msg.mId))
|
||||
|
@ -3752,18 +3765,18 @@ outer:
|
|||
}
|
||||
}
|
||||
if (mailbox.mType == Mailbox.TYPE_OUTBOX) {
|
||||
EmailServiceProxy service = EmailServiceUtils.getServiceForAccount(context,
|
||||
final EmailServiceProxy service = EmailServiceUtils.getServiceForAccount(context,
|
||||
mServiceCallback, mailbox.mAccountKey);
|
||||
try {
|
||||
service.startSync(mailbox.mId, true);
|
||||
} catch (RemoteException e) {
|
||||
}
|
||||
long originalMsgId = msg.mSourceKey;
|
||||
final long originalMsgId = msg.mSourceKey;
|
||||
if (originalMsgId != 0) {
|
||||
Message originalMsg = Message.restoreMessageWithId(context, originalMsgId);
|
||||
final Message originalMsg = Message.restoreMessageWithId(context, originalMsgId);
|
||||
// If the original message exists, set its forwarded/replied to flags
|
||||
if (originalMsg != null) {
|
||||
ContentValues cv = new ContentValues();
|
||||
final ContentValues cv = new ContentValues();
|
||||
flags = originalMsg.mFlags;
|
||||
switch(draftType) {
|
||||
case DraftType.FORWARD:
|
||||
|
@ -3795,7 +3808,7 @@ outer:
|
|||
if (mailbox == null) return null;
|
||||
Message msg = getMessageFromPathSegments(pathSegments);
|
||||
try {
|
||||
return uiSaveMessage(msg, mailbox, values);
|
||||
return uiSaveMessage(msg, mailbox, values, null);
|
||||
} finally {
|
||||
// Kick observers
|
||||
getContext().getContentResolver().notifyChange(Mailbox.CONTENT_URI, null);
|
||||
|
@ -3813,21 +3826,27 @@ outer:
|
|||
Mailbox mailbox = getMailboxByAccountIdAndType(pathSegments.get(1), Mailbox.TYPE_DRAFTS);
|
||||
if (mailbox == null) return null;
|
||||
Message msg = getMessageFromPathSegments(pathSegments);
|
||||
return uiSaveMessage(msg, mailbox, values);
|
||||
return uiSaveMessage(msg, mailbox, values, null);
|
||||
}
|
||||
|
||||
private Uri uiSaveDraftMessageBundle(Uri accountUri, Bundle extras) {
|
||||
List<String> pathSegments = accountUri.getPathSegments();
|
||||
Mailbox mailbox = getMailboxByAccountIdAndType(pathSegments.get(1), Mailbox.TYPE_DRAFTS);
|
||||
final List<String> pathSegments = accountUri.getPathSegments();
|
||||
final Mailbox mailbox =
|
||||
getMailboxByAccountIdAndType(pathSegments.get(1), Mailbox.TYPE_DRAFTS);
|
||||
if (mailbox == null) return null;
|
||||
final ContentValues values = translateMessage(extras);
|
||||
final Message msg = new Message();
|
||||
return uiSaveMessage(msg, mailbox, values);
|
||||
|
||||
// Get the Bundle of open fds from the extra
|
||||
final Bundle attachmentFds =
|
||||
extras.getParcelable(UIProvider.SendOrSaveMethodParamKeys.OPENED_FD_MAP);
|
||||
|
||||
return uiSaveMessage(msg, mailbox, values, attachmentFds);
|
||||
}
|
||||
|
||||
private Uri uiSendDraftMessageBundle(Uri uri, Bundle extras) {
|
||||
final long accountId = Long.parseLong(uri.getPathSegments().get(1));
|
||||
Context context = getContext();
|
||||
final Context context = getContext();
|
||||
final Message msg;
|
||||
if (extras.containsKey(BaseColumns._ID)) {
|
||||
final long messageId = extras.getLong(BaseColumns._ID);
|
||||
|
@ -3837,12 +3856,16 @@ outer:
|
|||
}
|
||||
|
||||
if (msg == null) return null;
|
||||
long mailboxId = Mailbox.findMailboxOfType(context, accountId, Mailbox.TYPE_OUTBOX);
|
||||
final long mailboxId = Mailbox.findMailboxOfType(context, accountId, Mailbox.TYPE_OUTBOX);
|
||||
if (mailboxId == Mailbox.NO_MAILBOX) return null;
|
||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
|
||||
final Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
|
||||
if (mailbox == null) return null;
|
||||
final ContentValues values = translateMessage(extras);
|
||||
final Uri messageUri = uiSaveMessage(msg, mailbox, values);
|
||||
// Get the Bundle of open fds from the extra
|
||||
final Bundle attachmentFds =
|
||||
extras.getParcelable(UIProvider.SendOrSaveMethodParamKeys.OPENED_FD_MAP);
|
||||
|
||||
final Uri messageUri = uiSaveMessage(msg, mailbox, values, attachmentFds);
|
||||
// Kick observers
|
||||
context.getContentResolver().notifyChange(Mailbox.CONTENT_URI, null);
|
||||
return messageUri;
|
||||
|
@ -3901,7 +3924,7 @@ outer:
|
|||
if (msg == null) return 0;
|
||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(context, msg.mMailboxKey);
|
||||
if (mailbox == null) return 0;
|
||||
uiSaveMessage(msg, mailbox, values);
|
||||
uiSaveMessage(msg, mailbox, values, null);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -3914,7 +3937,7 @@ outer:
|
|||
if (mailboxId == Mailbox.NO_MAILBOX) return 0;
|
||||
Mailbox mailbox = Mailbox.restoreMailboxWithId(context, mailboxId);
|
||||
if (mailbox == null) return 0;
|
||||
uiSaveMessage(msg, mailbox, values);
|
||||
uiSaveMessage(msg, mailbox, values, null);
|
||||
// Kick observers
|
||||
context.getContentResolver().notifyChange(Mailbox.CONTENT_URI, null);
|
||||
return 1;
|
||||
|
|
|
@ -524,26 +524,28 @@ public abstract class EmailServiceStub extends IEmailService.Stub implements IEm
|
|||
continue;
|
||||
}
|
||||
// 4. move to sent, or delete
|
||||
Uri syncedUri =
|
||||
final Uri syncedUri =
|
||||
ContentUris.withAppendedId(EmailContent.Message.SYNCED_CONTENT_URI, messageId);
|
||||
// Delete all cached files
|
||||
AttachmentUtilities.deleteAllCachedAttachmentFiles(context, account.mId, messageId);
|
||||
if (requireMoveMessageToSentFolder) {
|
||||
// If this is a forwarded message and it has attachments, delete them, as they
|
||||
// duplicate information found elsewhere (on the server). This saves storage.
|
||||
EmailContent.Message msg =
|
||||
final EmailContent.Message msg =
|
||||
EmailContent.Message.restoreMessageWithId(context, messageId);
|
||||
if (msg != null &&
|
||||
((msg.mFlags & EmailContent.Message.FLAG_TYPE_FORWARD) != 0)) {
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId,
|
||||
messageId);
|
||||
}
|
||||
int flags = msg.mFlags & ~(EmailContent.Message.FLAG_TYPE_REPLY |
|
||||
final int flags = msg.mFlags & ~(EmailContent.Message.FLAG_TYPE_REPLY |
|
||||
EmailContent.Message.FLAG_TYPE_FORWARD);
|
||||
moveToSentValues.put(EmailContent.MessageColumns.FLAGS, flags);
|
||||
resolver.update(syncedUri, moveToSentValues, null, null);
|
||||
} else {
|
||||
AttachmentUtilities.deleteAllAttachmentFiles(context, account.mId,
|
||||
messageId);
|
||||
Uri uri =
|
||||
final Uri uri =
|
||||
ContentUris.withAppendedId(EmailContent.Message.CONTENT_URI, messageId);
|
||||
resolver.delete(uri, null, null);
|
||||
resolver.delete(syncedUri, null, null);
|
||||
|
|
Loading…
Reference in New Issue