Repository: thundernest/k-9
Issue: Opening message and hitting archive doesn't mark the email as read.

### Checklist

- [X] I have used the search function to see if someone else has already submitted the same bug report.
- [X] I will describe the problem with as much detail as possible.

### App version

6.400

### Where did you get the app from?

F-Droid

### Android version

13 / OneUI 5.0

### Device model

Samsung Galaxy A52s 5G

### Steps to reproduce

This happens rarely

1. Open any unread message
2. Hit archive

### Expected behavior

The message should be marked as read and archived.

### Actual behavior

Sometimes (I havent found any pattern yet) some messages are archived but are still in unread state. I think it started with 6.400 version. I noticed it when opening Thunderbird on my computer and noticing that "archive" folder is in bold, indicating that there are unread messages (and I only archived read messages). I'm positive that those messages were archived using mobile/k9-mail. I'm fairly certain I did that when away from home, thus using mobile connection. I think it could be due to either poor network coverage or possibly it could happen when switching from wifi to mobile data.

### Logs

_No response_

Changed files:
app/core/src/main/java/com/fsck/k9/controller/MessagingController.java

diff --git a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java
index dfa2cc252..0d1f491f3 100644
--- a/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java
+++ b/app/core/src/main/java/com/fsck/k9/controller/MessagingController.java
@@ -952,11 +952,8 @@ public class MessagingController {
     }
 
     private void queueSetFlag(Account account, long folderId, boolean newState, Flag flag, List<String> uids) {
-        putBackground("queueSetFlag", null, () -> {
-            PendingCommand command = PendingSetFlag.create(folderId, newState, flag, uids);
-            queuePendingCommand(account, command);
-            processPendingCommands(account);
-        });
+        PendingCommand command = PendingSetFlag.create(folderId, newState, flag, uids);
+        queuePendingCommand(account, command);
     }
 
     /**
@@ -969,11 +966,8 @@ public class MessagingController {
     }
 
     private void queueDelete(Account account, long folderId, List<String> uids) {
-        putBackground("queueDelete", null, () -> {
-            PendingCommand command = PendingDelete.create(folderId, uids);
-            queuePendingCommand(account, command);
-            processPendingCommands(account);
-        });
+        PendingCommand command = PendingDelete.create(folderId, uids);
+        queuePendingCommand(account, command);
     }
 
     void processPendingDelete(PendingDelete command, Account account) throws MessagingException {
@@ -1044,12 +1038,9 @@ public class MessagingController {
 
         setFlagInCache(account, messageIds, flag, newState);
 
-        threadPool.execute(new Runnable() {
-            @Override
-            public void run() {
-                setFlagSynchronous(account, messageIds, flag, newState, false);
-            }
-        });
+        putBackground("setFlag", null, () ->
+            setFlagSynchronous(account, messageIds, flag, newState, false)
+        );
     }
 
     public void setFlagForThreads(final Account account, final List<Long> threadRootIds,
@@ -1057,12 +1048,9 @@ public class MessagingController {
 
         setFlagForThreadsInCache(account, threadRootIds, flag, newState);
 
-        threadPool.execute(new Runnable() {
-            @Override
-            public void run() {
-                setFlagSynchronous(account, threadRootIds, flag, newState, true);
-            }
-        });
+        putBackground("setFlagForThreads", null, () ->
+            setFlagSynchronous(account, threadRootIds, flag, newState, true)
+        );
     }
 
     private void setFlagSynchronous(final Account account, final List<Long> ids,
@@ -1284,36 +1272,49 @@ public class MessagingController {
     }
 
     public void markMessageAsOpened(Account account, LocalMessage message) {
-        put("markMessageAsOpened", null, () -> {
-            markMessageAsOpenedBlocking(account, message);
-        });
-    }
+        threadPool.execute(() ->
+            notificationController.removeNewMailNotification(account, message.makeMessageReference())
+        );
 
-    private void markMessageAsOpenedBlocking(Account account, LocalMessage message) {
-        notificationController.removeNewMailNotification(account,message.makeMessageReference());
+        if (message.isSet(Flag.SEEN)) {
+            // Nothing to do if the message is already marked as read
+            return;
+        }
 
-        if (!message.isSet(Flag.SEEN)) {
-            if (account.isMarkMessageAsReadOnView()) {
-                markMessageAsReadOnView(account, message);
-            } else {
-                // Marking a message as read will automatically mark it as "not new". But if we don't mark the message
-                // as read on opening, we have to manually mark it as "not new".
-                markMessageAsNotNew(account, message);
+        boolean markMessageAsRead = account.isMarkMessageAsReadOnView();
+        if (markMessageAsRead) {
+            // Mark the message itself as read right away
+            try {
+                message.setFlagInternal(Flag.SEEN, true);
+            } catch (MessagingException e) {
+                Timber.e(e, "Error while marking message as read");
             }
-        }
-    }
 
-    private void markMessageAsReadOnView(Account account, LocalMessage message) {
-        try {
+            // Also mark the message as read in the cache
             List<Long> messageIds = Collections.singletonList(message.getDatabaseId());
-            setFlag(account, messageIds, Flag.SEEN, true);
+            setFlagInCache(account, messageIds, Flag.SEEN, true);
+        }
 
-            message.setFlagInternal(Flag.SEEN, true);
-        } catch (MessagingException e) {
-            Timber.e(e, "Error while marking message as read");
+        putBackground("markMessageAsOpened", null, () -> {
+            markMessageAsOpenedBlocking(account, message, markMessageAsRead);
+        });
+    }
+
+    private void markMessageAsOpenedBlocking(Account account, LocalMessage message, boolean markMessageAsRead) {
+        if (markMessageAsRead) {
+            markMessageAsRead(account, message);
+        } else {
+            // Marking a message as read will automatically mark it as "not new". But if we don't mark the message
+            // as read on opening, we have to manually mark it as "not new".
+            markMessageAsNotNew(account, message);
         }
     }
 
+    private void markMessageAsRead(Account account, LocalMessage message) {
+        List<Long> messageIds = Collections.singletonList(message.getDatabaseId());
+        setFlagSynchronous(account, messageIds, Flag.SEEN, true, false);
+    }
+
     private void markMessageAsNotNew(Account account, LocalMessage message) {
         MessageStore messageStore = messageStoreManager.getMessageStore(account);
         long folderId = message.getFolder().getDatabaseId();