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/11 15:57:43 UTC
[james-project] branch master updated: JAMES-3850 [JMAP] Configure `urn:ietf:params:jmap:mail` `maxSizeAttac… (#1303)
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 bbbd3071ed JAMES-3850 [JMAP] Configure `urn:ietf:params:jmap:mail` `maxSizeAttac… (#1303)
bbbd3071ed is described below
commit bbbd3071eda233f980395c1440aa711b0959547a
Author: Benoit TELLIER <bt...@linagora.com>
AuthorDate: Fri Nov 11 22:57:38 2022 +0700
JAMES-3850 [JMAP] Configure `urn:ietf:params:jmap:mail` `maxSizeAttac… (#1303)
---
.../docs/modules/ROOT/pages/configure/jmap.adoc | 7 +++++++
.../main/java/org/apache/james/jmap/draft/JMAPModule.java | 8 ++++++--
.../main/scala/org/apache/james/jmap/core/Capabilities.scala | 2 +-
.../main/scala/org/apache/james/jmap/core/Capability.scala | 12 ++++++++++--
.../apache/james/jmap/core/JmapRfc8621Configuration.scala | 9 ++++++++-
.../apache/james/jmap/method/EmailSetCreatePerformer.scala | 5 +++--
src/site/xdoc/server/config-jmap.xml | 8 ++++++++
7 files changed, 43 insertions(+), 8 deletions(-)
diff --git a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/jmap.adoc b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/jmap.adoc
index 2d0a5531fc..27ce9a0a01 100644
--- a/server/apps/distributed-app/docs/modules/ROOT/pages/configure/jmap.adoc
+++ b/server/apps/distributed-app/docs/modules/ROOT/pages/configure/jmap.adoc
@@ -40,6 +40,13 @@ Defaults to an empty list.
| Optional. Configuration max size for message created in both JMAP Draft amd RFC-8621.
Default value: None. Supported units are B (bytes) K (KB) M (MB) G (GB).
+| max.size.attachments.per.mail
+| Optional. Defaults to 20MB. RFC-8621 `maxSizeAttachmentsPerEmail` advertised to JMAP client as part of the
+`urn:ietf:params:jmap:mail` capability. This needs to be at least 33% lower than `email.send.max.size` property
+(in order to account for text body, headers, base64 encoding and MIME structures).
+JMAP clients would use this property in order not to create too big emails.
+Default value: None. Supported units are B (bytes) K (KB) M (MB) G (GB).
+
| upload.max.size
| Optional. Configuration max size Upload in new JMAP-RFC-8621.
Default value: 30M. Supported units are B (bytes) K (KB) M (MB) G (GB).
diff --git a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
index 784d9f937c..9f6dce1161 100644
--- a/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
+++ b/server/container/guice/protocols/jmap/src/main/java/org/apache/james/jmap/draft/JMAPModule.java
@@ -43,7 +43,7 @@ import org.apache.james.jmap.core.IdentitySortOrderCapabilityFactory$;
import org.apache.james.jmap.core.JmapQuotaCapabilityFactory$;
import org.apache.james.jmap.core.JmapRfc8621Configuration;
import org.apache.james.jmap.core.MDNCapabilityFactory$;
-import org.apache.james.jmap.core.MailCapabilityFactory$;
+import org.apache.james.jmap.core.MailCapabilityFactory;
import org.apache.james.jmap.core.QuotaCapabilityFactory$;
import org.apache.james.jmap.core.SharesCapabilityFactory$;
import org.apache.james.jmap.core.SubmissionCapabilityFactory$;
@@ -144,7 +144,6 @@ public class JMAPModule extends AbstractModule {
supportedVersions.addBinding().toInstance(Version.RFC8621);
Multibinder<CapabilityFactory> supportedCapabilities = Multibinder.newSetBinder(binder(), CapabilityFactory.class);
- supportedCapabilities.addBinding().toInstance(MailCapabilityFactory$.MODULE$);
supportedCapabilities.addBinding().toInstance(QuotaCapabilityFactory$.MODULE$);
supportedCapabilities.addBinding().toInstance(JmapQuotaCapabilityFactory$.MODULE$);
supportedCapabilities.addBinding().toInstance(IdentitySortOrderCapabilityFactory$.MODULE$);
@@ -170,6 +169,11 @@ public class JMAPModule extends AbstractModule {
return ProcessorsCheck.noCheck();
}
+ @ProvidesIntoSet
+ CapabilityFactory vacationMailetCheck(JmapRfc8621Configuration configuration) {
+ return new MailCapabilityFactory(configuration);
+ }
+
@ProvidesIntoSet
CapabilityFactory coreCapability(JmapRfc8621Configuration configuration) {
return new CoreCapabilityFactory(configuration.maxUploadSize());
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 43a43190fb..57f1747aa9 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
@@ -25,7 +25,7 @@ object DefaultCapabilities {
@VisibleForTesting
def supported(configuration: JmapRfc8621Configuration): Set[CapabilityFactory] = Set(
CoreCapabilityFactory(configuration.maxUploadSize),
- MailCapabilityFactory,
+ MailCapabilityFactory(configuration),
QuotaCapabilityFactory,
JmapQuotaCapabilityFactory,
IdentitySortOrderCapabilityFactory,
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 25a715e99e..c3d587d4f4 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
@@ -179,18 +179,26 @@ object MailCapability {
final case class MailCapability(properties: MailCapabilityProperties,
identifier: CapabilityIdentifier = JMAP_MAIL) extends Capability
-case object MailCapabilityFactory extends CapabilityFactory {
+case class MailCapabilityFactory(configuration: JmapRfc8621Configuration) extends CapabilityFactory {
override def id(): CapabilityIdentifier = JMAP_MAIL
override def create(urlPrefixes: UrlPrefixes): Capability = MailCapability(MailCapabilityProperties(
MaxMailboxesPerEmail(Some(10_000_000L)),
MaxMailboxDepth(None),
MaxSizeMailboxName(200L),
- MaxSizeAttachmentsPerEmail(20_000_000L),
+ configuration.maxSizeAttachmentsPerEmail,
emailQuerySortOptions = List("receivedAt", "sentAt", "size", "from", "to", "subject"),
MayCreateTopLevelMailbox(true)))
}
+
+object MaxSizeAttachmentsPerEmail {
+ def of(size: Size): Try[MaxSizeAttachmentsPerEmail] = refined.refineV[UnsignedIntConstraint](size.asBytes()) match {
+ case Right(value) => Success(MaxSizeAttachmentsPerEmail(value))
+ case Left(error) => Failure(new NumberFormatException(error))
+ }
+}
+
case class MaxMailboxesPerEmail(value: Option[UnsignedInt])
case class MaxMailboxDepth(value: Option[UnsignedInt])
case class MaxSizeMailboxName(value: UnsignedInt)
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/JmapRfc8621Configuration.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/JmapRfc8621Configuration.scala
index 2ae82d9c66..0a8597264d 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/JmapRfc8621Configuration.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/core/JmapRfc8621Configuration.scala
@@ -23,7 +23,7 @@ import java.net.URI
import java.util.Optional
import org.apache.commons.configuration2.Configuration
-import org.apache.james.jmap.core.JmapRfc8621Configuration.UPLOAD_LIMIT_DEFAULT
+import org.apache.james.jmap.core.JmapRfc8621Configuration.{MAX_SIZE_ATTACHMENTS_PER_MAIL_DEFAULT, UPLOAD_LIMIT_DEFAULT}
import org.apache.james.jmap.pushsubscription.PushClientConfiguration
import org.apache.james.util.Size
@@ -31,6 +31,7 @@ import scala.jdk.OptionConverters._
object JmapConfigProperties {
val UPLOAD_LIMIT_PROPERTY: String = "upload.max.size"
+ val MAX_SIZE_ATTACHMENTS_PER_MAIL_PROPERTY: String = "max.size.attachments.per.mail"
val URL_PREFIX_PROPERTY: String = "url.prefix"
val WEBSOCKET_URL_PREFIX_PROPERTY: String = "websocket.url.prefix"
val WEB_PUSH_MAX_TIMEOUT_SECONDS_PROPERTY: String = "webpush.maxTimeoutSeconds"
@@ -45,6 +46,7 @@ object JmapRfc8621Configuration {
val URL_PREFIX_DEFAULT: String = "http://localhost"
val WEBSOCKET_URL_PREFIX_DEFAULT: String = "ws://localhost"
val UPLOAD_LIMIT_DEFAULT: MaxSizeUpload = MaxSizeUpload.of(Size.of(30L, Size.Unit.M)).get
+ val MAX_SIZE_ATTACHMENTS_PER_MAIL_DEFAULT: MaxSizeAttachmentsPerEmail = MaxSizeAttachmentsPerEmail.of(Size.of(20_000_000L, Size.Unit.B)).get
val LOCALHOST_CONFIGURATION: JmapRfc8621Configuration = JmapRfc8621Configuration(
urlPrefixString = URL_PREFIX_DEFAULT,
@@ -60,6 +62,10 @@ object JmapRfc8621Configuration {
.map(Size.parse)
.map(MaxSizeUpload.of(_).get)
.getOrElse(UPLOAD_LIMIT_DEFAULT),
+ maxSizeAttachmentsPerEmail = Option(configuration.getString(MAX_SIZE_ATTACHMENTS_PER_MAIL_PROPERTY, null))
+ .map(Size.parse)
+ .map(MaxSizeAttachmentsPerEmail.of(_).get)
+ .getOrElse(MAX_SIZE_ATTACHMENTS_PER_MAIL_DEFAULT),
maxTimeoutSeconds = Optional.ofNullable(configuration.getInteger(WEB_PUSH_MAX_TIMEOUT_SECONDS_PROPERTY, null)).map(Integer2int).toScala,
maxConnections = Optional.ofNullable(configuration.getInteger(WEB_PUSH_MAX_CONNECTIONS_PROPERTY, null)).map(Integer2int).toScala,
preventServerSideRequestForgery = Optional.ofNullable(configuration.getBoolean(WEB_PUSH_PREVENT_SERVER_SIDE_REQUEST_FORGERY, null)).orElse(true),
@@ -70,6 +76,7 @@ case class JmapRfc8621Configuration(urlPrefixString: String,
websocketPrefixString: String,
dynamicJmapPrefixResolutionEnabled: Boolean = false,
maxUploadSize: MaxSizeUpload = UPLOAD_LIMIT_DEFAULT,
+ maxSizeAttachmentsPerEmail: MaxSizeAttachmentsPerEmail = MAX_SIZE_ATTACHMENTS_PER_MAIL_DEFAULT,
maxTimeoutSeconds: Option[Int] = None,
maxConnections: Option[Int] = None,
authenticationStrategies: Option[java.util.List[String]] = None,
diff --git a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetCreatePerformer.scala b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetCreatePerformer.scala
index 35b25b3588..a9f34ada3e 100644
--- a/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetCreatePerformer.scala
+++ b/server/protocols/jmap-rfc-8621/src/main/scala/org/apache/james/jmap/method/EmailSetCreatePerformer.scala
@@ -28,7 +28,7 @@ import javax.mail.Flags
import org.apache.james.jmap.JMAPConfiguration
import org.apache.james.jmap.api.model.Size.sanitizeSize
import org.apache.james.jmap.core.SetError.SetErrorDescription
-import org.apache.james.jmap.core.{Properties, SetError, UTCDate}
+import org.apache.james.jmap.core.{JmapRfc8621Configuration, Properties, SetError, UTCDate}
import org.apache.james.jmap.json.EmailSetSerializer
import org.apache.james.jmap.mail.{BlobId, EmailCreationId, EmailCreationRequest, EmailCreationResponse, EmailSetRequest, ThreadId}
import org.apache.james.jmap.method.EmailSetCreatePerformer.{CreationFailure, CreationResult, CreationResults, CreationSuccess}
@@ -82,7 +82,8 @@ class EmailSetCreatePerformer @Inject()(serializer: EmailSetSerializer,
blobResolvers: BlobResolvers,
htmlTextExtractor: HtmlTextExtractor,
mailboxManager: MailboxManager,
- configuration: JMAPConfiguration) {
+ configuration: JMAPConfiguration,
+ configurationRfc8621: JmapRfc8621Configuration) {
def create(request: EmailSetRequest, mailboxSession: MailboxSession): SMono[CreationResults] =
SFlux.fromIterable(request.create.getOrElse(Map()))
diff --git a/src/site/xdoc/server/config-jmap.xml b/src/site/xdoc/server/config-jmap.xml
index 7dcbda82b9..9cfc5fa1c7 100644
--- a/src/site/xdoc/server/config-jmap.xml
+++ b/src/site/xdoc/server/config-jmap.xml
@@ -74,6 +74,14 @@
<dd>Optional. Configuration max size for message created in both JMAP Draft amd RFC-8621.</dd>
<dd>Default value: None. Supported units are B (bytes) K (KB) M (MB) G (GB).</dd>
+ <dt><strong>max.size.attachments.per.mail</strong></dt>
+ <dd>Optional. Defaults to 20MB. RFC-8621 <code>maxSizeAttachmentsPerEmail</code> advertised to JMAP
+ client as part of the <code>urn:ietf:params:jmap:mail</code> capability. This needs to be at
+ least 33% lower than <code>email.send.max.size</code> property (in order to account for text body,
+ headers, base64 encoding and MIME structures). JMAP clients would use this property in order not
+ to create too big emails.</dd>
+ <dd>Default value: None. Supported units are B (bytes) K (KB) M (MB) G (GB).</dd>
+
<dt><strong>view.email.query.enabled</strong></dt>
<dd>Optional boolean. Defaults to false.</dd>
<dd>Should simple Email/query be resolved against a Cassandra projection, or should we resolve them against OpenSearch?
---------------------------------------------------------------------
To unsubscribe, e-mail: notifications-unsubscribe@james.apache.org
For additional commands, e-mail: notifications-help@james.apache.org