Repository: james-project Updated Branches: refs/heads/master 0d416804a -> 4bf777b1e
MAILBOX-314 search: precise spec about search on email and fix ES impl Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/4bf777b1 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/4bf777b1 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/4bf777b1 Branch: refs/heads/master Commit: 4bf777b1e8640a0a0ee721fca2a814e42f60837a Parents: 0d41680 Author: Luc DUZAN <ldu...@linagora.com> Authored: Thu Oct 26 17:06:26 2017 +0700 Committer: Matthieu Baechler <matth...@apache.org> Committed: Mon Mar 26 15:27:46 2018 +0200 ---------------------------------------------------------------------- .../james/backends/es/IndexCreationFactory.java | 28 +++ .../james/backends/es/NodeMappingFactory.java | 2 + .../apache/james/mailbox/MailboxManager.java | 1 + .../elasticsearch/MailboxMappingFactory.java | 81 ++++++++- ...lasticSearchListeningMessageSearchIndex.java | 7 +- .../elasticsearch/query/CriterionConverter.java | 18 +- .../elasticsearch/query/SortConverter.java | 2 +- .../store/search/SimpleMessageSearchIndex.java | 3 +- .../search/AbstractMessageSearchIndexTest.java | 172 ++++++++++++++++++- mailbox/store/src/test/resources/eml/mail4.eml | 4 +- mailbox/store/src/test/resources/eml/mail5.eml | 13 ++ 11 files changed, 310 insertions(+), 21 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java ---------------------------------------------------------------------- diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java index 22c4943..7da3d8a 100644 --- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java +++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/IndexCreationFactory.java @@ -41,6 +41,9 @@ public class IndexCreationFactory { private static final int DEFAULT_NB_SHARDS = 1; private static final int DEFAULT_NB_REPLICA = 0; public static final String CASE_INSENSITIVE = "case_insensitive"; + public static final String KEEP_MAIL_AND_URL = "keep_mail_and_url"; + public static final String SNOWBALL_KEEP_MAIL_AND_URL = "snowball_keep_mail_and_token"; + public static final String ENGLISH_SNOWBALL = "english_snowball"; private IndexName indexName; private ArrayList<AliasName> aliases; @@ -137,6 +140,31 @@ public class IndexCreationFactory { .endArray() .endObject() .endObject() + .startObject("analyzer") + .startObject(KEEP_MAIL_AND_URL) + .field("tokenizer", "uax_url_email") + .startArray("filter") + .value("lowercase") + .value("stop") + .endArray() + .endObject() + .endObject() + .startObject("filter") + .startObject(ENGLISH_SNOWBALL) + .field("type", "snowball") + .field("language", "English") + .endObject() + .endObject() + .startObject("analyzer") + .startObject(SNOWBALL_KEEP_MAIL_AND_URL) + .field("tokenizer", "uax_url_email") + .startArray("filter") + .value("lowercase") + .value("stop") + .value(ENGLISH_SNOWBALL) + .endArray() + .endObject() + .endObject() .endObject() .endObject(); } http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/NodeMappingFactory.java ---------------------------------------------------------------------- diff --git a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/NodeMappingFactory.java b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/NodeMappingFactory.java index 3d16dc4..9c48526 100644 --- a/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/NodeMappingFactory.java +++ b/backends-common/elasticsearch/src/main/java/org/apache/james/backends/es/NodeMappingFactory.java @@ -36,7 +36,9 @@ public class NodeMappingFactory { public static final String NESTED = "nested"; public static final String FIELDS = "fields"; public static final String RAW = "raw"; + public static final String SPLIT_EMAIL = "splitEmail"; public static final String ANALYZER = "analyzer"; + public static final String SEARCH_ANALYZER = "search_analyzer"; public static final String SNOWBALL = "snowball"; public static final String IGNORE_ABOVE = "ignore_above"; http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java ---------------------------------------------------------------------- diff --git a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java index 67b122d..3374e4e 100644 --- a/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java +++ b/mailbox/api/src/main/java/org/apache/james/mailbox/MailboxManager.java @@ -91,6 +91,7 @@ public interface MailboxManager extends RequestAware, MailboxListenerSupport, Ri enum SearchCapabilities { MultimailboxSearch, + PartialEmailMatch, /** * The implementation supporting this capability should * provide an index on the fields: http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/MailboxMappingFactory.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/MailboxMappingFactory.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/MailboxMappingFactory.java index 25a1639..506b73c 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/MailboxMappingFactory.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/MailboxMappingFactory.java @@ -20,6 +20,8 @@ package org.apache.james.mailbox.elasticsearch; import static org.apache.james.backends.es.IndexCreationFactory.CASE_INSENSITIVE; +import static org.apache.james.backends.es.IndexCreationFactory.KEEP_MAIL_AND_URL; +import static org.apache.james.backends.es.IndexCreationFactory.SNOWBALL_KEEP_MAIL_AND_URL; import static org.apache.james.backends.es.NodeMappingFactory.ANALYZER; import static org.apache.james.backends.es.NodeMappingFactory.BOOLEAN; import static org.apache.james.backends.es.NodeMappingFactory.FIELDS; @@ -31,7 +33,9 @@ import static org.apache.james.backends.es.NodeMappingFactory.NESTED; import static org.apache.james.backends.es.NodeMappingFactory.NOT_ANALYZED; import static org.apache.james.backends.es.NodeMappingFactory.PROPERTIES; import static org.apache.james.backends.es.NodeMappingFactory.RAW; +import static org.apache.james.backends.es.NodeMappingFactory.SEARCH_ANALYZER; import static org.apache.james.backends.es.NodeMappingFactory.SNOWBALL; +import static org.apache.james.backends.es.NodeMappingFactory.SPLIT_EMAIL; import static org.apache.james.backends.es.NodeMappingFactory.STRING; import static org.apache.james.backends.es.NodeMappingFactory.TYPE; import static org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants.BCC; @@ -74,6 +78,7 @@ import com.google.common.base.Throwables; public class MailboxMappingFactory { private static final int MAXIMUM_TERM_LENGTH = 4096; + private static final String STANDARD = "standard"; public static XContentBuilder getMappingContent() { try { @@ -154,6 +159,7 @@ public class MailboxMappingFactory { .startObject(PROPERTIES) .startObject(EMailer.NAME) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) .startObject(FIELDS) .startObject(RAW) .field(TYPE, STRING) @@ -163,13 +169,21 @@ public class MailboxMappingFactory { .endObject() .startObject(EMailer.ADDRESS) .field(TYPE, STRING) - .field(INDEX, NOT_ANALYZED) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .endObject() .endObject() .startObject(SUBJECT) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) .startObject(FIELDS) .startObject(RAW) .field(TYPE, STRING) @@ -183,6 +197,7 @@ public class MailboxMappingFactory { .startObject(PROPERTIES) .startObject(EMailer.NAME) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) .startObject(FIELDS) .startObject(RAW) .field(TYPE, STRING) @@ -192,7 +207,14 @@ public class MailboxMappingFactory { .endObject() .startObject(EMailer.ADDRESS) .field(TYPE, STRING) - .field(INDEX, NOT_ANALYZED) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .endObject() .endObject() @@ -202,10 +224,24 @@ public class MailboxMappingFactory { .startObject(PROPERTIES) .startObject(EMailer.NAME) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .startObject(EMailer.ADDRESS) .field(TYPE, STRING) - .field(INDEX, NOT_ANALYZED) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .endObject() .endObject() @@ -215,10 +251,24 @@ public class MailboxMappingFactory { .startObject(PROPERTIES) .startObject(EMailer.NAME) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .startObject(EMailer.ADDRESS) .field(TYPE, STRING) - .field(INDEX, NOT_ANALYZED) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .endObject() .endObject() @@ -246,13 +296,20 @@ public class MailboxMappingFactory { .endObject() .startObject(Property.VALUE) .field(TYPE, STRING) + .field(INDEX, NOT_ANALYZED) .endObject() .endObject() .endObject() .startObject(TEXT_BODY) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) .startObject(FIELDS) + .startObject(SPLIT_EMAIL) + .field(TYPE, STRING) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .endObject() .startObject(RAW) .field(TYPE, STRING) .field(ANALYZER, CASE_INSENSITIVE) @@ -263,7 +320,13 @@ public class MailboxMappingFactory { .startObject(HTML_BODY) .field(TYPE, STRING) + .field(ANALYZER, KEEP_MAIL_AND_URL) .startObject(FIELDS) + .startObject(SPLIT_EMAIL) + .field(TYPE, STRING) + .field(ANALYZER, STANDARD) + .field(SEARCH_ANALYZER, KEEP_MAIL_AND_URL) + .endObject() .startObject(RAW) .field(TYPE, STRING) .field(ANALYZER, CASE_INSENSITIVE) @@ -278,8 +341,15 @@ public class MailboxMappingFactory { .startObject(TEXT) .field(TYPE, STRING) - .field(ANALYZER, SNOWBALL) + .field(ANALYZER, SNOWBALL_KEEP_MAIL_AND_URL) .field(IGNORE_ABOVE, MAXIMUM_TERM_LENGTH) + .startObject(FIELDS) + .startObject(SPLIT_EMAIL) + .field(TYPE, STRING) + .field(ANALYZER, SNOWBALL) + .field(SEARCH_ANALYZER, SNOWBALL_KEEP_MAIL_AND_URL) + .endObject() + .endObject() .endObject() .endObject() .endObject() @@ -288,5 +358,4 @@ public class MailboxMappingFactory { throw Throwables.propagate(e); } } - } http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java index fb378ee..ed47b44 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/events/ElasticSearchListeningMessageSearchIndex.java @@ -79,7 +79,12 @@ public class ElasticSearchListeningMessageSearchIndex extends ListeningMessageSe @Override public EnumSet<SearchCapabilities> getSupportedCapabilities(EnumSet<MessageCapabilities> messageCapabilities) { - return EnumSet.of(SearchCapabilities.MultimailboxSearch, SearchCapabilities.Text, SearchCapabilities.FullText, SearchCapabilities.Attachment); + return EnumSet.of( + SearchCapabilities.MultimailboxSearch, + SearchCapabilities.Text, + SearchCapabilities.FullText, + SearchCapabilities.Attachment, + SearchCapabilities.PartialEmailMatch); } @Override http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java index dd61fb9..ab1cf0d 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/CriterionConverter.java @@ -19,6 +19,8 @@ package org.apache.james.mailbox.elasticsearch.query; +import static org.apache.james.backends.es.NodeMappingFactory.RAW; +import static org.apache.james.backends.es.NodeMappingFactory.SPLIT_EMAIL; import static org.elasticsearch.index.query.QueryBuilders.boolQuery; import static org.elasticsearch.index.query.QueryBuilders.existsQuery; import static org.elasticsearch.index.query.QueryBuilders.matchAllQuery; @@ -136,13 +138,24 @@ public class CriterionConverter { case BODY: return boolQuery() .should(matchQuery(JsonMessageConstants.TEXT_BODY, textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.TEXT_BODY + "." + SPLIT_EMAIL, + textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.HTML_BODY + "." + SPLIT_EMAIL, + textCriterion.getOperator().getValue())) .should(matchQuery(JsonMessageConstants.HTML_BODY, textCriterion.getOperator().getValue())); case TEXT: return boolQuery() - .should(matchQuery(JsonMessageConstants.TEXT, textCriterion.getOperator().getValue())); + .should(matchQuery(JsonMessageConstants.TEXT, textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.TEXT + "." + SPLIT_EMAIL, + textCriterion.getOperator().getValue())); case FULL: return boolQuery() .should(matchQuery(JsonMessageConstants.TEXT_BODY, textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.TEXT_BODY + "." + SPLIT_EMAIL, + textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.HTML_BODY + "." + SPLIT_EMAIL, + textCriterion.getOperator().getValue())) + .should(matchQuery(JsonMessageConstants.HTML_BODY, textCriterion.getOperator().getValue())) .should(matchQuery(JsonMessageConstants.HTML_BODY, textCriterion.getOperator().getValue())) .should(matchQuery(JsonMessageConstants.ATTACHMENTS + "." + JsonMessageConstants.Attachment.TEXT_CONTENT, textCriterion.getOperator().getValue())); @@ -255,7 +268,8 @@ public class CriterionConverter { private QueryBuilder manageAddressFields(String headerName, String value) { return nestedQuery(getFieldNameFromHeaderName(headerName), boolQuery() .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.NAME, value)) - .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS, value))); + .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS, value)) + .should(matchQuery(getFieldNameFromHeaderName(headerName) + "." + JsonMessageConstants.EMailer.ADDRESS + "." + RAW, value))); } private String getFieldNameFromHeaderName(String headerName) { http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java index ebcc557..a6bad82 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/query/SortConverter.java @@ -51,7 +51,7 @@ public class SortConverter { return SortBuilders.fieldSort(JsonMessageConstants.TO + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS) .setNestedPath(JsonMessageConstants.TO); case BaseSubject : - return SortBuilders.fieldSort(JsonMessageConstants.SUBJECT); + return SortBuilders.fieldSort(JsonMessageConstants.SUBJECT + PATH_SEPARATOR + NodeMappingFactory.RAW); case Size : return SortBuilders.fieldSort(JsonMessageConstants.SIZE); case SentDate : http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java index 2b15b6f..d9b4c1d 100644 --- a/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java +++ b/mailbox/store/src/main/java/org/apache/james/mailbox/store/search/SimpleMessageSearchIndex.java @@ -81,7 +81,8 @@ public class SimpleMessageSearchIndex implements MessageSearchIndex { if (messageCapabilities.contains(MessageCapabilities.Attachment)) { return EnumSet.of(SearchCapabilities.MultimailboxSearch, SearchCapabilities.Text, - SearchCapabilities.Attachment); + SearchCapabilities.Attachment, + SearchCapabilities.PartialEmailMatch); } return EnumSet.of(SearchCapabilities.MultimailboxSearch, SearchCapabilities.Text); http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java index eda993e..f4e891e 100644 --- a/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java +++ b/mailbox/store/src/test/java/org/apache/james/mailbox/store/search/AbstractMessageSearchIndexTest.java @@ -95,6 +95,7 @@ public abstract class AbstractMessageSearchIndexTest { private StoreMessageManager myFolderMessageManager; private MailboxPath inboxPath; private MailboxPath otherInboxPath; + private StoreMessageManager inboxMessageManager; @Before @@ -110,7 +111,7 @@ public abstract class AbstractMessageSearchIndexTest { storeMailboxManager.createMailbox(inboxPath, session); storeMailboxManager.createMailbox(otherInboxPath, otherSession); - StoreMessageManager inboxMessageManager = (StoreMessageManager) storeMailboxManager.getMailbox(inboxPath, session); + inboxMessageManager = (StoreMessageManager) storeMailboxManager.getMailbox(inboxPath, session); StoreMessageManager otherInboxMessageManager = (StoreMessageManager) storeMailboxManager.getMailbox(otherInboxPath, otherSession); MailboxPath myFolderPath = MailboxPath.forUser(USERNAME, "MyFolder"); @@ -421,6 +422,34 @@ public abstract class AbstractMessageSearchIndexTest { } @Test + public void searchShouldBeExactOnEmailAddresses() throws MailboxException { + Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); + + ComposedMessageId m11 = inboxMessageManager.appendMessage( + ClassLoader.getSystemResourceAsStream("eml/mail5.eml"), + new Date(1396389600000L), + session, + RECENT, + new Flags(Flags.Flag.FLAGGED)); + + String emailToSearch = "luc.du...@james.apache.org"; + + await(); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.or(ImmutableList.of( + SearchQuery.address(AddressType.From, emailToSearch), + SearchQuery.address(AddressType.To, emailToSearch), + SearchQuery.address(AddressType.Cc, emailToSearch), + SearchQuery.address(AddressType.Bcc, emailToSearch), + SearchQuery.headerContains("Subject", emailToSearch), + SearchQuery.attachmentContains(emailToSearch), + SearchQuery.bodyContains(emailToSearch)))); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m11.getUid()); + } + + @Test public void hasNoAttachmenShouldOnlyReturnMessageThatHasNoAttachmentWhichAreNotInline() throws MailboxException { SearchQuery searchQuery = new SearchQuery(SearchQuery.hasNoAttachment()); @@ -767,6 +796,30 @@ public abstract class AbstractMessageSearchIndexTest { } @Test + public void addressShouldReturnUidHavingRightExpeditorWhenFromIsSpecifiedWithOnlyUserPartOfEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.From, "murari")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m8.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightExpeditorWhenFromIsSpecifiedWithDomainPartOfEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.From, "gmail.com")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m8.getUid()); + } + + @Test public void addressShouldReturnUidHavingRightRecipientWhenToIsSpecified() throws Exception { SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.To, "r...@listes.minet.net")); @@ -775,14 +828,91 @@ public abstract class AbstractMessageSearchIndexTest { } @Test + public void addressShouldReturnUidHavingRightRecipientWhenToIsSpecifiedWithOnlyEmailUserPart() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.To, "root")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m1.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightRecipientWhenToIsSpecifiedWithOnlyDomainPartSpecified() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.To, "listes.minet.net")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m1.getUid()); + } + + @Test public void addressShouldReturnUidHavingRightRecipientWhenCcIsSpecified() throws Exception { - SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Cc, "a...@any.com")); + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Cc, "mon...@any.com")); + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m5.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightRecipientWhenCcIsSpecifiedWithOnlyUserPartOfTheEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Cc, "monkey")); + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m5.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightRecipientWhenCcIsSpecifiedWithOnlyDomainPartOfTheEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Cc, "any.com")); + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m5.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightRecipientWhenBccIsSpecifiedWithOnlyUserPartOfTheEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Bcc, "monkey")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsOnly(m5.getUid()); + } + + @Test + public void addressShouldReturnUidHavingRightRecipientWhenBccIsSpecifiedWithOnlyDomainPartOfTheEmail() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Bcc, "any.com")); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) .containsOnly(m5.getUid()); } @Test public void addressShouldReturnUidHavingRightRecipientWhenBccIsSpecified() throws Exception { + Assume.assumeTrue(storeMailboxManager + .getSupportedSearchCapabilities() + .contains(MailboxManager.SearchCapabilities.PartialEmailMatch)); + SearchQuery searchQuery = new SearchQuery(SearchQuery.address(AddressType.Bcc, "n...@no.com")); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) @@ -917,7 +1047,7 @@ public abstract class AbstractMessageSearchIndexTest { // 2 : No cc // 3 : Cc : a...@abc.org // 4 : z...@bcd.org - // 5 : a...@any.com + // 5 : mon...@any.com } @Test @@ -927,7 +1057,7 @@ public abstract class AbstractMessageSearchIndexTest { searchQuery.setSorts(ImmutableList.of(new Sort(SortClause.MailboxFrom))); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) - .containsExactly(m3.getUid(), m2.getUid(), m4.getUid(), m5.getUid()); + .containsExactly(m2.getUid(), m3.getUid(), m4.getUid(), m5.getUid()); // 2 : ji...@apache.org // 3 : ji...@apache.org // 4 : j...@apache.org @@ -1047,9 +1177,17 @@ public abstract class AbstractMessageSearchIndexTest { } @Test - public void searchWithTextShouldReturnMailsWhenToMatches() throws Exception { + public void searchWithTextShouldReturnMailsWhenMatches() throws Exception { + Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("r...@listes.minet.net")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(m1.getUid()); + } + @Test + public void searchWithTextShouldReturnMailsWhenToIsNotAnExactMatches() throws Exception { Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); - SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("listes.minet.net")); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("root")); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) .containsExactly(m1.getUid()); @@ -1058,16 +1196,34 @@ public abstract class AbstractMessageSearchIndexTest { @Test public void searchWithTextShouldReturnMailsWhenCcMatches() throws Exception { Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); - SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("abc.org")); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("a...@abc.org")); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) .containsExactly(m3.getUid()); } @Test + public void searchWithTextShouldReturnMailsWhenCcIsNotAExactMatch() throws Exception { + Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("monkey")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(m5.getUid()); + } + + @Test public void searchWithTextShouldReturnMailsWhenBccMatches() throws Exception { Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); - SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("any.com")); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("mon...@any.com")); + + assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(m5.getUid()); + } + + @Test + public void searchWithTextShouldReturnMailsWhenBccIsNotAExactMatch() throws Exception { + Assume.assumeTrue(storeMailboxManager.getSupportedSearchCapabilities().contains(MailboxManager.SearchCapabilities.Text)); + SearchQuery searchQuery = new SearchQuery(SearchQuery.textContains("monkey")); assertThat(messageSearchIndex.search(session, mailbox, searchQuery)) .containsExactly(m5.getUid()); http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/store/src/test/resources/eml/mail4.eml ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/resources/eml/mail4.eml b/mailbox/store/src/test/resources/eml/mail4.eml index 3bf6dde..ad2a5f6 100644 --- a/mailbox/store/src/test/resources/eml/mail4.eml +++ b/mailbox/store/src/test/resources/eml/mail4.eml @@ -37,8 +37,8 @@ Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) Date: Fri, 15 May 2015 06:35:59 +0000 (UTC) From: "Eric Charles (JIRA)" <mailet-...@james.apache.org> To: "zzz" <mailet-...@james.apache.org> -Cc: a...@any.com -Bcc: a...@any.com +Cc: mon...@any.com +Bcc: mon...@any.com Message-ID: <jira.12825882.1430301328000.124152.1431671759...@atlassian.jira> In-Reply-To: <jira.12825882.1430301328...@atlassian.jira> References: <jira.12825882.1430301328...@atlassian.jira> <JIRA.12825882.1430301328925@arcas> http://git-wip-us.apache.org/repos/asf/james-project/blob/4bf777b1/mailbox/store/src/test/resources/eml/mail5.eml ---------------------------------------------------------------------- diff --git a/mailbox/store/src/test/resources/eml/mail5.eml b/mailbox/store/src/test/resources/eml/mail5.eml new file mode 100644 index 0000000..0f785c5 --- /dev/null +++ b/mailbox/store/src/test/resources/eml/mail5.eml @@ -0,0 +1,13 @@ +Date: Fri, 15 May 2015 06:35:59 +0000 (UTC) +From: "Luc DUZAN (JIRA)" <luc.du...@james.apache.org> +To: "zzz" <mailet-...@james.apache.org> +Cc: a...@any.com +Bcc: a...@any.com +Message-ID: <jira.1234567...@atlassian.jira> +Subject: This is a mail about mail! +MIME-Version: 1.0 +Content-Type: text/plain; charset=utf-8 +Content-Transfer-Encoding: 7bit + +This is the body of the mail + --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org