Distributed James Server — jmap.properties
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.
Consult this example to get some examples and hints.
Property name | explanation |
---|---|
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 |
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 |
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). |
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 |
Optional List[String] with delimiter |
authentication.strategy.rfc8621 |
Optional List[String] with delimiter |
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 |
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. |
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.
Generating a JWT key pair
Apache James can alternatively be configured to check the validity of JWT tokens itself. No revocation mechanism is
supported in such a setup, and the sub
claim is used to identify the user. The key configuration is static.
This requires the JWTAuthenticationStrategy
authentication strategy to be used.
The Distributed server enforces the use of RSA-SHA-256.
One can use OpenSSL to generate a JWT key pair :
# private key openssl genrsa -out rs256-4096-private.rsa 4096 # public key openssl rsa -in rs256-4096-private.rsa -pubout > rs256-4096-public.pem
The private key can be used to generate JWT tokens, for instance using jwtgen:
jwtgen -a RS256 -p rs256-4096-private.rsa 4096 -c "sub=bob@domain.tld" -e 3600 -V
This token can then be passed as Bearer
of the Authorization
header :
curl -H "Authorization: Bearer $token" -XPOST http://127.0.0.1:80/jmap -d '...'
The public key can be referenced as jwt.publickeypem.url
of the jmap.properties
configuration file.
Annotated specification
The [annotated documentation](https://github.com/apache/james-project/tree/master/server/protocols/jmap-rfc-8621/doc/specs/spec) 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](https://tools.ietf.org/html/rfc8887).
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](https://open-paas.org/) 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](https://github.com/iNPUTmice/lttrs-android). Version in the Accept headers needs to be explicitly set to
rfc-8621
. [Read more](https://github.com/linagora/james-project/pull/4089).
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.
Eg:
_jmap._tcp.domain.tld. 3600 IN SRV 0 1 443 jmap.domain.tld.