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 2020/11/23 08:20:13 UTC
[james-project] 14/19: JAMES-3434 Advertise
urn:ietf:params:jmap:submission capability
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 30e3ed5cb86e4788ebd0da22c462c337e4136982
Author: Benoit Tellier <bt...@linagora.com>
AuthorDate: Sun Nov 22 14:16:50 2020 +0700
JAMES-3434 Advertise urn:ietf:params:jmap:submission capability
---
.../rfc8621/contract/SessionRoutesContract.scala | 9 ++++++
.../org/apache/james/jmap/core/Capabilities.scala | 35 ++++++++++++----------
.../org/apache/james/jmap/core/Capability.scala | 16 ++++++++--
.../james/jmap/json/ResponseSerializer.scala | 7 +++++
.../james/jmap/routes/SessionRoutesTest.scala | 9 ++++++
5 files changed, 57 insertions(+), 19 deletions(-)
diff --git a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
index 7fc769e..b33c01e 100644
--- a/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
+++ b/server/protocols/jmap-rfc-8621-integration-tests/jmap-rfc-8621-integration-tests-common/src/main/scala/org/apache/james/jmap/rfc8621/contract/SessionRoutesContract.scala
@@ -41,6 +41,10 @@ import org.junit.jupiter.api.{BeforeEach, Tag, Test}
object SessionRoutesContract {
private val expected_session_object: String = """{
| "capabilities" : {
+ | "urn:ietf:params:jmap:submission": {
+ | "maxDelayedSend": 0,
+ | "submissionExtensions": []
+ | },
| "urn:ietf:params:jmap:core" : {
| "maxSizeUpload" : 31457280,
| "maxConcurrentUpload" : 4,
@@ -69,6 +73,10 @@ object SessionRoutesContract {
| "isPersonal" : true,
| "isReadOnly" : false,
| "accountCapabilities" : {
+ | "urn:ietf:params:jmap:submission": {
+ | "maxDelayedSend": 0,
+ | "submissionExtensions": []
+ | },
| "urn:ietf:params:jmap:core" : {
| "maxSizeUpload" : 31457280,
| "maxConcurrentUpload" : 4,
@@ -94,6 +102,7 @@ object SessionRoutesContract {
| }
| },
| "primaryAccounts" : {
+ | "urn:ietf:params:jmap:submission": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "urn:ietf:params:jmap:core" : "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "urn:ietf:params:jmap:mail" : "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
| "urn:apache:james:params:jmap:mail:quota": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6",
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capabilities.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capabilities.scala
index 8b74337..40fd95d 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capabilities.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capabilities.scala
@@ -19,10 +19,10 @@
package org.apache.james.jmap.core
import eu.timepit.refined.auto._
-import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_QUOTA, JAMES_SHARES, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION, JAMES_QUOTA, JAMES_SHARES, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
object DefaultCapabilities {
- def coreCapability(maxUploadSize: MaxSizeUpload) = CoreCapability(
+ private def coreCapability(maxUploadSize: MaxSizeUpload) = CoreCapability(
properties = CoreCapabilityProperties(
maxUploadSize,
MaxConcurrentUpload(4L),
@@ -32,8 +32,7 @@ object DefaultCapabilities {
MaxObjectsInGet(500L),
MaxObjectsInSet(500L),
collationAlgorithms = List("i;unicode-casemap")))
-
- val MAIL_CAPABILITY = MailCapability(
+ private val MAIL_CAPABILITY = MailCapability(
properties = MailCapabilityProperties(
MaxMailboxesPerEmail(Some(10_000_000L)),
MaxMailboxDepth(None),
@@ -41,20 +40,24 @@ object DefaultCapabilities {
MaxSizeAttachmentsPerEmail(20_000_000L),
emailQuerySortOptions = List("receivedAt", "sentAt"),
MayCreateTopLevelMailbox(true)))
-
- val QUOTA_CAPABILITY = QuotaCapability()
-
- val SHARES_CAPABILITY = SharesCapability()
-
- val VACATION_RESPONSE_CAPABILITY = VacationResponseCapability()
-
- val SUPPORTED_CAPABILITY_IDENTIFIERS = Set(JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE, JAMES_SHARES, JAMES_QUOTA)
-
- def supported(maxUploadSize: MaxSizeUpload) = Capabilities(coreCapability(maxUploadSize), MAIL_CAPABILITY, QUOTA_CAPABILITY, SHARES_CAPABILITY, VACATION_RESPONSE_CAPABILITY)
+ private val QUOTA_CAPABILITY = QuotaCapability()
+ private val SHARES_CAPABILITY = SharesCapability()
+ private val VACATION_RESPONSE_CAPABILITY = VacationResponseCapability()
+ private val SUBMISSION_CAPABILITY = SubmissionCapability()
+
+ val SUPPORTED_CAPABILITY_IDENTIFIERS: Set[CapabilityIdentifier] =
+ Set(JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE, JAMES_SHARES, JAMES_QUOTA, EMAIL_SUBMISSION)
+
+ def supported(maxUploadSize: MaxSizeUpload): Capabilities = Capabilities(coreCapability(maxUploadSize),
+ MAIL_CAPABILITY,
+ QUOTA_CAPABILITY,
+ SHARES_CAPABILITY,
+ VACATION_RESPONSE_CAPABILITY,
+ SUBMISSION_CAPABILITY)
}
case class Capabilities(capabilities: Capability*) {
- def toSet : Set[Capability] = capabilities.toSet
+ def toSet: Set[Capability] = capabilities.toSet
- def ids : Set[CapabilityIdentifier] = toSet.map(_.identifier())
+ def ids: Set[CapabilityIdentifier] = toSet.map(_.identifier())
}
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capability.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capability.scala
index 8ec9dfd..072dc24 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capability.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/Capability.scala
@@ -24,7 +24,7 @@ import eu.timepit.refined.api.Refined
import eu.timepit.refined.auto._
import eu.timepit.refined.collection.NonEmpty
import eu.timepit.refined.string.Uri
-import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, JAMES_QUOTA, JAMES_SHARES, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
+import org.apache.james.jmap.core.CapabilityIdentifier.{CapabilityIdentifier, EMAIL_SUBMISSION, JAMES_QUOTA, JAMES_SHARES, JMAP_CORE, JMAP_MAIL, JMAP_VACATION_RESPONSE}
import org.apache.james.jmap.core.CoreCapabilityProperties.CollationAlgorithm
import org.apache.james.jmap.core.MailCapability.EmailQuerySortOption
import org.apache.james.jmap.core.UnsignedInt.{UnsignedInt, UnsignedIntConstraint}
@@ -40,6 +40,7 @@ object CapabilityIdentifier {
val JMAP_CORE: CapabilityIdentifier = "urn:ietf:params:jmap:core"
val JMAP_MAIL: CapabilityIdentifier = "urn:ietf:params:jmap:mail"
val JMAP_VACATION_RESPONSE: CapabilityIdentifier = "urn:ietf:params:jmap:vacationresponse"
+ val EMAIL_SUBMISSION: CapabilityIdentifier = "urn:ietf:params:jmap:submission"
val JAMES_QUOTA: CapabilityIdentifier = "urn:apache:james:params:jmap:mail:quota"
val JAMES_SHARES: CapabilityIdentifier = "urn:apache:james:params:jmap:mail:shares"
}
@@ -80,8 +81,17 @@ final case class CoreCapabilityProperties(maxSizeUpload: MaxSizeUpload,
maxCallsInRequest: MaxCallsInRequest,
maxObjectsInGet: MaxObjectsInGet,
maxObjectsInSet: MaxObjectsInSet,
- collationAlgorithms: List[CollationAlgorithm]) extends CapabilityProperties {
-}
+ collationAlgorithms: List[CollationAlgorithm]) extends CapabilityProperties
+
+final case class MaxDelayedSend(value: Int) extends AnyVal
+final case class EhloName(value: String) extends AnyVal
+final case class EhloArgs(value: String) extends AnyVal
+
+final case class SubmissionCapability(identifier: CapabilityIdentifier = EMAIL_SUBMISSION,
+ properties: SubmissionProperties = SubmissionProperties()) extends Capability
+
+final case class SubmissionProperties(maxDelayedSend: MaxDelayedSend = MaxDelayedSend(0),
+ submissionExtensions: Map[EhloName, List[EhloArgs]] = Map()) extends CapabilityProperties
object MailCapability {
type EmailQuerySortOption = String Refined NonEmpty
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
index 2afc1bb..24eefc8 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/json/ResponseSerializer.scala
@@ -87,9 +87,14 @@ object ResponseSerializer {
private implicit val urlWrites: Writes[URL] = url => JsString(url.toString)
private implicit val coreCapabilityWrites: Writes[CoreCapabilityProperties] = Json.writes[CoreCapabilityProperties]
private implicit val mailCapabilityWrites: Writes[MailCapabilityProperties] = Json.writes[MailCapabilityProperties]
+ private implicit val maxDelayedSendWrites: Writes[MaxDelayedSend] = Json.valueWrites[MaxDelayedSend]
+ private implicit val ehloNameWrites: Writes[EhloName] = Json.valueWrites[EhloName]
+ private implicit val ehloArgsWrites: Writes[EhloArgs] = Json.valueWrites[EhloArgs]
+ private implicit val submissionPropertiesWrites: Writes[SubmissionProperties] = Json.writes[SubmissionProperties]
private implicit val quotaCapabilityWrites: Writes[QuotaCapabilityProperties] = OWrites[QuotaCapabilityProperties](_ => Json.obj())
private implicit val sharesCapabilityWrites: Writes[SharesCapabilityProperties] = OWrites[SharesCapabilityProperties](_ => Json.obj())
private implicit val vacationResponseCapabilityWrites: Writes[VacationResponseCapabilityProperties] = OWrites[VacationResponseCapabilityProperties](_ => Json.obj())
+ private implicit val submissionCapabilityWrites: Writes[SubmissionCapability] = OWrites[SubmissionCapability](_ => Json.obj())
private implicit val setCapabilityWrites: Writes[Set[_ <: Capability]] =
(set: Set[_ <: Capability]) => {
@@ -105,6 +110,8 @@ object ResponseSerializer {
jsObject.+(capability.identifier.value, sharesCapabilityWrites.writes(capability.properties))
case capability: VacationResponseCapability =>
jsObject.+(capability.identifier.value, vacationResponseCapabilityWrites.writes(capability.properties))
+ case capability: SubmissionCapability =>
+ jsObject.+(capability.identifier.value, submissionPropertiesWrites.writes(capability.properties))
case _ => jsObject
}
})
diff --git a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
index 7a27623..8a3bb45 100644
--- a/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
+++ b/server/protocols/jmap-rfc-8621/src/test/scala/org/apache/james/jmap/routes/SessionRoutesTest.scala
@@ -119,6 +119,10 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
val downloadPath: String = "download/{accountId}/{blobId}/?type={type}&name={name}"
val expectedJson = s"""{
| "capabilities" : {
+ | "urn:ietf:params:jmap:submission": {
+ | "maxDelayedSend": 0,
+ | "submissionExtensions": []
+ | },
| "urn:ietf:params:jmap:core" : {
| "maxSizeUpload" : 31457280,
| "maxConcurrentUpload" : 4,
@@ -147,6 +151,10 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
| "isPersonal" : true,
| "isReadOnly" : false,
| "accountCapabilities" : {
+ | "urn:ietf:params:jmap:submission": {
+ | "maxDelayedSend": 0,
+ | "submissionExtensions": []
+ | },
| "urn:ietf:params:jmap:core" : {
| "maxSizeUpload" : 31457280,
| "maxConcurrentUpload" : 4,
@@ -172,6 +180,7 @@ class SessionRoutesTest extends AnyFlatSpec with BeforeAndAfter with Matchers {
| }
| },
| "primaryAccounts" : {
+ | "urn:ietf:params:jmap:submission": "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401",
| "urn:ietf:params:jmap:core" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401",
| "urn:ietf:params:jmap:mail" : "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401",
| "urn:apache:james:params:jmap:mail:quota": "0fe275bf13ff761407c17f64b1dfae2f4b3186feea223d7267b79f873a105401",
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org