diff --git a/app/src/main/java/eu/faircode/email/MessageHelper.java b/app/src/main/java/eu/faircode/email/MessageHelper.java index edfc0f7a66..4ee293e189 100644 --- a/app/src/main/java/eu/faircode/email/MessageHelper.java +++ b/app/src/main/java/eu/faircode/email/MessageHelper.java @@ -82,8 +82,8 @@ public class MessageHelper { return props; } - static MimeMessage from(EntityMessage message, Session isession) throws MessagingException { - MimeMessage imessage = new MimeMessage(isession); + static MimeMessageEx from(EntityMessage message, Session isession) throws MessagingException { + MimeMessageEx imessage = new MimeMessageEx(isession, message.id); if (message.from != null) { Address[] from = MessageHelper.decodeAddresses(message.from); @@ -111,8 +111,8 @@ public class MessageHelper { return imessage; } - static MimeMessage from(EntityMessage message, EntityMessage reply, Session isession) throws MessagingException { - MimeMessage imessage = from(message, isession); + static MimeMessageEx from(EntityMessage message, EntityMessage reply, Session isession) throws MessagingException { + MimeMessageEx imessage = from(message, isession); imessage.addHeader("In-Reply-To", reply.msgid); imessage.addHeader("References", (reply.references == null ? "" : reply.references + " ") + reply.msgid); return imessage; diff --git a/app/src/main/java/eu/faircode/email/MimeMessageEx.java b/app/src/main/java/eu/faircode/email/MimeMessageEx.java new file mode 100644 index 0000000000..7e6bf8e7b5 --- /dev/null +++ b/app/src/main/java/eu/faircode/email/MimeMessageEx.java @@ -0,0 +1,64 @@ +package eu.faircode.email; + +import android.text.TextUtils; +import android.util.Log; + +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; + +import javax.mail.MessagingException; +import javax.mail.Session; +import javax.mail.internet.MimeMessage; + +public class MimeMessageEx extends MimeMessage { + private long id = -1; + + public MimeMessageEx(Session session, long id) { + super(session); + this.id = id; + } + + @Override + protected void updateMessageID() throws MessagingException { + try { + StringBuffer sb = new StringBuffer(); + sb.append('<') + .append(id).append('.') + .append(BuildConfig.APPLICATION_ID).append('.') + .append(System.currentTimeMillis()).append('.') + .append("anonymous@localhost") + .append('>'); + + setHeader("Message-ID", sb.toString()); + Log.i(Helper.TAG, "Override Message-ID=" + sb.toString()); + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + super.updateMessageID(); + } + } + + public static long getId(MimeMessage message) { + try { + String msgid = message.getMessageID(); + if (msgid == null) + return -1; + + List parts = new ArrayList<>(Arrays.asList(msgid.split("\\."))); + if (parts.size() < 1) + return -1; + + String part = parts.get(0); + parts.remove(0); + if (!TextUtils.join(".", parts).startsWith(BuildConfig.APPLICATION_ID)) + return -1; + + long id = Long.parseLong(part.substring(1)); + Log.i(Helper.TAG, "Parsed Message-ID=" + msgid + " id=" + id); + return id; + } catch (Throwable ex) { + Log.e(Helper.TAG, ex + "\n" + Log.getStackTraceString(ex)); + return -1; + } + } +} diff --git a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java index 1a853ca275..8a13d8bca3 100644 --- a/app/src/main/java/eu/faircode/email/ServiceSynchronize.java +++ b/app/src/main/java/eu/faircode/email/ServiceSynchronize.java @@ -711,18 +711,13 @@ public class ServiceSynchronize extends LifecycleService { ifolder.appendMessages(new Message[]{imessage}); // Drafts can be appended multiple times - try { - if (msg.uid != null) { - Message previously = ifolder.getMessageByUID(msg.uid); - if (previously == null) - throw new MessageRemovedException(); + if (msg.uid != null) { + Message previously = ifolder.getMessageByUID(msg.uid); + if (previously == null) + throw new MessageRemovedException(); - previously.setFlag(Flags.Flag.DELETED, true); - ifolder.expunge(); - } - } finally { - // Remote will report appended - message.deleteMessage(op.message); + previously.setFlag(Flags.Flag.DELETED, true); + ifolder.expunge(); } } else if (EntityOperation.MOVE.equals(op.name)) { @@ -789,7 +784,9 @@ public class ServiceSynchronize extends LifecycleService { Log.i(Helper.TAG, "Sent via " + ident.host + "/" + ident.user + " to " + TextUtils.join(", ", to)); - message.deleteMessage(op.message); + msg.ui_hide = true; + message.updateMessage(msg); + // TODO: purge sent messages } finally { itransport.close(); } @@ -1002,13 +999,14 @@ public class ServiceSynchronize extends LifecycleService { } private void synchronizeMessage(EntityFolder folder, IMAPFolder ifolder, IMAPMessage imessage) throws MessagingException, JSONException, IOException { - FetchProfile fp = new FetchProfile(); - fp.add(UIDFolder.FetchProfileItem.UID); - fp.add(IMAPFolder.FetchProfileItem.FLAGS); - ifolder.fetch(new Message[]{imessage}, fp); - - long uid = ifolder.getUID(imessage); + long uid = -1; try { + FetchProfile fp = new FetchProfile(); + fp.add(UIDFolder.FetchProfileItem.UID); + fp.add(IMAPFolder.FetchProfileItem.FLAGS); + ifolder.fetch(new Message[]{imessage}, fp); + + uid = ifolder.getUID(imessage); Log.i(Helper.TAG, folder.name + " start sync uid=" + uid); if (imessage.isExpunged()) { @@ -1033,7 +1031,12 @@ public class ServiceSynchronize extends LifecycleService { fp1.add(IMAPFolder.FetchProfileItem.MESSAGE); ifolder.fetch(new Message[]{imessage}, fp1); - message = new EntityMessage(); + long id = MimeMessageEx.getId(imessage); + message = db.message().getMessage(id); + boolean update = (message != null); + if (message == null) + message = new EntityMessage(); + message.account = folder.account; message.folder = folder.id; message.uid = uid; @@ -1054,8 +1057,13 @@ public class ServiceSynchronize extends LifecycleService { message.ui_seen = seen; message.ui_hide = false; - message.id = db.message().insertMessage(message); - Log.i(Helper.TAG, folder.name + " added id=" + message.id); + if (update) { + db.message().updateMessage(message); + Log.i(Helper.TAG, folder.name + " updated id=" + message.id); + } else { + message.id = db.message().insertMessage(message); + Log.i(Helper.TAG, folder.name + " added id=" + message.id); + } int sequence = 0; for (EntityAttachment attachment : helper.getAttachments()) { @@ -1066,7 +1074,6 @@ public class ServiceSynchronize extends LifecycleService { attachment.sequence = sequence; attachment.id = db.attachment().insertAttachment(attachment); } - } else if (message.seen != seen) { message.seen = seen; message.ui_seen = seen; @@ -1074,6 +1081,7 @@ public class ServiceSynchronize extends LifecycleService { db.message().updateMessage(message); Log.i(Helper.TAG, folder.name + " updated id=" + message.id); } + } finally { Log.i(Helper.TAG, folder.name + " end sync uid=" + uid); }