JMAP configuration

JMAP is intended to be a new standard for email clients to connect to mail stores. It therefore intends to primarily replace IMAP + SMTP submission. It is also designed to be more generic. It does not replace MTA-to-MTA SMTP transmission.

Cassandra Guice proposes a JMAP implementation.

jmap.properties

Consult jmap.properties in GIT to get some examples and hints.


enabled
true/false. Governs whether JMAP should be enabled
jmap.port
Optional. Defaults to 80. The port this server will be listening on. This value must be a valid port, ranging between 1 and 65535 (inclusive)
tls.keystoreURL
Keystore to be used for generating authentication tokens for password authentication mechanism. This should not be the same keystore than the ones used by TLS based protocols.
tls.secret
Password used to read the keystore
jwt.publickeypem.url
Optional. Coma separated list of RSA public keys URLs to validate JWT tokens allowing requests to bypass authentication. Defaults to an empty list.
url.prefix
Optional. Configuration urlPrefix for JMAP routes.
Default value: http://localhost.
websocket.url.prefix
Optional. URL for JMAP WebSocket route
Default value: ws://localhost
upload.max.size
Optional. Configuration max size for each upload file in new JMAP-RFC-8621.
Default value: 30M. Supported units are B (bytes) K (KB) M (MB) G (GB).
upload.quota.limit
Optional. Configure JMAP upload quota for total existing uploads' size per user. User exceeding the upload quota would result in old uploads being cleaned up.
Default value: 200M. Supported units are B (bytes) K (KB) M (MB) G (GB).
email.send.max.size
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).
view.email.query.enabled
Optional boolean. Defaults to false.
Should simple Email/query be resolved against a Cassandra projection, or should we resolve them against OpenSearch? This enables a higher resilience, but the projection needs to be correctly populated.
user.provisioning.enabled
Optional boolean. Defaults to true.
Governs whether authenticated users that do not exist locally should be created in the users repository.
authentication.strategy.draft
List[String] with delimiter ",". Defaults to AccessTokenAuthenticationStrategy,JWTAuthenticationStrategy, QueryParameterAccessTokenAuthenticationStrategy.
Specify which authentication strategies system admin want to use for JMAP draft server. The implicit package name is "org.apache.james.jmap.http". If you have a custom authentication strategy outside this package, you have to specify its FQDN. If no authentication strategy is specified, JMAP draft server will fallback to default strategies: AccessTokenAuthenticationStrategy, JWTAuthenticationStrategy, QueryParameterAccessTokenAuthenticationStrategy.
authentication.strategy.rfc8621
List[String] with delimiter ",". Defaults to JWTAuthenticationStrategy,BasicAuthenticationStrategy.
Specify which authentication strategies system admin want to use for JMAP RFC-8621 server. The implicit package name is "org.apache.james.jmap.http". If you have a custom authentication strategy outside this package, you have to specify its FQDN. If no authentication strategy is specified, JMAP RFC-8621 server will fallback to default strategies: JWTAuthenticationStrategy, BasicAuthenticationStrategy.
jmap.version.default
Optional string. Defaults to draft. Allowed values: draft, rfc-8621.
Which version of the JMAP protocol should be served when none supplied in the Accept header. Defaults to draft for legacy reasons (avoid breaking changes) but setting the value to rfc-8621 allow compatibility with other third party apps.
dynamic.jmap.prefix.resolution.enabled
Optional boolean. Defaults to false. Supported Jmap session endpoint returns dynamic prefix in response. When its config is true, and the HTTP request to Jmap session endpoint has a `X-JMAP-PREFIX` header with the value `http://new-domain/prefix`, then `apiUrl, downloadUrl, uploadUrl, eventSourceUrl, webSocketUrl` in response will be changed with a new prefix. Example: The `apiUrl` will be "http://new-domain/prefix/jmap". If the HTTP request to Jmap session endpoint has the `X-JMAP-WEBSOCKET-PREFIX` header with the value `ws://new-domain/prefix`, then `capabilities."urn:ietf:params:jmap:websocket".url` in response will be "ws://new-domain/prefix/jmap/ws".
webpush.prevent.server.side.request.forgery
Optional boolean. Prevent server side request forgery by preventing calls to the private network ranges. Defaults to true, can be disabled for testing.
cassandra.filter.projection.activated
Optional boolean. Defaults to false. Casandra backends only. Whether to use or not the Cassandra projection for JMAP filters. This projection optimizes reads, but needs to be correctly populated. Turning it on on systems with filters already defined would result in those filters to be not read.
delay.sends.enabled
Optional boolean. Defaults to false. Whether to support or not the delay send with JMAP protocol.
disabled.capabilities
Optional, defaults to empty. Coma separated list of JMAP capabilities to reject. This allows to prevent users from using some specific JMAP extensions.
email.get.full.max.size
Optional, default value is 5. The max number of items for EmailGet full reads
get.max.size
Optional, default value is 500. The max number of items for /get methods.
set.max.size
Optional, default value is 500. The max number of items for /set methods.

Wire tapping

Enabling TRACE on org.apache.james.jmap.wire enables reactor-netty wiretap, logging of all incoming and outgoing requests, outgoing requests. This will log also potentially sensible information like authentication credentials.

OIDC set up

The use of XUserAuthenticationStrategy allow delegating the authentication responsibility to a third party system, which could be used to set up authentication against an OIDC provider.

We do supply an example of such a setup. It combines the Keycloack OIDC provider with the Krackend API gateway, but usage of similar technologies is definitely doable.

JMAP-draft vs JMAP-RFC-8621

James had been supporting an implementation based on an early specification of JMAP, what we call here JMAP-draft version. But the protocol went under a lot of changes until its finalization as an official RFC.

The finalized version of JMAP regarding the core specifications [RFC-8620] and the mail specifications [RFC-8621] are being currently implemented in James (JMAP-RFC-8621 version). It's supposed to replace at term the JMAP-draft version.

Meanwhile, both versions will be available. The version by default will be JMAP-draft during the time it takes to implement the new version. If you want to use a specific version for a request, you will need to add an extra jmapVersion field in your Accept header of your JMAP request:

  • JMAP-draft: Accept: application/json; jmapVersion=draft
  • JMAP-RFC-8621: Accept: application/json; jmapVersion=rfc-8621

Annotated specification

The annotated documentation presents the limits of the JMAP RFC-8621 implementation part of the Apache James project. We furthermore implement JSON Meta Application Protocol (JMAP) Subprotocol for WebSocket.

Some methods / types are not yet implemented, some implementations are naive, and the PUSH is not supported yet.

Users are invited to read these limitations before using actively the JMAP RFC-8621 implementation, and should ensure their client applications only uses supported operations.

Contributions enhancing support are furthermore welcomed.

    The list of tested JMAP clients are:
  • OpenPaaS is actively using the draft version of the JMAP implementation. Migration to RFC-8621 is planned.
  • Experiments had been run on top of LTT.RS. Version in the Accept headers needs to be explicitly set to `rfc-8621`. Read more.

JMAP auto-configuration

RFC-8620 defining JMAP core RFC defines precisely service location.

James already redirects `http://jmap.domain.tld/.well-known/jmap` to the JMAP session.

You can further help your clients by publishing extra SRV records.

_jmap._tcp.domain.tld. 3600        IN    SRV    0 1 443 jmap.domain.tld.

Reverse-proxy set up

James implementation adds the value of X-Real-IP header as part of the logging MDC.

This allows for reverse proxies to cary other the IP address of the client down to the JMAP server for diagnostic purpose.