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 2022/11/22 07:11:48 UTC
[james-project] 03/12: JAMES-3858 Add FETCH item for EMAILID and THREADID
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
commit 6a4fa30410c5fcb1a45711e6aed70eb3b0a706be
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Thu Nov 17 11:02:14 2022 +0700
JAMES-3858 Add FETCH item for EMAILID and THREADID
---
.../org/apache/james/imap/api/ImapConstants.java | 2 ++
.../apache/james/imap/api/message/FetchData.java | 3 ++
.../imap/decode/parser/FetchCommandParser.java | 6 ++++
.../james/imap/encode/FetchResponseEncoder.java | 25 +++++++++++++++-
.../james/imap/message/response/FetchResponse.java | 16 ++++++++++-
.../imap/processor/AbstractMailboxProcessor.java | 4 +--
.../james/imap/processor/StoreProcessor.java | 6 ++--
.../imap/processor/fetch/FetchResponseBuilder.java | 33 +++++++++++++++++++++-
.../encode/FetchResponseEncoderEnvelopeTest.java | 2 +-
.../FetchResponseEncoderNoExtensionsTest.java | 8 +++---
.../imap/encode/FetchResponseEncoderTest.java | 6 ++--
11 files changed, 95 insertions(+), 16 deletions(-)
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConstants.java b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConstants.java
index fb90dc3359..211c4c9d1d 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConstants.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/ImapConstants.java
@@ -253,4 +253,6 @@ public interface ImapConstants {
String STORAGE_QUOTA_RESOURCE = "STORAGE";
String MESSAGE_QUOTA_RESOURCE = "MESSAGE";
+ String EMAILID = "EMAILID";
+ String THREADID = "THREADID";
}
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/api/message/FetchData.java b/protocols/imap/src/main/java/org/apache/james/imap/api/message/FetchData.java
index 45c93bc920..50cf6159b2 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/api/message/FetchData.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/api/message/FetchData.java
@@ -102,6 +102,9 @@ public class FetchData {
BODY,
BODY_STRUCTURE,
MODSEQ,
+ // https://www.rfc-editor.org/rfc/rfc8474.html#section-5.3
+ EMAILID,
+ THREADID
}
public static Builder builder() {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
index 84eed8c212..3f11db1465 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/decode/parser/FetchCommandParser.java
@@ -20,11 +20,13 @@ package org.apache.james.imap.decode.parser;
import static org.apache.james.imap.api.message.FetchData.Item.BODY;
import static org.apache.james.imap.api.message.FetchData.Item.BODY_STRUCTURE;
+import static org.apache.james.imap.api.message.FetchData.Item.EMAILID;
import static org.apache.james.imap.api.message.FetchData.Item.ENVELOPE;
import static org.apache.james.imap.api.message.FetchData.Item.FLAGS;
import static org.apache.james.imap.api.message.FetchData.Item.INTERNAL_DATE;
import static org.apache.james.imap.api.message.FetchData.Item.MODSEQ;
import static org.apache.james.imap.api.message.FetchData.Item.SIZE;
+import static org.apache.james.imap.api.message.FetchData.Item.THREADID;
import static org.apache.james.imap.api.message.FetchData.Item.UID;
import java.util.List;
@@ -185,6 +187,10 @@ public class FetchCommandParser extends AbstractUidCommandParser {
return fetch.add(BodyFetchElement.createRFC822Text(), false);
case "MODSEQ":
return fetch.fetch(MODSEQ);
+ case "EMAILID":
+ return fetch.fetch(EMAILID);
+ case "THREADID":
+ return fetch.fetch(THREADID);
default:
throw new DecodingException(HumanReadableText.ILLEGAL_ARGUMENTS, "Invalid fetch attribute: " + name);
}
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
index 80ce91485e..c67980610c 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/encode/FetchResponseEncoder.java
@@ -37,6 +37,8 @@ import org.apache.james.imap.message.response.FetchResponse.Structure;
import org.apache.james.mailbox.MessageSequenceNumber;
import org.apache.james.mailbox.MessageUid;
import org.apache.james.mailbox.ModSeq;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.ThreadId;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -81,7 +83,8 @@ public class FetchResponseEncoder implements ImapResponseEncoder<FetchResponse>
encodeBodyStructure(composer, fetchResponse.getBodyStructure());
encodeUid(composer, fetchResponse);
encodeBodyElements(composer, fetchResponse.getElements());
-
+ encodeEmailId(composer, fetchResponse);
+ encodeThreadId(composer, fetchResponse);
composer.closeParen().end();
}
@@ -295,6 +298,26 @@ public class FetchResponseEncoder implements ImapResponseEncoder<FetchResponse>
}
}
+ private void encodeEmailId(ImapResponseComposer composer, FetchResponse fetchResponse) throws IOException {
+ final MessageId emailId = fetchResponse.getEmailId();
+ if (emailId != null) {
+ composer.message(ImapConstants.EMAILID);
+ composer.openParen();
+ composer.message(emailId.serialize());
+ composer.closeParen();
+ }
+ }
+ private void encodeThreadId(ImapResponseComposer composer, FetchResponse fetchResponse) throws IOException {
+ final ThreadId threadId = fetchResponse.getThreadId();
+ if (threadId != null) {
+ composer.message(ImapConstants.THREADID);
+ composer.openParen();
+ composer.message(threadId.serialize());
+ composer.closeParen();
+ }
+ }
+
+
private void encodeFlags(ImapResponseComposer composer, FetchResponse fetchResponse) throws IOException {
final Flags flags = fetchResponse.getFlags();
if (flags != null) {
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java b/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java
index b909af977a..3a66268fde 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/message/response/FetchResponse.java
@@ -30,6 +30,8 @@ import org.apache.james.imap.message.Literal;
import org.apache.james.mailbox.MessageSequenceNumber;
import org.apache.james.mailbox.MessageUid;
import org.apache.james.mailbox.ModSeq;
+import org.apache.james.mailbox.model.MessageId;
+import org.apache.james.mailbox.model.ThreadId;
public final class FetchResponse implements ImapResponseMessage {
private final MessageSequenceNumber messageNumber;
@@ -42,8 +44,10 @@ public final class FetchResponse implements ImapResponseMessage {
private final Structure body;
private final Structure bodystructure;
private final ModSeq modSeq;
+ private final MessageId emailId;
+ private final ThreadId threadId;
- public FetchResponse(MessageSequenceNumber messageNumber, Flags flags, MessageUid uid, ModSeq modSeq, Date internalDate, Long size, Envelope envelope, Structure body, Structure bodystructure, List<BodyElement> elements) {
+ public FetchResponse(MessageSequenceNumber messageNumber, Flags flags, MessageUid uid, ModSeq modSeq, Date internalDate, Long size, Envelope envelope, Structure body, Structure bodystructure, List<BodyElement> elements, MessageId emailId, ThreadId threadId) {
this.messageNumber = messageNumber;
this.flags = flags;
this.uid = uid;
@@ -54,6 +58,8 @@ public final class FetchResponse implements ImapResponseMessage {
this.body = body;
this.bodystructure = bodystructure;
this.modSeq = modSeq;
+ this.emailId = emailId;
+ this.threadId = threadId;
}
/**
@@ -155,6 +161,14 @@ public final class FetchResponse implements ImapResponseMessage {
return modSeq;
}
+ public MessageId getEmailId() {
+ return emailId;
+ }
+
+ public ThreadId getThreadId() {
+ return threadId;
+ }
+
/**
* Describes the message structure.
*/
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 811383a093..5c4be73ce8 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
@@ -265,9 +265,9 @@ public abstract class AbstractMailboxProcessor<R extends ImapRequest> extends Ab
// Check if we also need to return the MODSEQ in the response. This is true if CONDSTORE or
// if QRESYNC was enabled, and the mailbox supports the permant storage of mod-sequences
if (condstoreEnabled || qresyncEnabled) {
- response = new FetchResponse(msn, flags, uidOut, mr.getModSeq(), null, null, null, null, null, null);
+ response = new FetchResponse(msn, flags, uidOut, mr.getModSeq(), null, null, null, null, null, null, null, null);
} else {
- response = new FetchResponse(msn, flags, uidOut, null, null, null, null, null, null, null);
+ response = new FetchResponse(msn, flags, uidOut, null, null, null, null, null, null, null, null, null);
}
responder.respond(response);
return null;
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
index 0c97d83816..00cb177af5 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/StoreProcessor.java
@@ -312,14 +312,14 @@ public class StoreProcessor extends AbstractMailboxProcessor<StoreRequest> {
if (unchangedSince != -1 || qresyncEnabled || condstoreEnabled) {
if (silent) {
// We need to return an FETCH response which contains the mod-sequence of the message even if FLAGS.SILENT was used
- return new FetchResponse(msn, null, resultUid, modSeqs.get(uid), null, null, null, null, null, null);
+ return new FetchResponse(msn, null, resultUid, modSeqs.get(uid), null, null, null, null, null, null, null, null);
} else {
// Use a FETCH response which contains the mod-sequence and the flags
- return new FetchResponse(msn, resultFlags, resultUid, modSeqs.get(uid), null, null, null, null, null, null);
+ return new FetchResponse(msn, resultFlags, resultUid, modSeqs.get(uid), null, null, null, null, null, null, null, null);
}
} else {
// Use a FETCH response which only contains the flags as no CONDSTORE was used
- return new FetchResponse(msn, resultFlags, resultUid, null, null, null, null, null, null, null);
+ return new FetchResponse(msn, resultFlags, resultUid, null, null, null, null, null, null, null, null, null);
}
}
diff --git a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
index 9b78f318d9..a33c2421bc 100644
--- a/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
+++ b/protocols/imap/src/main/java/org/apache/james/imap/processor/fetch/FetchResponseBuilder.java
@@ -48,9 +48,11 @@ import org.apache.james.mailbox.exception.MessageRangeException;
import org.apache.james.mailbox.model.ComposedMessageIdWithMetaData;
import org.apache.james.mailbox.model.Content;
import org.apache.james.mailbox.model.Header;
+import org.apache.james.mailbox.model.MessageId;
import org.apache.james.mailbox.model.MessageRange;
import org.apache.james.mailbox.model.MessageResult;
import org.apache.james.mailbox.model.MimePath;
+import org.apache.james.mailbox.model.ThreadId;
import reactor.core.publisher.Mono;
@@ -58,6 +60,8 @@ public final class FetchResponseBuilder {
private final EnvelopeBuilder envelopeBuilder;
private MessageSequenceNumber msn;
+ private MessageId messageId;
+ private ThreadId threadId;
private MessageUid uid;
private Flags flags;
private Date internalDate;
@@ -74,6 +78,8 @@ public final class FetchResponseBuilder {
public void reset(MessageSequenceNumber msn) {
this.msn = msn;
+ messageId = null;
+ threadId = null;
uid = null;
flags = null;
internalDate = null;
@@ -84,6 +90,14 @@ public final class FetchResponseBuilder {
modSeq = null;
}
+ public void setMessageId(MessageId messageId) {
+ this.messageId = messageId;
+ }
+
+ public void setThreadId(ThreadId threadId) {
+ this.threadId = threadId;
+ }
+
public void setUid(MessageUid resultUid) {
this.uid = resultUid;
}
@@ -98,7 +112,7 @@ public final class FetchResponseBuilder {
}
public FetchResponse build() {
- return new FetchResponse(msn, flags, uid, modSeq, internalDate, size, envelope, body, bodystructure, elements);
+ return new FetchResponse(msn, flags, uid, modSeq, internalDate, size, envelope, body, bodystructure, elements, messageId, threadId);
}
public Mono<FetchResponse> build(FetchData fetch, MessageResult result, MessageManager mailbox, SelectedMailbox selectedMailbox, MailboxSession mailboxSession) throws MessageRangeException, MailboxException {
@@ -152,6 +166,9 @@ public final class FetchResponseBuilder {
addUid(fetch, resultUid);
+ addThreadId(fetch, result.getThreadId());
+ addMessageId(fetch, result.getMessageId());
+
addModSeq(fetch, result.getModSeq());
// FLAGS response
@@ -170,6 +187,20 @@ public final class FetchResponseBuilder {
}
}
+ private void addMessageId(FetchData fetch, MessageId messageId) {
+ // EMAILID response
+ if (fetch.contains(Item.EMAILID)) {
+ setMessageId(messageId);
+ }
+ }
+
+ private void addThreadId(FetchData fetch, ThreadId threadId) {
+ // THREADID response
+ if (fetch.contains(Item.THREADID)) {
+ setThreadId(threadId);
+ }
+ }
+
private void addModSeq(FetchData fetch, ModSeq modSeq) {
if (fetch.contains(Item.MODSEQ)) {
long changedSince = fetch.getChangedSince();
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
index 9244671d74..e42dadd105 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderEnvelopeTest.java
@@ -97,7 +97,7 @@ public class FetchResponseEncoderEnvelopeTest {
subject = null;
to = null;
- message = new FetchResponse(MSN, null, null, null, null, null, envelope, null, null, null);
+ message = new FetchResponse(MSN, null, null, null, null, null, envelope, null, null, null, null, null);
encoder = new FetchResponseEncoder(false);
}
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
index 4e0a4fc752..0bd013a916 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderNoExtensionsTest.java
@@ -58,7 +58,7 @@ class FetchResponseEncoderNoExtensionsTest {
@Test
void testShouldEncodeFlagsResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, flags, null, null, null, null,
- null, null, null, null);
+ null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (FLAGS (\\Deleted))\r\n");
}
@@ -66,7 +66,7 @@ class FetchResponseEncoderNoExtensionsTest {
@Test
void testShouldEncodeUidResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, null, MessageUid.of(72), null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (UID 72)\r\n");
@@ -75,7 +75,7 @@ class FetchResponseEncoderNoExtensionsTest {
@Test
void testShouldEncodeAllResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, flags, MessageUid.of(72), null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (FLAGS (\\Deleted) UID 72)\r\n");
@@ -84,7 +84,7 @@ class FetchResponseEncoderNoExtensionsTest {
@Test
void testShouldNotAddExtensionsWithEncodingBodyStructure() throws Exception {
FetchResponse message = new FetchResponse(MSN, flags, MessageUid.of(72), null,
- null, null, null, null, stubStructure, null);
+ null, null, null, null, stubStructure, null, null, null);
final Map<String, String> parameters = new HashMap<>();
parameters.put("CHARSET", "US-ASCII");
final List<String> parameterList = new ArrayList<>();
diff --git a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
index 7c803cb274..395ebb44ad 100644
--- a/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
+++ b/protocols/imap/src/test/java/org/apache/james/imap/encode/FetchResponseEncoderTest.java
@@ -52,7 +52,7 @@ class FetchResponseEncoderTest {
@Test
void testShouldEncodeFlagsResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, flags, null, null, null, null,
- null, null, null, null);
+ null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (FLAGS (\\Deleted))\r\n");
@@ -62,7 +62,7 @@ class FetchResponseEncoderTest {
@Test
void testShouldEncodeUidResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, null, MessageUid.of(72), null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (UID 72)\r\n");
@@ -72,7 +72,7 @@ class FetchResponseEncoderTest {
@Test
void testShouldEncodeAllResponse() throws Exception {
FetchResponse message = new FetchResponse(MSN, flags, MessageUid.of(72), null,
- null, null, null, null, null, null);
+ null, null, null, null, null, null, null, null);
encoder.encode(message, composer);
assertThat(writer.getString()).isEqualTo("* 100 FETCH (FLAGS (\\Deleted) UID 72)\r\n");
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org