Removed dependency on UIDPLUS

pull/156/head
M66B 6 years ago
parent 5e54bc0c6a
commit fc2840ae30

@ -43,7 +43,6 @@ import com.bugsnag.android.Bugsnag;
import com.sun.mail.iap.CommandFailedException; import com.sun.mail.iap.CommandFailedException;
import com.sun.mail.iap.ConnectionException; import com.sun.mail.iap.ConnectionException;
import com.sun.mail.iap.Response; import com.sun.mail.iap.Response;
import com.sun.mail.imap.AppendUID;
import com.sun.mail.imap.IMAPFolder; import com.sun.mail.imap.IMAPFolder;
import com.sun.mail.imap.IMAPMessage; import com.sun.mail.imap.IMAPMessage;
import com.sun.mail.imap.IMAPStore; import com.sun.mail.imap.IMAPStore;
@ -146,7 +145,6 @@ class Core {
crumb.put("args", op.args); crumb.put("args", op.args);
crumb.put("folder", folder.type); crumb.put("folder", folder.type);
crumb.put("free", Integer.toString(Log.getFreeMemMb())); crumb.put("free", Integer.toString(Log.getFreeMemMb()));
crumb.put("UIDPLUS", Boolean.toString(((IMAPStore) istore).hasCapability("UIDPLUS")));
Bugsnag.leaveBreadcrumb("operation", BreadcrumbType.LOG, crumb); Bugsnag.leaveBreadcrumb("operation", BreadcrumbType.LOG, crumb);
// Fetch most recent copy of message // Fetch most recent copy of message
@ -436,144 +434,120 @@ class Core {
DB db = DB.getInstance(context); DB db = DB.getInstance(context);
// Get arguments // Get arguments
Long tmpid = (jargs.length() > 0 && !jargs.isNull(0) ? jargs.getLong(0) : null); long target = (jargs.length() > 0 ? jargs.getLong(0) : folder.id);
boolean autoread = (jargs.length() > 1 && jargs.getBoolean(1)); boolean autoread = (jargs.length() > 1 && jargs.getBoolean(1));
boolean across = (jargs.length() > 2 && jargs.getBoolean(2));
try { if (target != folder.id)
if (EntityFolder.DRAFTS.equals(folder.type) && throw new IllegalArgumentException("Invalid folder");
!folder.id.equals(message.folder) &&
!across) {
Log.i("Drafts moved folder=" + message.folder);
return;
}
// Delete previous message(s) with same ID // Prevent async deletion
if (folder.id.equals(message.folder)) { if (folder.id.equals(message.folder)) {
// Prevent adding/deleting message if (message.uid != null)
db.message().setMessageUid(message.id, null); db.message().setMessageUid(message.id, null);
}
if (TextUtils.isEmpty(message.msgid)) { // External draft might have a uid only
// Draft might be created somewhere else if (TextUtils.isEmpty(message.msgid)) {
if (message.uid == null) message.msgid = EntityMessage.generateMessageId();
throw new IllegalArgumentException("Add without ID"); db.message().setMessageMsgId(message.id, message.msgid);
else { }
Message idelete = ifolder.getMessageByUID(message.uid);
Log.i(folder.name + " deleting previous uid=" + message.uid + " msgid=" + message.msgid);
try {
idelete.setFlag(Flags.Flag.DELETED, true);
} catch (MessageRemovedException ignored) {
}
}
message.msgid = EntityMessage.generateMessageId();
} else {
Message[] ideletes = ifolder.search(new MessageIDTerm(message.msgid));
for (Message idelete : ideletes) {
long uid = ifolder.getUID(idelete);
Log.i(folder.name + " deleting previous uid=" + uid + " msgid=" + message.msgid);
try {
idelete.setFlag(Flags.Flag.DELETED, true);
} catch (MessageRemovedException ignored) {
}
}
}
ifolder.expunge();
}
// Get message // Get raw message
MimeMessage imessage; MimeMessage imessage;
if (folder.id.equals(message.folder)) { if (folder.id.equals(message.folder)) {
// Pre flight checks // Pre flight checks
if (!message.content) if (!message.content)
throw new IllegalArgumentException("Message body missing"); throw new IllegalArgumentException("Message body missing");
EntityIdentity identity = EntityIdentity identity =
(message.identity == null ? null : db.identity().getIdentity(message.identity)); (message.identity == null ? null : db.identity().getIdentity(message.identity));
imessage = MessageHelper.from(context, message, identity, isession); imessage = MessageHelper.from(context, message, identity, isession);
} else { } else {
// Cross account move // Cross account move
File file = message.getRawFile(context); File file = message.getRawFile(context);
if (!file.exists()) if (!file.exists())
throw new IllegalArgumentException("raw message file not found"); throw new IllegalArgumentException("raw message file not found");
Log.i(folder.name + " reading " + file);
try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
imessage = new MimeMessage(isession, is);
}
}
// Handle auto read Log.i(folder.name + " reading " + file);
if (ifolder.getPermanentFlags().contains(Flags.Flag.SEEN)) { try (InputStream is = new BufferedInputStream(new FileInputStream(file))) {
if (autoread && !imessage.isSet(Flags.Flag.SEEN)) { imessage = new MimeMessage(isession, is);
Log.i(folder.name + " autoread");
imessage.setFlag(Flags.Flag.SEEN, true);
}
} }
}
// Handle draft // Handle auto read
if (EntityFolder.DRAFTS.equals(folder.type)) if (ifolder.getPermanentFlags().contains(Flags.Flag.SEEN)) {
if (ifolder.getPermanentFlags().contains(Flags.Flag.DRAFT)) if (autoread && !imessage.isSet(Flags.Flag.SEEN)) {
imessage.setFlag(Flags.Flag.DRAFT, true); Log.i(folder.name + " autoread");
imessage.setFlag(Flags.Flag.SEEN, true);
// Add message
long uid = -1;
if (istore.hasCapability("UIDPLUS")) {
AppendUID[] uids = ifolder.appendUIDMessages(new Message[]{imessage});
if (uids != null && uids.length > 0) {
Log.i("Appended uid=" + uids[0].uid);
uid = uids[0].uid;
}
} else
ifolder.appendMessages(new Message[]{imessage});
// Lookup uid
if (uid <= 0) {
Log.i("Searching for appended msgid=" + message.msgid);
Message[] messages = ifolder.search(new MessageIDTerm(message.msgid));
if (messages != null)
for (Message iappended : messages) {
long muid = ifolder.getUID(iappended);
Log.i("Found appended uid=" + muid);
// RFC3501: Unique identifiers are assigned in a strictly ascending fashion
if (muid > uid)
uid = muid;
}
} }
}
if (uid <= 0) // Handle draft
throw new IllegalArgumentException("uid not found"); if (EntityFolder.DRAFTS.equals(folder.type))
if (ifolder.getPermanentFlags().contains(Flags.Flag.DRAFT))
Log.i(folder.name + " appended id=" + message.id + " uid=" + uid); imessage.setFlag(Flags.Flag.DRAFT, true);
try {
db.beginTransaction();
if (folder.id.equals(message.folder)) { // Add message
if (EntityFolder.DRAFTS.equals(folder.type)) { ifolder.appendMessages(new Message[]{imessage});
Log.i(folder.name + " Setting id=" + message.id + " uid=" + uid);
db.message().setMessageUid(message.id, uid); if (folder.id.equals(message.folder)) {
} // External draft might have a uid only
} else { if (message.uid != null) {
// Mark source read Message iexisting = ifolder.getMessageByUID(message.uid);
if (autoread) { if (iexisting == null)
Log.i(folder.name + " queuing SEEN id=" + message.id); Log.w(folder.name + " existing not found uid=" + message.uid);
EntityOperation.queue(context, message, EntityOperation.SEEN, true); else
try {
Log.i(folder.name + " deleting uid=" + message.uid);
iexisting.setFlag(Flags.Flag.DELETED, true);
} catch (MessageRemovedException ignored) {
Log.w(folder.name + " existing gone uid=" + message.uid);
} }
}
// Delete source Log.i(folder.name + " searching for msgid=" + message.msgid);
Log.i(folder.name + " queuing DELETE id=" + message.id); Message[] imessages = ifolder.search(new MessageIDTerm(message.msgid));
EntityOperation.queue(context, message, EntityOperation.DELETE); if (imessages == null)
Log.w(folder.name + " search for msgid=" + message.msgid + " returned null");
else {
long uid = -1;
for (Message iexisting : imessages) {
long muid = ifolder.getUID(iexisting);
Log.i(folder.name + " found uid=" + muid);
// RFC3501: Unique identifiers are assigned in a strictly ascending fashion
if (muid > uid)
uid = muid;
} }
db.setTransactionSuccessful(); if (uid < 0)
} finally { Log.w(folder.name + " appended msgid=" + message.msgid + " not found");
db.endTransaction(); else {
Log.i(folder.name + " appended uid=" + uid);
for (Message iexisting : imessages) {
long muid = ifolder.getUID(iexisting);
if (muid != uid)
try {
Log.i(folder.name + " deleting uid=" + muid);
iexisting.setFlag(Flags.Flag.DELETED, true);
} catch (MessageRemovedException ignored) {
Log.w(folder.name + " existing gone uid=" + muid);
}
}
}
} }
} catch (Throwable ex) {
if (folder.id.equals(message.folder)) ifolder.expunge();
db.message().setMessageUid(message.id, message.uid);
throw ex; } else {
// Mark source read
if (autoread)
EntityOperation.queue(context, message, EntityOperation.SEEN, true);
// Delete source
EntityOperation.queue(context, message, EntityOperation.DELETE);
} }
} }
@ -675,9 +649,7 @@ class Core {
if (jargs.length() > 0) { if (jargs.length() > 0) {
// Cross account move // Cross account move
long target = jargs.getLong(2); long target = jargs.getLong(0);
jargs.remove(2);
jargs.put(2, true); // cross account
Log.i(folder.name + " queuing ADD id=" + message.id + ":" + target); Log.i(folder.name + " queuing ADD id=" + message.id + ":" + target);
EntityOperation operation = new EntityOperation(); EntityOperation operation = new EntityOperation();

@ -326,6 +326,9 @@ public interface DaoMessage {
@Query("UPDATE message SET uid = :uid WHERE id = :id") @Query("UPDATE message SET uid = :uid WHERE id = :id")
int setMessageUid(long id, Long uid); int setMessageUid(long id, Long uid);
@Query("UPDATE message SET msgid = :msgid WHERE id = :id")
int setMessageMsgId(long id, String msgid);
@Query("UPDATE message SET seen = :seen WHERE id = :id") @Query("UPDATE message SET seen = :seen WHERE id = :id")
int setMessageSeen(long id, boolean seen); int setMessageSeen(long id, boolean seen);

@ -117,9 +117,8 @@ public class EntityOperation {
else if (MOVE.equals(name)) { else if (MOVE.equals(name)) {
// Parameters: // Parameters:
// 0: target folder id // 0: target folder
// 1: allow auto read // 1: auto read
// 2: temporary target message id
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context); SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(context);
boolean autoread = prefs.getBoolean("autoread", false); boolean autoread = prefs.getBoolean("autoread", false);
@ -144,7 +143,6 @@ public class EntityOperation {
// Create copy without uid in target folder // Create copy without uid in target folder
// Message with same msgid can be in archive // Message with same msgid can be in archive
Long tmpid = null;
if (message.uid != null && if (message.uid != null &&
target.synchronize && target.synchronize &&
message.received > cal_keep.getTimeInMillis() && message.received > cal_keep.getTimeInMillis() &&
@ -171,7 +169,7 @@ public class EntityOperation {
message.ui_browsed = false; message.ui_browsed = false;
message.id = db.message().insertMessage(message); message.id = db.message().insertMessage(message);
File mtarget = message.getFile(context); File mtarget = message.getFile(context);
tmpid = message.id; long tmpid = message.id;
message.id = id; message.id = id;
message.account = source.account; message.account = source.account;
@ -194,25 +192,13 @@ public class EntityOperation {
EntityAttachment.copy(context, message.id, tmpid); EntityAttachment.copy(context, message.id, tmpid);
} }
if (source.account.equals(target.account)) // Cross account move
jargs.put(2, tmpid); // Can be null if (!source.account.equals(target.account))
else {
// Cross account move
if (message.raw != null && message.raw) { if (message.raw != null && message.raw) {
name = ADD; name = ADD;
folder = target.id; folder = target.id;
jargs = new JSONArray(); } else
jargs.put(0, tmpid); // Can be null
jargs.put(1, autoread);
jargs.put(2, true); // Cross account
} else {
name = RAW; name = RAW;
jargs = new JSONArray();
jargs.put(0, tmpid); // Can be null
jargs.put(1, autoread);
jargs.put(2, target.id);
}
}
} else if (DELETE.equals(name)) } else if (DELETE.equals(name))
db.message().setMessageUiHide(message.id, true); db.message().setMessageUiHide(message.id, true);

Loading…
Cancel
Save