MAILBOX-266 Sorts should work
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/7f02ab71 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/7f02ab71 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/7f02ab71 Branch: refs/heads/master Commit: 7f02ab719453f704fbf39f67a6784b76dc2a2ae9 Parents: f9717d2 Author: Benoit Tellier <btell...@linagora.com> Authored: Mon Mar 28 16:27:07 2016 +0700 Committer: Benoit Tellier <btell...@linagora.com> Committed: Wed Apr 6 16:18:45 2016 +0700 ---------------------------------------------------------------------- .../elasticsearch/IndexCreationFactory.java | 28 +++- .../elasticsearch/NodeMappingFactory.java | 25 ++++ .../elasticsearch/query/SortConverter.java | 36 ++++-- .../ElasticSearchIntegrationTest.java | 127 ++++++++++++++++++- .../src/test/resources/documents/mail1.eml | 4 +- .../src/test/resources/documents/mail2.eml | 5 +- .../src/test/resources/documents/mail3.eml | 5 +- .../src/test/resources/documents/mail4.eml | 2 +- 8 files changed, 202 insertions(+), 30 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/IndexCreationFactory.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/IndexCreationFactory.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/IndexCreationFactory.java index 71a6c11..6cf0933 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/IndexCreationFactory.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/IndexCreationFactory.java @@ -19,10 +19,12 @@ package org.apache.james.mailbox.elasticsearch; +import static org.elasticsearch.common.xcontent.XContentFactory.jsonBuilder; + import java.io.IOException; import org.elasticsearch.client.Client; -import org.elasticsearch.common.settings.Settings; +import org.elasticsearch.common.xcontent.XContentBuilder; import org.elasticsearch.indices.IndexAlreadyExistsException; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -32,6 +34,7 @@ public class IndexCreationFactory { private static final Logger LOGGER = LoggerFactory.getLogger(IndexCreationFactory.class); 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 ClientProvider createIndex(ClientProvider clientProvider, int nbShards, int nbReplica) { try { @@ -46,7 +49,7 @@ public class IndexCreationFactory { return createIndex(clientProvider, DEFAULT_NB_SHARDS, DEFAULT_NB_REPLICA); } - private static ClientProvider createIndex(ClientProvider clientProvider, Settings settings) { + private static ClientProvider createIndex(ClientProvider clientProvider, XContentBuilder settings) { try { try (Client client = clientProvider.get()) { client.admin() @@ -62,11 +65,22 @@ public class IndexCreationFactory { return clientProvider; } - private static Settings generateSetting(int nbShards, int nbReplica) throws IOException { - return Settings.builder() - .put("number_of_shards", nbShards) - .put("number_of_replicas", nbReplica) - .build(); + private static XContentBuilder generateSetting(int nbShards, int nbReplica) throws IOException { + return jsonBuilder() + .startObject() + .field("number_of_shards", nbShards) + .field("number_of_replicas", nbReplica) + .startObject("analysis") + .startObject("analyzer") + .startObject(CASE_INSENSITIVE) + .field("tokenizer", "keyword") + .startArray("filter") + .value("lowercase") + .endArray() + .endObject() + .endObject() + .endObject() + .endObject(); } } http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeMappingFactory.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeMappingFactory.java b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeMappingFactory.java index 758f3c2..85b5b05 100644 --- a/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeMappingFactory.java +++ b/mailbox/elasticsearch/src/main/java/org/apache/james/mailbox/elasticsearch/NodeMappingFactory.java @@ -41,6 +41,9 @@ public class NodeMappingFactory { public static final String DATE = "date"; public static final String FORMAT = "format"; public static final String NESTED = "nested"; + public static final String FIELDS = "fields"; + public static final String RAW = "raw"; + public static final String ANALYZER = "analyzer"; public static ClientProvider applyMapping(ClientProvider clientProvider) { return applyMapping(clientProvider, getMappingContent()); @@ -118,6 +121,12 @@ public class NodeMappingFactory { .startObject(PROPERTIES) .startObject(JsonMessageConstants.EMailer.NAME) .field(TYPE, STRING) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, IndexCreationFactory.CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .startObject(JsonMessageConstants.EMailer.ADDRESS) .field(TYPE, STRING) @@ -126,11 +135,27 @@ public class NodeMappingFactory { .endObject() .endObject() + .startObject(JsonMessageConstants.SUBJECT) + .field(TYPE, STRING) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, IndexCreationFactory.CASE_INSENSITIVE) + .endObject() + .endObject() + .endObject() + .startObject(JsonMessageConstants.TO) .field(TYPE, NESTED) .startObject(PROPERTIES) .startObject(JsonMessageConstants.EMailer.NAME) .field(TYPE, STRING) + .startObject(FIELDS) + .startObject(RAW) + .field(TYPE, STRING) + .field(ANALYZER, IndexCreationFactory.CASE_INSENSITIVE) + .endObject() + .endObject() .endObject() .startObject(JsonMessageConstants.EMailer.ADDRESS) .field(TYPE, STRING) http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/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 7ac74ea..5644239 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 @@ -19,6 +19,7 @@ package org.apache.james.mailbox.elasticsearch.query; +import org.apache.james.mailbox.elasticsearch.NodeMappingFactory; import org.apache.james.mailbox.elasticsearch.json.JsonMessageConstants; import org.apache.james.mailbox.model.SearchQuery; import org.elasticsearch.search.sort.FieldSortBuilder; @@ -27,33 +28,42 @@ import org.elasticsearch.search.sort.SortOrder; public class SortConverter { + private static final String MIN = "min"; + private static final String PATH_SEPARATOR = "."; + public static FieldSortBuilder convertSort(SearchQuery.Sort sort) { - return SortBuilders.fieldSort(getFieldFromClause(sort.getSortClause())) - .order(getOrder(sort)); + return getSortClause(sort.getSortClause()) + .order(getOrder(sort)) + .sortMode(MIN); } - private static String getFieldFromClause(SearchQuery.Sort.SortClause clause) { + private static FieldSortBuilder getSortClause(SearchQuery.Sort.SortClause clause) { switch (clause) { case Arrival : - return JsonMessageConstants.DATE; + return SortBuilders.fieldSort(JsonMessageConstants.DATE); case MailboxCc : - return JsonMessageConstants.CC; + return SortBuilders.fieldSort(JsonMessageConstants.CC + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS) + .setNestedPath(JsonMessageConstants.CC); case MailboxFrom : - return JsonMessageConstants.FROM + "." + JsonMessageConstants.EMailer.ADDRESS; + return SortBuilders.fieldSort(JsonMessageConstants.FROM + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS) + .setNestedPath(JsonMessageConstants.FROM); case MailboxTo : - return JsonMessageConstants.TO + "." + JsonMessageConstants.EMailer.ADDRESS; + return SortBuilders.fieldSort(JsonMessageConstants.TO + PATH_SEPARATOR + JsonMessageConstants.EMailer.ADDRESS) + .setNestedPath(JsonMessageConstants.TO); case BaseSubject : - return JsonMessageConstants.SUBJECT; + return SortBuilders.fieldSort(JsonMessageConstants.SUBJECT); case Size : - return JsonMessageConstants.SIZE; + return SortBuilders.fieldSort(JsonMessageConstants.SIZE); case SentDate : - return JsonMessageConstants.DATE; + return SortBuilders.fieldSort(JsonMessageConstants.SENT_DATE); case Uid : - return JsonMessageConstants.ID; + return SortBuilders.fieldSort(JsonMessageConstants.ID); case DisplayFrom: - return JsonMessageConstants.FROM + "." + JsonMessageConstants.EMailer.NAME; + return SortBuilders.fieldSort(JsonMessageConstants.FROM + PATH_SEPARATOR + JsonMessageConstants.EMailer.NAME + PATH_SEPARATOR + NodeMappingFactory.RAW) + .setNestedPath(JsonMessageConstants.FROM); case DisplayTo: - return JsonMessageConstants.TO + "." + JsonMessageConstants.EMailer.NAME; + return SortBuilders.fieldSort(JsonMessageConstants.TO + PATH_SEPARATOR + JsonMessageConstants.EMailer.NAME + PATH_SEPARATOR + NodeMappingFactory.RAW) + .setNestedPath(JsonMessageConstants.TO); default: throw new RuntimeException("Sort is not implemented"); } http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java index 832e4a6..e2ddc84 100644 --- a/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java +++ b/mailbox/elasticsearch/src/test/java/org/apache/james/mailbox/elasticsearch/ElasticSearchIntegrationTest.java @@ -50,7 +50,6 @@ import org.apache.james.mailbox.store.StoreMailboxManager; import org.apache.james.mailbox.store.StoreMessageManager; import org.apache.james.mailbox.store.mail.model.Mailbox; import org.junit.Before; -import org.junit.Ignore; import org.junit.Rule; import org.junit.Test; import org.junit.rules.RuleChain; @@ -63,8 +62,8 @@ import com.google.common.collect.Lists; public class ElasticSearchIntegrationTest { private static final Logger LOGGER = LoggerFactory.getLogger(ElasticSearchIntegrationTest.class); - public static final int BATCH_SIZE = 1; - public static final int SEARCH_SIZE = 1; + private static final int BATCH_SIZE = 1; + private static final int SEARCH_SIZE = 1; private TemporaryFolder temporaryFolder = new TemporaryFolder(); private EmbeddedElasticSearch embeddedElasticSearch= new EmbeddedElasticSearch(temporaryFolder); @@ -578,4 +577,126 @@ public class ElasticSearchIntegrationTest { .containsOnly(1L, 6L); } + @Test + public void sortOnCcShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.MailboxCc))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(3L, 5L, 4L, 2L); + // 2 : No cc + // 3 : Cc : a...@abc.org + // 4 : z...@bcd.org + // 5 : a...@any.com + } + + @Test + public void sortOnFromShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.MailboxFrom))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(3L, 2L, 4L, 5L); + // 2 : ji...@apache.org + // 3 : ji...@apache.org + // 4 : j...@apache.org + // 5 : mailet-...@james.apache.org + } + + @Test + public void sortOnToShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.MailboxTo))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(5L, 2L, 3L, 4L); + // 2 : server-dev@james.apache.org + // 3 : server-dev@james.apache.org + // 4 : server-dev@james.apache.org + // 5 : mailet-...@james.apache.org + } + + @Test + public void sortOnSubjectShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.BaseSubject))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(4L, 3L, 2L, 5L); + // 2 : [jira] [Created] (MAILBOX-234) Convert Message into JSON + // 3 : [jira] [Closed] (MAILBOX-217) We should index attachment in elastic search + // 4 : [jira] [Closed] (MAILBOX-11) MailboxQuery ignore namespace + // 5 : [jira] [Resolved] (MAILET-94) James Mailet should use latest version of other James subprojects + } + + @Test + public void sortOnSizeShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Size))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(2L, 3L, 5L, 4L); + // 2 : 3210 o + // 3 : 3647 o + // 4 : 4360 o + // 5 : 3653 o + } + + @Test + public void sortOnDisplayFromShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.DisplayFrom))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(4L, 3L, 5L, 2L); + // 2 : Tellier Benoit (JIRA) + // 3 : efij + // 4 : abcd + // 5 : Eric Charles (JIRA) + } + + @Test + public void sortOnDisplayToShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.DisplayTo))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(3L, 2L, 4L, 5L); + // 2 : abc + // 3 : aaa + // 4 : server + // 5 : zzz + } + + @Test + public void sortOnSentDateShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.SentDate))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(5L, 4L, 2L, 3L); + // 2 : 4 Jun 2015 09:23:37 + // 3 : 4 Jun 2015 09:27:37 + // 4 : 2 Jun 2015 08:16:19 + // 5 : 15 May 2015 06:35:59 + } + + @Test + public void sortOnIdShouldWork() throws Exception { + SearchQuery searchQuery = new SearchQuery(); + SearchQuery.NumericRange[] numericRanges = {new SearchQuery.NumericRange(2L, 5L)}; + searchQuery.andCriteria(SearchQuery.uid(numericRanges)); + searchQuery.setSorts(Lists.newArrayList(new SearchQuery.Sort(SearchQuery.Sort.SortClause.Uid))); + assertThat(elasticSearchListeningMessageSearchIndex.search(session, mailbox, searchQuery)) + .containsExactly(2L, 3L, 4L, 5L); + } + } http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/test/resources/documents/mail1.eml ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/resources/documents/mail1.eml b/mailbox/elasticsearch/src/test/resources/documents/mail1.eml index 3d596f7..3850a62 100644 --- a/mailbox/elasticsearch/src/test/resources/documents/mail1.eml +++ b/mailbox/elasticsearch/src/test/resources/documents/mail1.eml @@ -33,8 +33,8 @@ Received: (qmail 37236 invoked by uid 99); 4 Jun 2015 09:23:38 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Jun 2015 09:23:38 +0000 Date: Thu, 4 Jun 2015 09:23:37 +0000 (UTC) -From: "Tellier Benoit (JIRA)" <j...@apache.org> -To: server-dev@james.apache.org +From: "Tellier Benoit (JIRA)" <ji...@apache.org> +To: "abc" <server-dev@james.apache.org> Message-ID: <jira.12835341.1433409792000.9340.1433409817...@atlassian.jira> In-Reply-To: <jira.12835341.1433409792...@atlassian.jira> References: <jira.12835341.1433409792...@atlassian.jira> <JIRA.12835341.1433409792972@arcas> http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/test/resources/documents/mail2.eml ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/resources/documents/mail2.eml b/mailbox/elasticsearch/src/test/resources/documents/mail2.eml index 5f361de..9c2c413 100644 --- a/mailbox/elasticsearch/src/test/resources/documents/mail2.eml +++ b/mailbox/elasticsearch/src/test/resources/documents/mail2.eml @@ -33,8 +33,9 @@ Received: (qmail 43130 invoked by uid 99); 4 Jun 2015 09:27:38 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Thu, 04 Jun 2015 09:27:38 +0000 Date: Thu, 4 Jun 2015 09:27:37 +0000 (UTC) -From: "Tellier Benoit (JIRA)" <j...@apache.org> -To: server-dev@james.apache.org +From: "efij" <ji...@apache.org> +To: "aaa" <server-dev@james.apache.org> +Cc: a...@abc.org Message-ID: <jira.12781874.1426269127000.9353.1433410057...@atlassian.jira> In-Reply-To: <jira.12781874.1426269127...@atlassian.jira> References: <jira.12781874.1426269127...@atlassian.jira> <JIRA.12781874.1426269127444@arcas> http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/test/resources/documents/mail3.eml ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/resources/documents/mail3.eml b/mailbox/elasticsearch/src/test/resources/documents/mail3.eml index 1e7f788..e9cc325 100644 --- a/mailbox/elasticsearch/src/test/resources/documents/mail3.eml +++ b/mailbox/elasticsearch/src/test/resources/documents/mail3.eml @@ -35,8 +35,9 @@ Received: (qmail 1132 invoked by uid 99); 2 Jun 2015 08:16:20 -0000 Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Tue, 02 Jun 2015 08:16:20 +0000 Date: Tue, 2 Jun 2015 08:16:19 +0000 (UTC) -From: "Eric Charles (JIRA)" <j...@apache.org> -To: server-dev@james.apache.org +From: "abcd" <j...@apache.org> +Cc: z...@bcd.org +To: "server" <server-dev@james.apache.org> Message-ID: <jira.12473940.1284322083000.91735.1433232979...@atlassian.jira> In-Reply-To: <jira.12473940.1284322083...@atlassian.jira> References: <jira.12473940.1284322083...@atlassian.jira> <JIRA.12473940.1284322083687@arcas> http://git-wip-us.apache.org/repos/asf/james-project/blob/7f02ab71/mailbox/elasticsearch/src/test/resources/documents/mail4.eml ---------------------------------------------------------------------- diff --git a/mailbox/elasticsearch/src/test/resources/documents/mail4.eml b/mailbox/elasticsearch/src/test/resources/documents/mail4.eml index 584b24c..37ecba1 100644 --- a/mailbox/elasticsearch/src/test/resources/documents/mail4.eml +++ b/mailbox/elasticsearch/src/test/resources/documents/mail4.eml @@ -36,7 +36,7 @@ Received: from arcas.apache.org (HELO arcas.apache.org) (140.211.11.28) by apache.org (qpsmtpd/0.29) with ESMTP; Fri, 15 May 2015 06:36:00 +0000 Date: Fri, 15 May 2015 06:35:59 +0000 (UTC) From: "Eric Charles (JIRA)" <mailet-...@james.apache.org> -To: mailet-...@james.apache.org +To: "zzz" <mailet-...@james.apache.org> Cc: a...@any.com Bcc: a...@any.com Message-ID: <jira.12825882.1430301328000.124152.1431671759...@atlassian.jira> --------------------------------------------------------------------- To unsubscribe, e-mail: server-dev-unsubscr...@james.apache.org For additional commands, e-mail: server-dev-h...@james.apache.org