| /**************************************************************** |
| * Licensed to the Apache Software Foundation (ASF) under one * |
| * or more contributor license agreements. See the NOTICE file * |
| * distributed with this work for additional information * |
| * regarding copyright ownership. The ASF licenses this file * |
| * to you under the Apache License, Version 2.0 (the * |
| * "License"); you may not use this file except in compliance * |
| * with the License. You may obtain a copy of the License at * |
| * * |
| * http://www.apache.org/licenses/LICENSE-2.0 * |
| * * |
| * Unless required by applicable law or agreed to in writing, * |
| * software distributed under the License is distributed on an * |
| * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * |
| * KIND, either express or implied. See the License for the * |
| * specific language governing permissions and limitations * |
| * under the License. * |
| ****************************************************************/ |
| |
| package org.apache.james.jmap.rfc8621.contract |
| |
| import java.io.ByteArrayInputStream |
| import java.nio.charset.StandardCharsets |
| import java.time.{Duration, ZonedDateTime} |
| import java.util.Date |
| import java.util.concurrent.TimeUnit |
| |
| import io.netty.handler.codec.http.HttpHeaderNames.ACCEPT |
| import io.restassured.RestAssured.{`given`, requestSpecification} |
| import io.restassured.http.ContentType.JSON |
| import jakarta.mail.Flags |
| import net.javacrumbs.jsonunit.assertj.JsonAssertions.assertThatJson |
| import net.javacrumbs.jsonunit.core.Option |
| import net.javacrumbs.jsonunit.core.Option.IGNORING_ARRAY_ORDER |
| import net.javacrumbs.jsonunit.core.internal.Options |
| import org.apache.http.HttpStatus.SC_OK |
| import org.apache.james.GuiceJamesServer |
| import org.apache.james.jmap.api.change.State |
| import org.apache.james.jmap.api.model.AccountId |
| import org.apache.james.jmap.core.ResponseObject.SESSION_STATE |
| import org.apache.james.jmap.core.UuidState.INSTANCE |
| import org.apache.james.jmap.draft.{JmapGuiceProbe} |
| import org.apache.james.jmap.http.UserCredential |
| import org.apache.james.jmap.rfc8621.contract.EmailGetMethodContract.createTestMessage |
| import org.apache.james.jmap.rfc8621.contract.Fixture.{ACCEPT_RFC8621_VERSION_HEADER, ALICE, ANDRE, ANDRE_ACCOUNT_ID, ANDRE_PASSWORD, BOB, BOB_PASSWORD, DOMAIN, authScheme, baseRequestSpecBuilder} |
| import org.apache.james.jmap.rfc8621.contract.probe.DelegationProbe |
| import org.apache.james.mailbox.MessageManager.AppendCommand |
| import org.apache.james.mailbox.model.MailboxACL.Right |
| import org.apache.james.mailbox.model.{ComposedMessageId, MailboxACL, MailboxId, MailboxPath, MessageId} |
| import org.apache.james.mime4j.dom.Message |
| import org.apache.james.mime4j.message.MultipartBuilder |
| import org.apache.james.mime4j.stream.RawField |
| import org.apache.james.modules.{ACLProbeImpl, MailboxProbeImpl} |
| import org.apache.james.util.ClassLoaderUtils |
| import org.apache.james.utils.DataProbeImpl |
| import org.assertj.core.api.Assertions.assertThat |
| import org.awaitility.Awaitility |
| import org.junit.jupiter.api.{BeforeEach, Test} |
| import play.api.libs.json.Json |
| |
| object EmailGetMethodContract { |
| private def createTestMessage: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| } |
| |
| trait EmailGetMethodContract { |
| private lazy val slowPacedPollInterval = Duration.ofMillis(100) |
| private lazy val calmlyAwait = Awaitility.`with` |
| .pollInterval(slowPacedPollInterval) |
| .and.`with`.pollDelay(slowPacedPollInterval) |
| .await |
| private lazy val awaitAtMostTenSeconds = calmlyAwait.atMost(10, TimeUnit.SECONDS) |
| |
| @BeforeEach |
| def setUp(server: GuiceJamesServer): Unit = { |
| server.getProbe(classOf[DataProbeImpl]) |
| .fluent |
| .addDomain(DOMAIN.asString) |
| .addUser(BOB.asString, BOB_PASSWORD) |
| .addUser(ANDRE.asString(), ANDRE_PASSWORD) |
| |
| requestSpecification = baseRequestSpecBuilder(server) |
| .setAuth(authScheme(UserCredential(BOB, BOB_PASSWORD))) |
| .build |
| } |
| |
| def randomMessageId: MessageId |
| |
| @Test |
| def emailGetShouldFailWhenWrongAccountId(): Unit = { |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "unknownAccountId", |
| | "ids": [] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "accountNotFound" |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def idsShouldBeMandatory(): Unit = { |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": null |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "invalidArguments", |
| | "description": "ids can not be ommited for email/get" |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def noIdsShouldBeAccepted(): Unit = { |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": [] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def invalidIdsShouldBeNotFound(): Unit = { |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["invalid"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": ["invalid"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def notExistingValidIdsShouldBeNotFound(): Unit = { |
| val messageId: MessageId = randomMessageId |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": ["${messageId.serialize}"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def existingEmailsShouldBeFound(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [{ |
| | "id": "${messageId.serialize}", |
| | "size": 85 |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def messageIdPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["messageId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "messageId": ["13d4375e-a4a9-f613-06a1-7e8cb1e0ea93@linagora.com"] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def inReplyToPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["inReplyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "inReplyTo": ["d5c6f1d6-96e7-8172-9fe6-41fa6c9bd6ec@linagora.com"] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def referencesPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["references"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "references": ["9b6a4271-69fb-217a-5c14-c68c68375d96@linagora.com"] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def toPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("To", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["to"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "to": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def toPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("To", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("To", |
| "user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["to"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "to": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def toPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("To", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["to"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "to": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def fromPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("From", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["from"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "from": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def ccPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Cc", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["cc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "cc": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bccPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Bcc", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["bcc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "bcc": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Sender", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sender": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def replyToPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Reply-To", |
| "=?UTF-8?Q?MODAL=C4=B0F?=\r\n <modalif@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["replyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "replyTo": [ |
| | { |
| | "name": "MODALÄ°F", |
| | "email": "modalif@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def subjectPropertyShouldDecodeField(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Subject", |
| "=?UTF-8?Q?MODAL=C4=B0F?= is\r\n the best!")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["subject"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "subject": "MODALÄ°F is the best!" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def fromPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("From", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("From", |
| "user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["from"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "from": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def ccPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Cc", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("Cc", |
| "user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["cc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "cc": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bccPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Bcc", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("Bcc", |
| "user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["bcc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "bcc": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Sender", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("Sender", |
| "user2@domain.tld")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sender": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def replyToPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Reply-To", |
| "\"user1\" <user1@domain.tld>")) |
| .addField(new RawField("Reply-To", |
| "user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["replyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "replyTo": [ |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def subjectPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Subject", |
| "Ga Bou")) |
| .addField(new RawField("Subject", |
| "Zo Meuh")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["subject"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "subject": "Zo Meuh" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def toPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["to"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def ccPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Cc", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["cc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "cc": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def ccPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["cc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bccPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Bcc", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["bcc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "bcc": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bccPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["bcc"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def fromPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("From", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["from"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "from": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def fromPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["from"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def replyToPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Reply-To", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["replyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "replyTo": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def replyToPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["replyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def subjectPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["subject"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "subject": "test" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def subjectPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["subject"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def sentAtPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Date", |
| "Wed, 9 Sep 2020 07:00:26 +0200")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sentAt"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sentAt": "2020-09-09T05:00:26Z" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def sentAtPropertyShouldReturnLastWhenMultipleFields(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Date", |
| "Wed, 9 Sep 2014 07:00:26 +0200")) |
| .addField(new RawField("Date", |
| "Wed, 9 Sep 2020 07:00:26 +0200")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sentAt"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sentAt": "2020-09-09T05:00:26Z" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def sentAtPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setDate(null) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sentAt"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldBeSupported(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Sender", |
| "\"user1\" <user1@domain.tld>")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sender": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldBeSupportedWhenNoName(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Sender", |
| "user1@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sender": [ |
| | { |
| | "email": "user1@domain.tld" |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldDisplayBothValues(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .addField(new RawField("Sender", |
| "\"user1\" <user1@domain.tld>, user2@domain.tld")) |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "sender": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "email": "user2@domain.tld" |
| | } |
| | |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def senderPropertyShouldBeNullWhenMissing(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def messageIdShouldReturnNullWhenNone(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["messageId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "messageId":null |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def inReplyToShouldReturnNullWhenNone(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["inReplyTo"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "inReplyTo":null |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def referencesShouldReturnNullWhenNone(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["references"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "references":null |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def foundAndNotFoundCanBeMixed(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| val nonExistingMessageId: MessageId = randomMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "invalid", "${nonExistingMessageId.serialize}"], |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .withOptions(new Options(IGNORING_ARRAY_ORDER)) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ { |
| | "id": "${messageId.serialize}", |
| | "size": 85 |
| | }], |
| | "notFound": ["${nonExistingMessageId.serialize}", "invalid"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def severalEmailCanBeRetrievedAtOnce(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId1: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| val messageId2: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId1.serialize()}", "${messageId2.serialize()}"], |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId1.serialize()}", |
| | "size": 85 |
| | }, |
| | { |
| | "id": "${messageId2.serialize()}", |
| | "size": 85 |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def useDefaultPropertiesWhenNone(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.builder() |
| .withInternalDate(Date.from(ZonedDateTime.parse("2014-10-30T14:12:00Z").toInstant)) |
| .build(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "threadId": "${messageId.serialize}", |
| | "size": 2695, |
| | "keywords": {}, |
| | "blobId": "${messageId.serialize}", |
| | "mailboxIds": {"${mailboxId.serialize}": true}, |
| | "id": "${messageId.serialize}", |
| | "receivedAt": "2014-10-30T14:12:00Z", |
| | "references": null, |
| | "subject": "MultiAttachment", |
| | "inReplyTo": null, |
| | "messageId": ["13d4375e-a4a9-f613-06a1-7e8cb1e0ea93@linagora.com"], |
| | "from": [{"name": "Lina","email": "from@linagora.com"}], |
| | "sentAt": "2017-02-27T04:24:48Z", |
| | "to": [{"email": "to@linagora.com"}], |
| | "textBody": [ |
| | { |
| | "partId": "2", |
| | "blobId": "${messageId.serialize}_2", |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "utf-8" |
| | } |
| | ], |
| | "attachments": [ |
| | { |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "size": 271, |
| | "name": "text1", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "size": 398, |
| | "name": "text2", |
| | "type": "application/vnd.ms-publisher", |
| | "charset": "us-ascii", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "size": 412, |
| | "name": "text3", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | } |
| | ], |
| | "htmlBody": [ |
| | { |
| | "partId": "2", |
| | "blobId": "${messageId.serialize}_2", |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "utf-8" |
| | } |
| | ], |
| | "bodyValues": {}, |
| | "preview": "Send", |
| | "hasAttachment": true |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldInlineMDN(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.builder() |
| .withInternalDate(Date.from(ZonedDateTime.parse("2014-10-30T14:12:00Z").toInstant)) |
| .build(ClassLoaderUtils.getSystemResourceAsSharedStream("eml/mdn_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "inReplyTo": null, |
| | "to": [ |
| | { |
| | "email": "magiclan@linagora.com" |
| | } |
| | ], |
| | "receivedAt": "2014-10-30T14:12:00Z", |
| | "sentAt": "2021-03-30T03:31:50Z", |
| | "attachments": [], |
| | "subject": "Read: test", |
| | "size": 908, |
| | "blobId": "${messageId.serialize()}", |
| | "preview": "This is simple body of human-readable part", |
| | "references": null, |
| | "id": "${messageId.serialize()}", |
| | "htmlBody": [ |
| | { |
| | "charset": "UTF-8", |
| | "size": 42, |
| | "partId": "2", |
| | "blobId": "${messageId.serialize()}_2", |
| | "type": "text/plain" |
| | }, |
| | { |
| | "charset": "UTF-8", |
| | "size": 108, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize()}_3", |
| | "type": "message/disposition-notification" |
| | } |
| | ], |
| | "mailboxIds": { |
| | "${mailboxId.serialize()}": true |
| | }, |
| | "bodyValues": {}, |
| | "messageId": [ |
| | "Mime4j.f.9089aa43e656a14b.1788130035c@linagora.com" |
| | ], |
| | "from": [ |
| | { |
| | "email": "tungexplorer@linagora.com" |
| | } |
| | ], |
| | "keywords": {}, |
| | "textBody": [ |
| | { |
| | "charset": "UTF-8", |
| | "size": 42, |
| | "partId": "2", |
| | "blobId": "${messageId.serialize()}_2", |
| | "type": "text/plain" |
| | }, |
| | { |
| | "charset": "UTF-8", |
| | "size": 108, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize()}_3", |
| | "type": "message/disposition-notification" |
| | } |
| | ], |
| | "threadId": "${messageId.serialize()}", |
| | "hasAttachment": false |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def requestingTheSameIdTwiceReturnsItOnce(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"], |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [{ |
| | "id": "${messageId.serialize}", |
| | "size": 85 |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def propertiesShouldBeFiltered(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"], |
| | "properties": ["id"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [{ |
| | "id": "${messageId.serialize}" |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emptyPropertiesDefaultsToId(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"], |
| | "properties": [] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [{ |
| | "id": "${messageId.serialize}" |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def idPropertyShouldAlwaysBeReturned(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"], |
| | "properties": ["size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [{ |
| | "id": "${messageId.serialize}", |
| | "size": 85 |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def invalidPropertiesShouldFail(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"], |
| | "properties": ["invalid"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "invalidArguments", |
| | "description": "The following properties [invalid] do not exist." |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def requestingTheSameNotFoundIdTwiceReturnsItOnce(): Unit = { |
| val messageId: MessageId = randomMessageId |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}", "${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": ["${messageId.serialize}"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def getShouldReturnNotFoundWhenNoRights(server: GuiceJamesServer): Unit = { |
| val andreMailbox: String = "andrecustom" |
| val path = MailboxPath.forUser(ANDRE, andreMailbox) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(ANDRE.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": ["${messageId.serialize}"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def getShouldReturnMessagesInDelegatedMailboxes(server: GuiceJamesServer): Unit = { |
| val andreMailbox: String = "andrecustom" |
| val path = MailboxPath.forUser(ANDRE, andreMailbox) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(ANDRE.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| server.getProbe(classOf[ACLProbeImpl]) |
| .replaceRights(path, BOB.asString, new MailboxACL.Rfc4314Rights(Right.Read)) |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [{ |
| | "id": "${messageId.serialize}", |
| | "size": 85 |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def getShouldReturnNotFoundWhenDeletedUserMissesReadRight(server: GuiceJamesServer): Unit = { |
| val andreMailbox: String = "andrecustom" |
| val path = MailboxPath.forUser(ANDRE, andreMailbox) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(ANDRE.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| server.getProbe(classOf[ACLProbeImpl]) |
| .replaceRights(path, BOB.asString, MailboxACL.Rfc4314Rights.allExcept(Right.Read)) |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${INSTANCE.value}", |
| | "list": [], |
| | "notFound": ["${messageId.serialize}"] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnUnknownMethodWhenMissingOneCapability(): Unit = { |
| val messageId: MessageId = randomMessageId |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": ["urn:ietf:params:jmap:core"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "unknownMethod", |
| | "description": "Missing capability(ies): urn:ietf:params:jmap:mail" |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnUnknownMethodWhenMissingAllCapabilities(): Unit = { |
| val messageId: MessageId = randomMessageId |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "unknownMethod", |
| | "description": "Missing capability(ies): urn:ietf:params:jmap:core, urn:ietf:params:jmap:mail" |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyPropertiesFilteringShouldBeApplied(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "partId": "1", |
| | "blobId": "${messageId.serialize}_1" |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldSupportAttachedMessageWithComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/nested2.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId", "subParts","size", "type"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .inPath("methodResponses[0][1].list[0].bodyStructure") |
| .isEqualTo( |
| s"""{ |
| | "subParts": [ |
| | { |
| | "size": 0, |
| | "partId": "2", |
| | "blobId": "${messageId.serialize()}_2", |
| | "type": "text/plain" |
| | }, |
| | { |
| | "size": 2093, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize()}_3", |
| | "type": "message/rfc822" |
| | } |
| | ], |
| | "size": 2513, |
| | "partId": "1", |
| | "type": "multipart/mixed" |
| | }""".stripMargin) |
| } |
| |
| @Test |
| def mailboxIdsPropertiesShouldBeReturned(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| val mailboxId: MailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["mailboxIds"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "mailboxIds": { |
| | "${mailboxId.serialize}": true |
| | } |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def receivedAtPropertyShouldBeReturned(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.builder() |
| .withInternalDate(Date.from(ZonedDateTime.parse("2014-10-30T14:12:00Z").toInstant)) |
| .build(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["receivedAt"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "receivedAt": "2014-10-30T14:12:00Z" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def blobIdPropertiesShouldBeReturned(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["blobId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "blobId": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def threadIdPropertiesShouldBeReturned(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["threadId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "threadId": "${messageId.serialize}" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyPropertiesShouldMatchSpecifiedDefaults(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "partId": "1", |
| | "blobId": "${messageId.serialize}_1", |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "UTF-8" |
| | } |
| | } |
| | ], |
| | "notFound": [ |
| | |
| | ] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emptyBodyPropertiesShouldReturnEmptyObjects(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":[] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": {} |
| | } |
| | ], |
| | "notFound": [ |
| | |
| | ] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def invalidBodyPropertiesShouldBeRejected(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["invalid"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "error", |
| | { |
| | "type": "invalidArguments", |
| | "description": "The following bodyProperties [invalid] do not exist." |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyStructureForSimpleMessage(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location", "subParts", "headers"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "partId": "1", |
| | "blobId": "${messageId.serialize}_1", |
| | "headers": [ |
| | { |
| | "name": "MIME-Version", |
| | "value": " 1.0" |
| | }, |
| | { |
| | "name": "Subject", |
| | "value": " test" |
| | }, |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=UTF-8" |
| | } |
| | ], |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "UTF-8" |
| | } |
| | } |
| | ], |
| | "notFound": [ |
| | |
| | ] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyStructureShouldSupportSpecificHeaders(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "header:Subject:asText"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "header:Subject:asText": "test", |
| | "charset": "UTF-8", |
| | "size": 8, |
| | "partId": "1", |
| | "blobId": "${messageId.serialize}_1", |
| | "type": "text/plain" |
| | } |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyStructureForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location", "subParts", "headers"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| val contentType = " multipart/mixed;\\r\\n boundary=\\\"------------64D8D789FC30153D6ED18258\\\"" |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "partId": "1", |
| | "headers": [ |
| | { |
| | "name": "Return-Path", |
| | "value": " <from@linagora.com>" |
| | }, |
| | { |
| | "name": "To", |
| | "value": " to@linagora.com" |
| | }, |
| | { |
| | "name": "From", |
| | "value": " Lina <from@linagora.com>" |
| | }, |
| | { |
| | "name": "Subject", |
| | "value": " MultiAttachment" |
| | }, |
| | { |
| | "name": "Message-ID", |
| | "value": " <13d4375e-a4a9-f613-06a1-7e8cb1e0ea93@linagora.com>" |
| | }, |
| | { |
| | "name": "Date", |
| | "value": " Mon, 27 Feb 2017 11:24:48 +0700" |
| | }, |
| | { |
| | "name": "User-Agent", |
| | "value": " Mozilla/5.0 (X11; Linux x86_64; rv:45.0) Gecko/20100101\\r\\n Thunderbird/45.2.0" |
| | }, |
| | { |
| | "name": "MIME-Version", |
| | "value": " 1.0" |
| | }, |
| | { |
| | "name": "Content-Type", |
| | "value": "$contentType" |
| | } |
| | ], |
| | "size": 1880, |
| | "type": "multipart/mixed", |
| | "charset": "us-ascii", |
| | "subParts": [ |
| | { |
| | "partId": "2", |
| | "blobId": "${messageId.serialize}_2", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=utf-8; format=flowed" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " 7bit" |
| | } |
| | ], |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "utf-8" |
| | }, |
| | { |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=UTF-8;\\r\\n name=\\\"text1\\\"" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " base64" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": " attachment;\\r\\n filename=\\\"text1\\\"" |
| | } |
| | ], |
| | "size": 271, |
| | "name": "text1", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " application/vnd.ms-publisher;\\r\\n name=\\\"text2\\\"" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " base64" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": " attachment;\\r\\n filename=\\\"text2\\\"" |
| | } |
| | ], |
| | "size": 398, |
| | "name": "text2", |
| | "type": "application/vnd.ms-publisher", |
| | "charset": "us-ascii", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=UTF-8;\\r\\n name=\\\"text3\\\"" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " base64" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": " attachment;\\r\\n filename=\\\"text3\\\"" |
| | } |
| | ], |
| | "size": 412, |
| | "name": "text3", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | } |
| | ] |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyStructureForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyStructure"], |
| | "bodyProperties":["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "language", "location", "subParts", "headers"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyStructure": { |
| | "partId": "1", |
| | "headers": [ |
| | { |
| | "name": "Date", |
| | "value": " Tue, 03 Jan 2017 16:05:01 +0100" |
| | }, |
| | { |
| | "name": "From", |
| | "value": " sender <sender@james.org>" |
| | }, |
| | { |
| | "name": "MIME-Version", |
| | "value": " 1.0" |
| | }, |
| | { |
| | "name": "To", |
| | "value": " David DOLCIMASCOLO <david.ddo@linagora.com>" |
| | }, |
| | { |
| | "name": "Subject", |
| | "value": " Re: [Internet] Rendez-vous" |
| | }, |
| | { |
| | "name": "References", |
| | "value": " <9b6a4271-69fb-217a-5c14-c68c68375d96@linagora.com>" |
| | }, |
| | { |
| | "name": "In-Reply-To", |
| | "value": " <d5c6f1d6-96e7-8172-9fe6-41fa6c9bd6ec@linagora.com>" |
| | }, |
| | { |
| | "name": "X-Gie-Attachments", |
| | "value": " none" |
| | }, |
| | { |
| | "name": "Cc", |
| | "value": "" |
| | }, |
| | { |
| | "name": "Content-type", |
| | "value": " multipart/mixed; boundary=\\"----------=_1483455916-7086-3\\"" |
| | } |
| | ], |
| | "size": 891, |
| | "type": "multipart/mixed", |
| | "charset": "us-ascii", |
| | "subParts": [ |
| | { |
| | "partId": "2", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " multipart/alternative; boundary=\\\"------------060506070600060108040700\\\"" |
| | } |
| | ], |
| | "size": 398, |
| | "type": "multipart/alternative", |
| | "charset": "us-ascii", |
| | "subParts": [ |
| | { |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=ISO-8859-1; format=flowed" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " 8bit" |
| | } |
| | ], |
| | "size": 20, |
| | "type": "text/plain", |
| | "charset": "ISO-8859-1" |
| | }, |
| | { |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "headers": [ |
| | { |
| | "name": "Content-Type", |
| | "value": " text/html; charset=ISO-8859-1" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " 7bit" |
| | } |
| | ], |
| | "size": 30, |
| | "type": "text/html", |
| | "charset": "ISO-8859-1" |
| | } |
| | ] |
| | }, |
| | { |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "headers": [ |
| | { |
| | "name": "Content-ID", |
| | "value": " <14672787885774e5c4d4cee471352039@linagora.com>" |
| | }, |
| | { |
| | "name": "Content-Type", |
| | "value": " text/plain; charset=\\\"iso-8859-1\\\"; name=\\\"avertissement.txt\\\"" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": " inline; filename=\\\"avertissement.txt\\\"" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " binary" |
| | } |
| | ], |
| | "size": 19, |
| | "name": "avertissement.txt", |
| | "type": "text/plain", |
| | "charset": "iso-8859-1", |
| | "disposition": "inline", |
| | "cid": "14672787885774e5c4d4cee471352039@linagora.com" |
| | } |
| | ] |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textBodyForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["textBody"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "textBody": [ |
| | { |
| | "partId": "2", |
| | "blobId": "${messageId.serialize}_2", |
| | "size": 8, |
| | "type": "text/plain", |
| | "charset": "utf-8" |
| | } |
| | ] |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textBodyForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["textBody"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "textBody": [ |
| | { |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "size": 20, |
| | "type": "text/plain", |
| | "charset": "ISO-8859-1" |
| | }, |
| | { |
| | "charset": "iso-8859-1", |
| | "disposition": "inline", |
| | "size": 19, |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "name": "avertissement.txt", |
| | "type": "text/plain", |
| | "cid": "14672787885774e5c4d4cee471352039@linagora.com" |
| | } |
| | ] |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def htmlBodyForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["htmlBody"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "htmlBody": [ |
| | { |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "size": 30, |
| | "type": "text/html", |
| | "charset": "ISO-8859-1" |
| | }, |
| | { |
| | "charset": "iso-8859-1", |
| | "disposition": "inline", |
| | "size": 19, |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "name": "avertissement.txt", |
| | "type": "text/plain", |
| | "cid": "14672787885774e5c4d4cee471352039@linagora.com" |
| | } |
| | ] |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textBodyValuesForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "2": { |
| | "value": "Send\\r\\n\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textBodyValuesForHtmlMessage(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/html.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "2": { |
| | "value": "Send\\nconcerted from html\\n\\n\\r\\n\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textBodyValuesForAlternativeMessage(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/alternative.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "notFound": [ |
| | |
| | ], |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "3": { |
| | "value": "I am the text plain part!\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def attachmentValuesForInlinedMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/inlined-mixed.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues", "attachments"], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "notFound": [ |
| | |
| | ], |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "attachments": [ |
| | { |
| | "charset": "us-ascii", |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "type": "application/json", |
| | "name":"yyy.txt" |
| | }, |
| | { |
| | "charset": "us-ascii", |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "type": "application/json", |
| | "name":"xxx.txt" |
| | } |
| | ], |
| | "bodyValues": { |
| | "2": { |
| | "value": "Main test message...\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldUseFullViewReaderWhenFetchAllBodyProperties(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/inlined-mixed.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail" |
| | ], |
| | "methodCalls": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": [ |
| | "id", |
| | "subject", |
| | "from", |
| | "to", |
| | "cc", |
| | "bcc", |
| | "keywords", |
| | "size", |
| | "receivedAt", |
| | "sentAt", |
| | "preview", |
| | "hasAttachment", |
| | "attachments", |
| | "replyTo", |
| | "mailboxIds" |
| | ], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "notFound": [], |
| | "list": [{ |
| | "preview": "Main test message...", |
| | "to": [{ |
| | "name": "Alice", |
| | "email": "alice@domain.tld" |
| | }], |
| | "id": "${messageId.serialize}", |
| | "mailboxIds": { |
| | "${mailboxId.serialize}": true |
| | }, |
| | "from": [{ |
| | "name": "Bob", |
| | "email": "bob@domain.tld" |
| | }], |
| | "keywords": { |
| | |
| | }, |
| | "receivedAt": "$${json-unit.ignore}", |
| | "sentAt": "$${json-unit.ignore}", |
| | "hasAttachment": true, |
| | "attachments": [{ |
| | "charset": "us-ascii", |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "name": "yyy.txt", |
| | "type": "application/json" |
| | }, |
| | { |
| | "charset": "us-ascii", |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "name": "xxx.txt", |
| | "type": "application/json" |
| | } |
| | ], |
| | "subject": "My subject", |
| | "size": 970 |
| | }] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldUseFastViewWithAttachmentMetadataWhenSupportedBodyProperties(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| val mailboxId = server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/inlined-mixed.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail" |
| | ], |
| | "methodCalls": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": [ |
| | "id", |
| | "subject", |
| | "from", |
| | "to", |
| | "cc", |
| | "bcc", |
| | "keywords", |
| | "size", |
| | "receivedAt", |
| | "sentAt", |
| | "preview", |
| | "hasAttachment", |
| | "attachments", |
| | "replyTo", |
| | "mailboxIds" |
| | ], |
| | "fetchTextBodyValues": true, |
| | "bodyProperties": ["partId", "blobId", "size", "name", "type", "charset", "disposition", "cid", "headers"] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "notFound": [], |
| | "list": [{ |
| | "preview": "Main test message...", |
| | "to": [{ |
| | "name": "Alice", |
| | "email": "alice@domain.tld" |
| | }], |
| | "id": "${messageId.serialize}", |
| | "mailboxIds": { |
| | "${mailboxId.serialize}": true |
| | }, |
| | "from": [{ |
| | "name": "Bob", |
| | "email": "bob@domain.tld" |
| | }], |
| | "keywords": { |
| | |
| | }, |
| | "receivedAt": "$${json-unit.ignore}", |
| | "sentAt": "$${json-unit.ignore}", |
| | "hasAttachment": true, |
| | "attachments": [{ |
| | "charset": "us-ascii", |
| | "headers": [{ |
| | "name": "Content-Type", |
| | "value": " application/json; charset=us-ascii" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": "$${json-unit.ignore}" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " quoted-printable" |
| | } |
| | ], |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "name": "yyy.txt", |
| | "type": "application/json" |
| | }, |
| | { |
| | "charset": "us-ascii", |
| | "headers": [{ |
| | "name": "Content-Type", |
| | "value": " application/json; charset=us-ascii" |
| | }, |
| | { |
| | "name": "Content-Disposition", |
| | "value": "$${json-unit.ignore}" |
| | }, |
| | { |
| | "name": "Content-Transfer-Encoding", |
| | "value": " quoted-printable" |
| | } |
| | ], |
| | "disposition": "attachment", |
| | "size": 102, |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "name": "xxx.txt", |
| | "type": "application/json" |
| | } |
| | ], |
| | "subject": "My subject", |
| | "size": 970 |
| | }] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldBeAbleToDownloadAttachmentBaseOnFastViewWithAttachmentsMetadataResult(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/inlined-single-attachment.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail" |
| | ], |
| | "methodCalls": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": [ |
| | "id", |
| | "subject", |
| | "from", |
| | "to", |
| | "cc", |
| | "bcc", |
| | "keywords", |
| | "size", |
| | "receivedAt", |
| | "sentAt", |
| | "preview", |
| | "hasAttachment", |
| | "attachments", |
| | "replyTo", |
| | "mailboxIds" |
| | ], |
| | "fetchTextBodyValues": true, |
| | "bodyProperties": ["blobId", "size", "name", "type", "charset", "disposition", "cid"] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin |
| |
| val blobId = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .jsonPath() |
| .getString("methodResponses[0][1].list[0].attachments[0].blobId") |
| |
| val blob = `given` |
| .basePath("") |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .when |
| .get(s"/download/29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6/$blobId") |
| .`then` |
| .statusCode(SC_OK) |
| .contentType("application/json") |
| .extract |
| .body |
| .asString |
| |
| val expectedBlob: String = |
| """[ |
| | { |
| | "Id": "2xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx" |
| | } |
| |]""".stripMargin |
| |
| assertThat(new ByteArrayInputStream(blob.getBytes(StandardCharsets.UTF_8))) |
| .hasContent(expectedBlob) |
| } |
| |
| @Test |
| def textBodyValuesForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "3": { |
| | "value": "/blabla/\\r\\n*bloblo*\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "5":{ |
| | "value": "inline attachment\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def htmlBodyValuesForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchHTMLBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "4": { |
| | "value": "<i>blabla</i>\\r\\n<b>bloblo</b>\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "5": { |
| | "value": "inline attachment\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def htmlBodyValuesShouldFallBackToPlainTextWhenNoHtmlPart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/alternative.cal.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues", "htmlBody"], |
| | "fetchHTMLBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .inPath(s"methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "htmlBody": [{ |
| | "charset": "UTF-8", |
| | "size": 47, |
| | "partId": "3", |
| | "blobId": "${messageId.serialize()}_3", |
| | "type": "text/plain" |
| | }], |
| | "id": "${messageId.serialize()}", |
| | "bodyValues": { |
| | "3": { |
| | "value": "J <j@linagora.com> a accepté votre invitation.", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textAndHtmlBodyValuesForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true, |
| | "fetchHTMLBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "3": { |
| | "value": "/blabla/\\r\\n*bloblo*\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "4": { |
| | "value": "<i>blabla</i>\\r\\n<b>bloblo</b>\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "5":{ |
| | "value": "inline attachment\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ] |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def textAndHtmlBodyValuesForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchTextBodyValues": true, |
| | "fetchHTMLBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "2": { |
| | "value": "Send\\r\\n\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def allBodyValuesForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchAllBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "2": { |
| | "value": "Send\\r\\n\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "3": { |
| | "value": "-----BEGIN RSA PRIVATE KEY-----\\nMIIEogIBAAKCAQEAx7PG0+E//EMpm7IgI5Q9TMDSFya/1hE+vvTJrk0iGFllPeHL\\nA5/VlTM0YWgG6X50qiMfE3VLazf2c19iXrT0mq/21PZ1wFnogv4zxUNaih+Bng62\\nF0SyruE/O/Njqxh/Ccq6K/e05TV4T643USxAeG0KppmYW9x8HA/GvV832apZuxkV\\ni6NVkDBrfzaUCwu4zH+HwOv/pI87E7KccHYC++Biaj3\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "5": { |
| | "value": "|1|oS75OgL3vF2Gdl99CJDbEpaJ3yE=|INGqljCW1XMf4ggOQm26/BNnKGc= ssh-rsa AAAAB3NzaC1yc2EAAAABIwAAAQEAq2A7hRGmdnm9tUDbO9IDSwBK6TbQa+PXYPCPy6rbTrTtw7PHkccKrpp0yVhp5HdEIcKr6pLlVDBfOLX9QUsyCOV0wzfjIJNlGEYsdlLJizHhbn2mUjvSAHQqZETYP81eFzLQNnPHt4EVVUh7VfDESU84KezmD5QlWpXLmvU31/yMf+Se8xhHTvKSCZIFImWwoG6mbUoWf9nzpIoaSjB+weqqUUmpaaasXVal72J+UX2B+2RPW3RcT0eOzQgqlJL3RKrTJvdsjE3JEAvGq3lGHSZXyN6m5U4hpph9uOv54aHc4Xr8jhAa/SX5MJ\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def htmlBodyValuesForRelatedMultipartInsideAlternative(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/related_in_alternative_multipart.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchHTMLBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "4": { |
| | "value": "<table></table>", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyValueShouldBeTruncatedIfNeeded(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchAllBodyValues": true, |
| | "maxBodyValueBytes": 32 |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [ |
| | [ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "2": { |
| | "value": "Send\\r\\n\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "3": { |
| | "value": "-----BEGIN RSA PRIVATE KEY-----\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": true |
| | }, |
| | "5": { |
| | "value": "|1|oS75OgL3vF2Gdl99CJDbEpaJ3yE=|", |
| | "isEncodingProblem": false, |
| | "isTruncated": true |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def allBodyValuesForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"], |
| | "fetchAllBodyValues": true |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": { |
| | "3": { |
| | "value": "/blabla/\\r\\n*bloblo*\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "4": { |
| | "value": "<i>blabla</i>\\r\\n<b>bloblo</b>\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | }, |
| | "5": { |
| | "value": "inline attachment\\r\\n", |
| | "isEncodingProblem": false, |
| | "isTruncated": false |
| | } |
| | } |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bodyValuesShouldBeEmptyWithoutFetch(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["bodyValues"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "bodyValues": {} |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def attachmentsForSimpleMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["attachments"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "attachments": [ |
| | { |
| | "partId": "3", |
| | "blobId": "${messageId.serialize}_3", |
| | "size": 271, |
| | "name": "text1", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "4", |
| | "blobId": "${messageId.serialize}_4", |
| | "size": 398, |
| | "name": "text2", |
| | "type": "application/vnd.ms-publisher", |
| | "charset": "us-ascii", |
| | "disposition": "attachment" |
| | }, |
| | { |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "size": 412, |
| | "name": "text3", |
| | "type": "text/plain", |
| | "charset": "UTF-8", |
| | "disposition": "attachment" |
| | } |
| | ] |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def attachmentsForComplexMultipart(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_complex.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["attachments"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [ |
| | { |
| | "id": "${messageId.serialize}", |
| | "attachments": [ |
| | { |
| | "partId": "5", |
| | "blobId": "${messageId.serialize}_5", |
| | "size": 19, |
| | "name": "avertissement.txt", |
| | "type": "text/plain", |
| | "charset": "iso-8859-1", |
| | "disposition": "inline", |
| | "cid": "14672787885774e5c4d4cee471352039@linagora.com" |
| | } |
| | ] |
| | } |
| | ], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def previewForSimpleEmail(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["preview"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "preview": "testmail" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def previewShouldBeTruncatedForLongTextBodies(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("0123456789".repeat(100), StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["preview"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "preview": "${"0123456789".repeat(25)}012345" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def previewForSimpleEmailWithoutBody(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["preview"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "preview": "" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def previewForSimpleEmailWithHtmlBody(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("A <b>HTML</b> body...", "html", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["preview"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "preview": "A HTML body..." |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def hasAttachmentForSimpleEmail(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["hasAttachment"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo(s"""{ |
| | "id": "${messageId.serialize}", |
| | "hasAttachment": false |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def hasAttachmentForMultipartWithAttachment(server: GuiceJamesServer): Unit = { |
| |
| val path = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["hasAttachment"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "hasAttachment": true |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def hasAttachmentForMultipartWithoutAttachment(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody(MultipartBuilder.create() |
| .addTextPart("body", StandardCharsets.UTF_8) |
| .build()) |
| .build() |
| |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core","urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties":["hasAttachment"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "hasAttachment": false |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnUnparsedHeaders(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["headers"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .whenIgnoringPaths("methodResponses[0][1].state") |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "list": [{ |
| | "id": "${messageId.serialize}", |
| | "headers": [ |
| | {"name":"MIME-Version","value":" 1.0"}, |
| | {"name":"Subject","value":" =?US-ASCII?Q?World_domination_=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header?="}, |
| | {"name":"Sender","value":" andre@domain.tld"}, |
| | {"name":"From","value":" andre@domain.tld"}, |
| | {"name":"Content-Type","value":" text/plain; charset=UTF-8"} |
| | ] |
| | }], |
| | "notFound": [] |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificUnparsedHeaders(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB); |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject", "header:From", "header:Sender"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Subject":" =?US-ASCII?Q?World_domination_=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header?=", |
| | "header:From":" andre@domain.tld", |
| | "header:Sender":" andre@domain.tld" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificUnparsedHeadersWithInsensitiveCaseMatching(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB); |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:subJeCt"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:subJeCt":" =?US-ASCII?Q?World_domination_=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header?=" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldRejectSpecificUnparsedHeadersWithColon(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB); |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:From:Subject"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "invalidArguments", |
| | "description": "The following properties [header:From:Subject] do not exist." |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnNullWhenUnknownSpecificUnparsedHeaders(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB); |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:blahblah"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:blahblah": null |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldRejectEmptySpecificUnparsedHeaders(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB); |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response).isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "invalidArguments", |
| | "description": "The following properties [header:] do not exist." |
| | }, |
| | "c1" |
| | ]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnKeyword(server: GuiceJamesServer): Unit = { |
| val message: Message = createTestMessage |
| |
| val flags: Flags = new Flags(Flags.Flag.ANSWERED) |
| |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]).appendMessage(BOB.asString(), bobPath, AppendCommand.builder() |
| .withFlags(flags) |
| .build(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["keywords"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo(String.format( |
| """ |
| | { |
| | "id":"%s", |
| | "keywords": { |
| | "$answered": true |
| | } |
| | } |
| """.stripMargin, messageId.serialize) |
| ) |
| } |
| |
| @Test |
| def emailGetShouldReturnSystemKeywords(server: GuiceJamesServer): Unit = { |
| val message: Message = createTestMessage |
| |
| val flags: Flags = new Flags(Flags.Flag.ANSWERED) |
| flags.add(Flags.Flag.DRAFT) |
| flags.add(Flags.Flag.FLAGGED) |
| flags.add(Flags.Flag.SEEN) |
| |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]).appendMessage(BOB.asString(), bobPath, AppendCommand.builder() |
| .withFlags(flags) |
| .build(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["keywords"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo(String.format( |
| """ |
| | { |
| | "id":"%s", |
| | "keywords": { |
| | "$answered": true, |
| | "$seen": true, |
| | "$draft": true, |
| | "$flagged": true |
| | } |
| | } |
| """.stripMargin, messageId.serialize) |
| ) |
| } |
| |
| @Test |
| def emailGetShouldReturnSystemAndUserKeywordsIfExposed(server: GuiceJamesServer): Unit = { |
| val message: Message = createTestMessage |
| |
| val flags: Flags = new Flags(Flags.Flag.ANSWERED) |
| flags.add(Flags.Flag.DRAFT) |
| flags.add(Flags.Flag.FLAGGED) |
| flags.add("custom_flag") |
| |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]).appendMessage(BOB.asString(), bobPath, AppendCommand.builder() |
| .withFlags(flags) |
| .build(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["keywords"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo(String.format( |
| """ |
| | { |
| | "id":"%s", |
| | "keywords": { |
| | "$answered": true, |
| | "custom_flag": true, |
| | "$draft": true, |
| | "$flagged": true |
| | } |
| | } |
| """.stripMargin, messageId.serialize) |
| ) |
| } |
| |
| @Test |
| def emailGetShouldNotReturnNonExposedKeywords(server: GuiceJamesServer): Unit = { |
| val message: Message = createTestMessage |
| |
| val nonExposedFlags: Flags = new Flags(Flags.Flag.RECENT) |
| nonExposedFlags.add(Flags.Flag.DELETED) |
| |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]).appendMessage(BOB.asString(), bobPath, AppendCommand.builder() |
| .withFlags(nonExposedFlags) |
| .build(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["keywords"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s""" |
| | { |
| | "id":"${messageId.serialize}", |
| | "keywords": {} |
| | } |
| """.stripMargin) |
| } |
| |
| @Test |
| def shouldAggregateKeywordsAccrossMailbox(server: GuiceJamesServer): Unit = { |
| val message: Message = createTestMessage |
| |
| val flags1: Flags = new Flags(Flags.Flag.ANSWERED) |
| flags1.add(Flags.Flag.FLAGGED) |
| flags1.add("f1") |
| flags1.add("f2") |
| |
| val flags2: Flags = new Flags(Flags.Flag.SEEN) |
| flags2.add(Flags.Flag.FLAGGED) |
| flags2.add("f3") |
| flags2.add("f2") |
| |
| val path1 = MailboxPath.inbox(BOB) |
| val path2 = MailboxPath.forUser(BOB, "box2") |
| val mailboxProbe = server.getProbe(classOf[MailboxProbeImpl]) |
| mailboxProbe.createMailbox(path1) |
| mailboxProbe.createMailbox(path2) |
| val messageId: ComposedMessageId = mailboxProbe.appendMessage(BOB.asString(), path1, AppendCommand.builder() |
| .withFlags(flags1) |
| .build(message)) |
| mailboxProbe.copy(BOB, path1, path2, messageId.getUid) |
| mailboxProbe.setFlags(BOB, path1, messageId.getUid, flags2) |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.getMessageId.serialize}"], |
| | "properties": ["keywords"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s""" |
| | { |
| | "id":"${messageId.getMessageId.serialize}", |
| | "keywords": { |
| | "$$flagged": true, |
| | "f1": true, |
| | "f2": true, |
| | "f3": true, |
| | "$$seen": true, |
| | "$$answered": true |
| | } |
| | } |
| """.stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeadersAsRaw(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject:asRaw"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Subject:asRaw": " =?US-ASCII?Q?World_domination_=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header?=" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def asRawShouldSupportSeveralHeaders(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", |
| "\"user1\" user1@domain.tld")) |
| .addField(new RawField("Cc", |
| "\"user2\" user2@domain.tld")) |
| .addField(new RawField("Bcc", |
| "\"user3\" user3@domain.tld")) |
| .addField(new RawField("ReplyTo", |
| "\"user1\" user1@domain.tld")) |
| .setSubject("World domination \r\n" + |
| " and this is also part of the header") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject:asRaw", "header:Sender:asRaw", "header:From:asRaw", "header:To:asRaw", "header:Cc:asRaw", "header:Bcc:asRaw", |
| | "header:ReplyTo:asRaw", "header:InReplyTo:asRaw", "header:References:asRaw", "header:MessageId:asRaw", "header:sentAt:asRaw"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Bcc:asRaw": " \\"user3\\" user3@domain.tld", |
| | "header:MessageId:asRaw": null, |
| | "header:ReplyTo:asRaw": " \\"user1\\" user1@domain.tld", |
| | "header:From:asRaw": " andre@domain.tld", |
| | "header:Cc:asRaw": " \\"user2\\" user2@domain.tld", |
| | "header:Subject:asRaw": " =?US-ASCII?Q?World_domination_=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header?=", |
| | "header:InReplyTo:asRaw": null, |
| | "header:sentAt:asRaw": null, |
| | "header:To:asRaw": " \\"user1\\" user1@domain.tld", |
| | "header:References:asRaw": null, |
| | "header:Sender:asRaw": " andre@domain.tld" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeadersAsText(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject(" World domination\r\n" + |
| " and this is also part of the header\r\n") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject:asText"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Subject:asText": "World domination and this is also part of the header" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldSupportDifferentSpecificHeadersTypeOnSameMessage(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setSubject(" World domination\r\n" + |
| " and this is also part of the header\r\n") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject:asText", "header:Subject:asRaw"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Subject:asRaw": " =?US-ASCII?Q?___World_domination=0D=0A_and_th?=\\r\\n =?US-ASCII?Q?is_is_also_part_of_the_header=0D=0A?=", |
| | "header:Subject:asText": "World domination and this is also part of the header" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldSupportAllQualifierForSpecificHeader(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .addField(new RawField("Subject", "Another SUB")) |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Subject:asText:all", "header:Subject:all", "header:Missing:all"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Subject:asText:all": ["test", "Another SUB"], |
| | "header:Subject:all": [" test", " Another SUB"], |
| | "header:Missing:all": [] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeadersAsAddresses(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "\" user1 \" <user1@domain.tld>, \"user2\" <user2@domain.tld>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asAddresses": [ |
| | { "name": "user1", "email": "user1@domain.tld" }, |
| | { "name": "user2", "email": "user2@domain.tld" } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeadersAsAddressesAndIgnoresGroup(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "\" user1 \" <user1@domain.tld>, Friends: \"user2\" <user2@domain.tld>, \"user3\" <user3@domain.tld>;")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asAddresses": [ |
| | { "name": "user1", "email": "user1@domain.tld" }, |
| | { "name": "user2", "email": "user2@domain.tld" }, |
| | { "name": "user3", "email": "user3@domain.tld" } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnEmptyWhenCannotParseAsAddresses(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "blahblah")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asAddresses": [] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnGroupedAddresses(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "\" user1 \" <user1@domain.tld>, \" user2 \" <user2@domain.tld>, Friends: <user3@domain.tld>, \"user4\" <user4@domain.tld>;")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asGroupedAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asGroupedAddresses": [ |
| | { |
| | "name": null, |
| | "addresses": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "name": "user2", |
| | "email": "user2@domain.tld" |
| | } |
| | ] |
| | }, |
| | { |
| | "name": "Friends", |
| | "addresses": [ |
| | { |
| | "email": "user3@domain.tld" |
| | }, |
| | { |
| | "name": "user4", |
| | "email": "user4@domain.tld" |
| | } |
| | ] |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnAsGroupedAddressesWithoutGroupInfo(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "\" user1 \" <user1@domain.tld>, \" user2 \" <user2@domain.tld>, <user3@domain.tld>, \"user4\" <user4@domain.tld>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asGroupedAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asGroupedAddresses": [ |
| | { |
| | "name": null, |
| | "addresses": [ |
| | { |
| | "name": "user1", |
| | "email": "user1@domain.tld" |
| | }, |
| | { |
| | "name": "user2", |
| | "email": "user2@domain.tld" |
| | }, |
| | { |
| | "email": "user3@domain.tld" |
| | }, |
| | { |
| | "name": "user4", |
| | "email": "user4@domain.tld" |
| | } |
| | ] |
| | } |
| | ] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnEmptyWhenCannotParseAsGroupedAddresses(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("To", "blahblah")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:To:asGroupedAddresses"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:To:asGroupedAddresses": [] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeaderAsMessageIds(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setMessageId("<1234@local.machine.example>") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Message-Id:asMessageIds"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Message-Id:asMessageIds": [ |
| | "1234@local.machine.example" |
| | ] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetSpecificHeaderAsMessageIdsShouldSupportMultipleIds(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("References", "<1234@local.machine.example> \r\n <3456@example.net>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:References:asMessageIds"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:References:asMessageIds": [ |
| | "1234@local.machine.example", |
| | "3456@example.net" |
| | ] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetAsMessageIdsHeaderShouldReturnNullWhenInvalidMessageIds(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .setMessageId("invalid") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Message-Id:asMessageIds"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Message-Id:asMessageIds": null |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeaderWhenPartialInvalidMessageIds(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("References", "invalid bloblah \r\n <3456@example.net>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:References:asMessageIds"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:References:asMessageIds": [ |
| | "3456@example.net" |
| | ] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeaderAsDate(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("Date", |
| "Wed, 9 Sep 2020 07:00:26 +0200")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Date:asDate"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Date:asDate": "2020-09-09T05:00:26Z" |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnNullWhenInvalidSpecificHeaderAsDate(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("Date", "Invalid")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:Date:asDate"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:Date:asDate": null |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeaderAsURLs(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("List-Help", "<http://www.host.com/list/>, <mailto:list-info@host.com>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:List-Help:asURLs"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:List-Help:asURLs": [ |
| | "http://www.host.com/list/", |
| | "mailto:list-info@host.com" |
| | ] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnSpecificHeaderAsURLsAndIgnoresComments(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("List-Help", "<http://www.host.com/list/>, (FTP) <mailto:list-info@host.com>")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:List-Help:asURLs"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:List-Help:asURLs": [ |
| | "http://www.host.com/list/", |
| | "mailto:list-info@host.com" |
| | ] |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailGetShouldReturnNullWhenInvalidSpecificHeaderAsURLs(server: GuiceJamesServer): Unit = { |
| val bobPath = MailboxPath.inbox(BOB) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(bobPath) |
| val alicePath = MailboxPath.inbox(ALICE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(alicePath) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(ANDRE.asString()) |
| .setFrom(ANDRE.asString()) |
| .addField(new RawField("List-Help", "Invalid")) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, bobPath, AppendCommand.from(message)) |
| .getMessageId |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["header:List-Help:asURLs"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "header:List-Help:asURLs": null |
| }""".stripMargin) |
| } |
| |
| @Test |
| def emailStateShouldBeTheLatestOne(server: GuiceJamesServer): Unit = { |
| val mailboxProbe: MailboxProbeImpl = server.getProbe(classOf[MailboxProbeImpl]) |
| val accountId: AccountId = AccountId.fromUsername(BOB) |
| val path: MailboxPath = MailboxPath.inbox(BOB) |
| mailboxProbe.createMailbox(path) |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setSender(BOB.asString()) |
| .setFrom(ANDRE.asString()) |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| val messageId: String = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, path, AppendCommand.from(message)) |
| .getMessageId |
| .serialize() |
| |
| val state: State = waitForNextState(server, accountId, State.INITIAL) |
| |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body( |
| s"""{ |
| | "using": ["urn:ietf:params:jmap:core", "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": ["$messageId"], |
| | "properties": ["id"] |
| | }, |
| | "c1"] |
| | ] |
| |}""".stripMargin) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .extract() |
| .body() |
| .asString() |
| |
| assertThatJson(response) |
| .withOptions(new Options(Option.IGNORING_ARRAY_ORDER)) |
| .inPath("methodResponses[0][1]") |
| .isEqualTo( |
| s"""{ |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "state": "${state.getValue}", |
| | "list":[ |
| | { |
| | "id":"$messageId" |
| | } |
| | ], |
| | "notFound": [] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bobShouldBeAbleToAccessAndreMailboxWhenDelegated(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(ANDRE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(ANDRE.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| server.getProbe(classOf[DelegationProbe]).addAuthorizedUser(ANDRE, BOB) |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "$ANDRE_ACCOUNT_ID", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["messageId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1].list[0]") |
| .isEqualTo( |
| s"""{ |
| | "id": "${messageId.serialize}", |
| | "messageId": ["13d4375e-a4a9-f613-06a1-7e8cb1e0ea93@linagora.com"] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def bobShouldNotBeAbleToAccessAndreMailboxWhenNotDelegated(server: GuiceJamesServer): Unit = { |
| val path = MailboxPath.inbox(ANDRE) |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(path) |
| val messageId: MessageId = server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(ANDRE.asString, path, AppendCommand.from( |
| ClassLoaderUtils.getSystemResourceAsSharedStream("eml/multipart_simple.eml"))) |
| .getMessageId |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "$ANDRE_ACCOUNT_ID", |
| | "ids": ["${messageId.serialize}"], |
| | "properties": ["messageId"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .inPath("methodResponses[0][1]") |
| .isEqualTo( |
| s"""{ |
| | "type": "accountNotFound" |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def shouldFailWhenReadFullLevelAndIdsSizeTooLarge(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| |
| val messagesList = List.range(0, 100) |
| .map(_ => { |
| server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| .serialize() |
| }).toArray |
| |
| val messageIdsJson: String = Json.stringify(Json.arr(messagesList)).replace("[[", "[").replace("]]", "]"); |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": $messageIdsJson, |
| | "properties": ["id", "size", "bodyStructure", "textBody", "htmlBody", "bodyValues"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "error", |
| | { |
| | "type": "requestTooLarge", |
| | "description": "Too many items in an email read at level FULL. Got 100 items instead of maximum 5." |
| | }, |
| | "c1"]] |
| |}""".stripMargin) |
| } |
| |
| @Test |
| def getEmailShouldSucceedWhenNotReadFullLevelAndExceedIdsSize(server: GuiceJamesServer): Unit = { |
| val message: Message = Message.Builder |
| .of |
| .setSubject("test") |
| .setBody("testmail", StandardCharsets.UTF_8) |
| .build |
| server.getProbe(classOf[MailboxProbeImpl]).createMailbox(MailboxPath.inbox(BOB)) |
| |
| val messagesList = List.range(0, 100) |
| .map(_ => { |
| server.getProbe(classOf[MailboxProbeImpl]) |
| .appendMessage(BOB.asString, MailboxPath.inbox(BOB), AppendCommand.from(message)) |
| .getMessageId |
| .serialize() |
| }).toArray |
| |
| val messageIdsJson: String = Json.stringify(Json.arr(messagesList)).replace("[[", "[").replace("]]", "]"); |
| |
| val request = |
| s"""{ |
| | "using": [ |
| | "urn:ietf:params:jmap:core", |
| | "urn:ietf:params:jmap:mail"], |
| | "methodCalls": [[ |
| | "Email/get", |
| | { |
| | "accountId": "29883977c13473ae7cb7678ef767cbfbaffc8a44a6e463d971d23a65c1dc4af6", |
| | "ids": $messageIdsJson, |
| | "properties": ["id", "size"] |
| | }, |
| | "c1"]] |
| |}""".stripMargin |
| val response = `given` |
| .header(ACCEPT.toString, ACCEPT_RFC8621_VERSION_HEADER) |
| .body(request) |
| .when |
| .post |
| .`then` |
| .statusCode(SC_OK) |
| .contentType(JSON) |
| .extract |
| .body |
| .asString |
| |
| assertThatJson(response) |
| .isEqualTo( |
| s"""{ |
| | "sessionState": "${SESSION_STATE.value}", |
| | "methodResponses": [[ |
| | "Email/get", "$${json-unit.ignore}", |
| | "c1"]] |
| |}""".stripMargin) |
| } |
| |
| private def waitForNextState(server: GuiceJamesServer, accountId: AccountId, initialState: State): State = { |
| val jmapGuiceProbe: JmapGuiceProbe = server.getProbe(classOf[JmapGuiceProbe]) |
| awaitAtMostTenSeconds.untilAsserted { |
| () => assertThat(jmapGuiceProbe.getLatestEmailState(accountId)).isNotEqualTo(initialState) |
| } |
| |
| jmapGuiceProbe.getLatestEmailState(accountId) |
| } |
| } |