You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@james.apache.org by bt...@apache.org on 2021/09/06 07:34:02 UTC
[james-project] branch master updated: JAMES-3642 Fix Buggy
behavior with Android Email mobile application (#629)
This is an automated email from the ASF dual-hosted git repository.
btellier pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push:
new d7e8b78 JAMES-3642 Fix Buggy behavior with Android Email mobile application (#629)
d7e8b78 is described below
commit d7e8b782835b301f4a3f86ae5a3de1fd7b8de9be
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Mon Sep 6 14:33:42 2021 +0700
JAMES-3642 Fix Buggy behavior with Android Email mobile application (#629)
Co-authored-by: Rene Cordier <re...@gmail.com>
---
protocols/imap/pom.xml | 8 +-
.../imap/processor/AbstractMailboxProcessor.java | 18 +--
.../imap/processor/AbstractSelectionProcessor.java | 2 +-
.../james/imap/processor/fetch/FetchProcessor.java | 2 +-
.../james/imap/processor/SelectProcessorTest.java | 173 +++++++++++++++++++++
5 files changed, 191 insertions(+), 12 deletions(-)
diff --git a/protocols/imap/pom.xml b/protocols/imap/pom.xml
index 92e5b4f..d462ac7 100644
--- a/protocols/imap/pom.xml
+++ b/protocols/imap/pom.xml
@@ -45,7 +45,13 @@
</dependency>
<dependency>
<groupId>${james.groupId}</groupId>
- <artifactId>apache-james-mailbox-store</artifactId>
+ <artifactId>apache-james-mailbox-memory</artifactId>
+ <scope>test</scope>
+ </dependency>
+ <dependency>
+ <groupId>${james.groupId}</groupId>
+ <artifactId>apache-james-mailbox-memory</artifactId>
+ <type>test-jar</type>
<scope>test</scope>
</dependency>
<dependency>
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
index e02e99b..786a7e7 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractMailboxProcessor.java
@@ -24,7 +24,6 @@ import java.util.Iterator;
import java.util.List;
import java.util.Optional;
import java.util.Set;
-import java.util.stream.Stream;
import javax.mail.Flags;
@@ -535,7 +534,7 @@ public abstract class AbstractMailboxProcessor<R extends ImapRequest> extends Ab
/**
* Send VANISHED responses if needed.
*/
- protected void respondVanished(MailboxSession session, MessageManager mailbox, List<MessageRange> ranges, long changedSince, MailboxMetaData metaData, Responder responder) throws MailboxException {
+ protected void respondVanished(SelectedMailbox selectedMailbox, List<MessageRange> ranges, long changedSince, MailboxMetaData metaData, Responder responder) throws MailboxException {
// RFC5162 4.2. Server Implementations Storing Minimal State
//
// A server that stores the HIGHESTMODSEQ value at the time of the last
@@ -561,16 +560,17 @@ public abstract class AbstractMailboxProcessor<R extends ImapRequest> extends Ab
MessageUid from = nr.getLowValue();
MessageUid to = nr.getHighValue();
while (from.compareTo(to) <= 0) {
- vanishedUids.add(from);
+ MessageUid copy = from;
+ selectedMailbox.msn(from).fold(
+ () -> vanishedUids.add(copy),
+ msn -> {
+ // ignore still there
+ return true;
+ });
from = from.next();
}
nRanges[i] = nr;
-
- }
- searchQuery.andCriteria(SearchQuery.uid(nRanges));
- searchQuery.andCriteria(SearchQuery.modSeqGreaterThan(changedSince));
- try (Stream<MessageUid> uids = Flux.from(mailbox.search(searchQuery.build(), session)).toStream()) {
- uids.forEach(vanishedUids::remove);
+
}
UidRange[] vanishedIdRanges = uidRanges(MessageRange.toRanges(vanishedUids));
responder.respond(new VanishedResponse(vanishedIdRanges, true));
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
index 556aa38..0230e86 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/AbstractSelectionProcessor.java
@@ -299,7 +299,7 @@ abstract class AbstractSelectionProcessor<R extends AbstractMailboxSelectionRequ
// expunges have not happened, or happen only toward the end of the
// mailbox.
//
- respondVanished(mailboxSession, mailbox, ranges, modSeq, metaData, responder);
+ respondVanished(selected, ranges, modSeq, metaData, responder);
}
taggedOk(responder, request, metaData, HumanReadableText.SELECT);
} else {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
index 8be367d..74b02cc 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchProcessor.java
@@ -112,7 +112,7 @@ public class FetchProcessor extends AbstractMailboxProcessor<FetchRequest> {
if (vanished) {
// TODO: From the QRESYNC RFC it seems ok to send the VANISHED responses after the FETCH Responses.
// If we do so we could prolly save one mailbox access which should give use some more speed up
- respondVanished(mailboxSession, mailbox, ranges, changedSince, metaData.get(), responder);
+ respondVanished(session.getSelected(), ranges, changedSince, metaData.get(), responder);
}
processMessageRanges(session, mailbox, ranges, fetch, useUids, mailboxSession, responder);
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/processor/SelectProcessorTest.java b/protocols/imap/src/test/java/org/apache/james/imap/processor/SelectProcessorTest.java
new file mode 100644
index 0000000..97eb73f
--- /dev/null
+++ b/protocols/imap/src/test/java/org/apache/james/imap/processor/SelectProcessorTest.java
@@ -0,0 +1,173 @@
+/****************************************************************
+ * Licensed to the Apache Software Foundation (ASF) under one *
+ * or more contributor license agreements. See the NOTICE file *
+ * distributed with this work for additional information *
+ * regarding copyright ownership. The ASF licenses this file *
+ * to you under the Apache License, Version 2.0 (the *
+ * "License"); you may not use this file except in compliance *
+ * with the License. You may obtain a copy of the License at *
+ * *
+ * http://www.apache.org/licenses/LICENSE-2.0 *
+ * *
+ * Unless required by applicable law or agreed to in writing, *
+ * software distributed under the License is distributed on an *
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY *
+ * KIND, either express or implied. See the License for the *
+ * specific language governing permissions and limitations *
+ * under the License. *
+ ****************************************************************/
+
+package org.apache.james.imap.processor;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.io.ByteArrayOutputStream;
+
+import javax.mail.Flags;
+import javax.mail.util.SharedByteArrayInputStream;
+
+import org.apache.james.core.Username;
+import org.apache.james.imap.api.ImapConfiguration;
+import org.apache.james.imap.api.ImapConstants;
+import org.apache.james.imap.api.ImapMessage;
+import org.apache.james.imap.api.Tag;
+import org.apache.james.imap.api.message.IdRange;
+import org.apache.james.imap.api.message.UidRange;
+import org.apache.james.imap.api.process.ImapProcessor;
+import org.apache.james.imap.api.process.ImapSession;
+import org.apache.james.imap.decode.main.OutputStreamImapResponseWriter;
+import org.apache.james.imap.encode.FakeImapSession;
+import org.apache.james.imap.encode.base.ImapResponseComposerImpl;
+import org.apache.james.imap.encode.main.DefaultImapEncoderFactory;
+import org.apache.james.imap.encode.main.DefaultLocalizer;
+import org.apache.james.imap.main.ResponseEncoder;
+import org.apache.james.imap.message.request.AbstractMailboxSelectionRequest;
+import org.apache.james.imap.message.request.SelectRequest;
+import org.apache.james.imap.message.response.UnpooledStatusResponseFactory;
+import org.apache.james.mailbox.MailboxSession;
+import org.apache.james.mailbox.MessageManager;
+import org.apache.james.mailbox.inmemory.InMemoryMailboxManager;
+import org.apache.james.mailbox.inmemory.manager.InMemoryIntegrationResources;
+import org.apache.james.mailbox.model.MailboxPath;
+import org.apache.james.mailbox.model.UidValidity;
+import org.apache.james.metrics.tests.RecordingMetricFactory;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.Test;
+
+import com.google.common.collect.ImmutableList;
+
+class SelectProcessorTest {
+ private static final Username BOB = Username.of("bob");
+
+ private SelectProcessor testee;
+ private InMemoryMailboxManager mailboxManager;
+ private MailboxSession mailboxSession;
+ private UidValidity uidValidity;
+
+ @BeforeEach
+ void setUp() throws Exception {
+ InMemoryIntegrationResources integrationResources = InMemoryIntegrationResources.defaultResources();
+
+ mailboxManager = integrationResources.getMailboxManager();
+ testee = new SelectProcessor(new ImapProcessor() {
+ @Override
+ public void process(ImapMessage message, Responder responder, ImapSession session) {
+
+ }
+
+ @Override
+ public void configure(ImapConfiguration imapConfiguration) {
+
+ }
+ }, mailboxManager,
+ integrationResources.getEventBus(),
+ new UnpooledStatusResponseFactory(),
+ new RecordingMetricFactory());
+
+ mailboxSession = mailboxManager.createSystemSession(Username.of("bob"));
+ mailboxManager.createMailbox(MailboxPath.inbox(BOB), mailboxSession);
+ uidValidity = mailboxManager.getMailbox(MailboxPath.inbox(BOB), mailboxSession).getMailboxEntity().getUidValidity();
+ }
+
+ @Test
+ void vanishedResponsesShouldNotBeSentWhenNoDeletes() throws Exception {
+ FakeImapSession session = new FakeImapSession();
+ session.authenticated();
+ session.setMailboxSession(mailboxSession);
+ EnableProcessor.getEnabledCapabilities(session)
+ .add(ImapConstants.SUPPORTS_QRESYNC);
+
+ MessageManager mailbox = mailboxManager.getMailbox(MailboxPath.inbox(BOB), mailboxSession);
+ MessageManager.AppendCommand appendCommand = MessageManager.AppendCommand
+ .builder()
+ .withFlags(new Flags(Flags.Flag.SEEN))
+ .notRecent()
+ .build(new SharedByteArrayInputStream("header: value\r\n\r\nbody".getBytes()));
+ mailbox.appendMessage(appendCommand, mailboxSession);
+ mailbox.appendMessage(appendCommand, mailboxSession);
+ mailbox.appendMessage(appendCommand, mailboxSession);
+ mailbox.appendMessage(appendCommand, mailboxSession);
+ mailbox.appendMessage(appendCommand, mailboxSession);
+
+ UidRange[] uidRanges = null;
+ IdRange[] sequences = null;
+ SelectRequest message = new SelectRequest("INBOX", false,
+ AbstractMailboxSelectionRequest.ClientSpecifiedUidValidity.valid(uidValidity),
+ 4L, uidRanges, uidRanges, sequences, new Tag("AA"));
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ testee.process(message,
+ new ResponseEncoder(
+ new DefaultImapEncoderFactory(new DefaultLocalizer(), true).buildImapEncoder(),
+ new ImapResponseComposerImpl(new OutputStreamImapResponseWriter(outputStream))),
+ session);
+
+ assertThat(new String(outputStream.toByteArray()))
+ .doesNotContain("* VANISHED (EARLIER) 1:4");
+ }
+
+ @Test
+ void vanishedResponsesShouldBeSentWhenDeletes() throws Exception {
+ FakeImapSession session = new FakeImapSession();
+ session.authenticated();
+ session.setMailboxSession(mailboxSession);
+ EnableProcessor.getEnabledCapabilities(session)
+ .add(ImapConstants.SUPPORTS_QRESYNC);
+
+ MessageManager mailbox = mailboxManager.getMailbox(MailboxPath.inbox(BOB), mailboxSession);
+ MessageManager.AppendCommand appendCommand = MessageManager.AppendCommand
+ .builder()
+ .withFlags(new Flags(Flags.Flag.SEEN))
+ .notRecent()
+ .build(new SharedByteArrayInputStream("header: value\r\n\r\nbody".getBytes()));
+ mailbox.appendMessage(appendCommand, mailboxSession);
+
+ MessageManager.AppendResult msg2 = mailbox.appendMessage(appendCommand, mailboxSession);
+
+ mailbox.appendMessage(appendCommand, mailboxSession);
+
+ MessageManager.AppendResult msg4 = mailbox.appendMessage(appendCommand, mailboxSession);
+
+ mailbox.appendMessage(appendCommand, mailboxSession);
+
+ mailbox.delete(ImmutableList.of(msg2.getId().getUid(), msg4.getId().getUid()), mailboxSession);
+
+ UidRange[] uidRanges = null;
+ IdRange[] sequences = null;
+ SelectRequest message = new SelectRequest("INBOX", false,
+ AbstractMailboxSelectionRequest.ClientSpecifiedUidValidity.valid(uidValidity),
+ 4L, uidRanges, uidRanges, sequences, new Tag("AA"));
+
+ ByteArrayOutputStream outputStream = new ByteArrayOutputStream();
+
+ testee.process(message,
+ new ResponseEncoder(
+ new DefaultImapEncoderFactory(new DefaultLocalizer(), true).buildImapEncoder(),
+ new ImapResponseComposerImpl(new OutputStreamImapResponseWriter(outputStream))),
+ session);
+
+ assertThat(new String(outputStream.toByteArray()))
+ .contains("* VANISHED (EARLIER) 2,4");
+ }
+}
\ No newline at end of file
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org