| = Distributed James Server — jmap.properties |
| :navtitle: jmap.properties |
| |
| https://jmap.io/[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 link:https://github.com/apache/james-project/blob/master/server/apps/distributed-app/sample-configuration/jmap.properties[example] |
| to get some examples and hints. |
| |
| .jmap.properties content |
| |=== |
| | 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 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 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). |
| |
| | 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.rfc8621 |
| | Optional List[String] with delimiter `,` . 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 `rfc-8621`. Allowed values: rfc-8621 |
| Which version of the JMAP protocol should be served when none supplied in the Accept header. |
| |
| | 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 link:https://github.com[example] of such a setup. It combines the link:https://www.keycloak.org/[Keycloack] |
| OIDC provider with the link:https://www.krakend.io/[Krackend] API gateway, but usage of similar technologies is definitely doable. |
| |
| == 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 link:https://github.com/vandium-io/jwtgen[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: |
| |
| - 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 |
| |
| link:https://datatracker.ietf.org/doc/html/rfc8620[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. |
| ---- |
| |
| == JMAP 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. |