Author: matthieu
Date: Tue Nov 3 16:49:53 2015
New Revision: 1712337
URL: http://svn.apache.org/viewvc?rev=1712337&view=rev
Log:
JAMES-1626 Implement an InMemory MailRepository
Added:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
james/project/trunk/server/container/cassandra-guice/src/test/resources/fakemailrepositorystore.xml
james/project/trunk/server/container/cassandra-guice/src/test/resources/mailrepositorystore.xml
Modified:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
Modified:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java?rev=1712337&r1=1712336&r2=1712337&view=diff
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
(original)
+++
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/CassandraJamesServerMain.java
Tue Nov 3 16:49:53 2015
@@ -35,6 +35,7 @@ import org.apache.james.modules.server.C
import org.apache.james.modules.server.DNSServiceModule;
import org.apache.james.modules.server.FileSystemModule;
import org.apache.james.modules.server.JMXServerModule;
+import org.apache.james.modules.server.MailStoreRepositoryModule;
import org.apache.james.modules.server.QuotaModule;
import com.google.inject.Module;
@@ -58,7 +59,8 @@ public class CassandraJamesServerMain {
new LMTPServerModule(),
new ActiveMQQueueModule(),
new QuotaModule(),
- new FileSystemModule());
+ new FileSystemModule(),
+ new MailStoreRepositoryModule());
public static void main(String[] args) throws Exception {
CassandraJamesServer server = new CassandraJamesServer(Modules.combine(
Added:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/modules/server/MailStoreRepositoryModule.java
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,87 @@
+/****************************************************************
+ * 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.modules.server;
+
+import com.google.inject.AbstractModule;
+import com.google.inject.Inject;
+import com.google.inject.Singleton;
+import com.google.inject.multibindings.Multibinder;
+import org.apache.james.filesystem.api.FileSystem;
+import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.file.FileMailRepository;
+import org.apache.james.utils.ClassPathConfigurationProvider;
+import org.apache.james.utils.ConfigurationPerformer;
+import org.apache.james.utils.InMemoryMailRepositoryStore;
+import org.apache.james.utils.MailRepositoryProvider;
+
+public class MailStoreRepositoryModule extends AbstractModule {
+
+ @Override
+ protected void configure() {
+ bind(MailRepositoryStore.class).to(InMemoryMailRepositoryStore.class);
+ Multibinder<MailRepositoryProvider> multibinder =
Multibinder.newSetBinder(binder(), MailRepositoryProvider.class);
+ multibinder.addBinding().to(FileMailRepositoryProvider.class);
+ Multibinder.newSetBinder(binder(),
ConfigurationPerformer.class).addBinding().to(MailRepositoryStoreModuleConfigurationPerformer.class);
+ }
+
+ public static class FileMailRepositoryProvider implements
MailRepositoryProvider {
+
+ private final FileSystem fileSystem;
+
+ @Inject
+ public FileMailRepositoryProvider(FileSystem fileSystem) {
+ this.fileSystem = fileSystem;
+ }
+
+ @Override
+ public String canonicalName() {
+ return FileMailRepository.class.getCanonicalName();
+ }
+
+ @Override
+ public MailRepository get() {
+ FileMailRepository fileMailRepository = new FileMailRepository();
+ fileMailRepository.setFileSystem(fileSystem);
+ return fileMailRepository;
+ }
+ }
+
+ @Singleton
+ public static class MailRepositoryStoreModuleConfigurationPerformer
implements ConfigurationPerformer {
+
+ private final ClassPathConfigurationProvider
classPathConfigurationProvider;
+ private final InMemoryMailRepositoryStore javaMailRepositoryStore;
+
+ @Inject
+ public
MailRepositoryStoreModuleConfigurationPerformer(ClassPathConfigurationProvider
classPathConfigurationProvider,
+
InMemoryMailRepositoryStore javaMailRepositoryStore) {
+ this.classPathConfigurationProvider =
classPathConfigurationProvider;
+ this.javaMailRepositoryStore = javaMailRepositoryStore;
+ }
+
+ @Override
+ public void initModule() throws Exception {
+
javaMailRepositoryStore.configure(classPathConfigurationProvider.getConfiguration("mailrepositorystore"));
+ javaMailRepositoryStore.init();
+ }
+ }
+
+}
Added:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/InMemoryMailRepositoryStore.java
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,158 @@
+/****************************************************************
+ * 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.utils;
+
+import com.google.inject.Inject;
+import org.apache.commons.configuration.CombinedConfiguration;
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.commons.configuration.DefaultConfigurationBuilder;
+import org.apache.commons.configuration.HierarchicalConfiguration;
+import org.apache.james.lifecycle.api.Configurable;
+import org.apache.james.lifecycle.api.LogEnabled;
+import org.apache.james.mailrepository.api.MailRepository;
+import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.inject.Singleton;
+import java.util.Set;
+import java.util.Map;
+import java.util.HashMap;
+import java.util.List;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.ConcurrentMap;
+import java.util.stream.Collectors;
+
+@Singleton
+public class InMemoryMailRepositoryStore implements MailRepositoryStore {
+
+ private static final Logger LOGGER =
LoggerFactory.getLogger(InMemoryMailRepositoryStore.class);
+
+ private Set<MailRepositoryProvider> mailRepositories;
+ private ConcurrentMap<String, MailRepository>
destinationToRepositoryAssociations;
+ private Map<String, MailRepositoryProvider> protocolToRepositoryProvider;
+ private Map<String, HierarchicalConfiguration>
perProtocolMailRepositoryDefaultConfiguration;
+ private HierarchicalConfiguration configuration;
+
+ @Inject
+ public InMemoryMailRepositoryStore(Set<MailRepositoryProvider>
mailRepositories) {
+ this.mailRepositories = mailRepositories;
+ this.destinationToRepositoryAssociations = new ConcurrentHashMap<>();
+ this.protocolToRepositoryProvider = new HashMap<>();
+ this.perProtocolMailRepositoryDefaultConfiguration = new HashMap<>();
+ }
+
+ @Override
+ public List<String> getUrls() {
+ return destinationToRepositoryAssociations.keySet()
+ .stream()
+ .collect(Collectors.toList());
+ }
+
+ public void configure(HierarchicalConfiguration configuration) throws
ConfigurationException {
+ this.configuration = configuration;
+ }
+
+ public void init() throws Exception {
+ LOGGER.info("JamesMailStore init... " + this);
+ List<HierarchicalConfiguration> registeredClasses =
configuration.configurationsAt("mailrepositories.mailrepository");
+ for (HierarchicalConfiguration registeredClass : registeredClasses) {
+ readConfigurationEntry(registeredClass);
+ }
+ }
+
+ @Override
+ public MailRepository select(String destination) throws
MailRepositoryStoreException {
+ MailRepository mailRepository =
destinationToRepositoryAssociations.get(destination);
+ if (mailRepository != null) {
+ return mailRepository;
+ }
+ String protocol = retrieveProtocol(destination);
+ mailRepository = retrieveMailRepository(protocol);
+ mailRepository = initialiseNewRepository(mailRepository,
createRepositoryCombinedConfig(destination, protocol));
+ destinationToRepositoryAssociations.putIfAbsent(destination,
mailRepository);
+ return mailRepository;
+ }
+
+ private void readConfigurationEntry(HierarchicalConfiguration
repositoryConfiguration) throws ConfigurationException {
+ String className = repositoryConfiguration.getString("[@class]");
+ MailRepositoryProvider usedMailRepository = mailRepositories.stream()
+ .filter(mailRepositoryProvider ->
mailRepositoryProvider.canonicalName().equals(className))
+ .findAny()
+ .orElseThrow(() -> new ConfigurationException("MailRepository " +
className + " has not been registered"));
+ for (String protocol :
repositoryConfiguration.getStringArray("protocols.protocol")) {
+ protocolToRepositoryProvider.put(protocol, usedMailRepository);
+ registerRepositoryDefaultConfiguration(repositoryConfiguration,
protocol);
+ }
+ }
+
+ private void
registerRepositoryDefaultConfiguration(HierarchicalConfiguration
repositoryConfiguration, String protocol) {
+ HierarchicalConfiguration defConf = null;
+ if (repositoryConfiguration.getKeys("config").hasNext()) {
+ defConf = repositoryConfiguration.configurationAt("config");
+ }
+ if (defConf != null) {
+ perProtocolMailRepositoryDefaultConfiguration.put(protocol,
defConf);
+ }
+ }
+
+ private CombinedConfiguration createRepositoryCombinedConfig(String
destination, String protocol) {
+ final CombinedConfiguration config = new CombinedConfiguration();
+ HierarchicalConfiguration defaultProtocolConfig =
perProtocolMailRepositoryDefaultConfiguration.get(protocol);
+ if (defaultProtocolConfig != null) {
+ config.addConfiguration(defaultProtocolConfig);
+ }
+ DefaultConfigurationBuilder builder = new
DefaultConfigurationBuilder();
+ builder.addProperty("[@destinationURL]", destination);
+ config.addConfiguration(builder);
+ return config;
+ }
+
+ private MailRepository initialiseNewRepository(MailRepository
mailRepository, CombinedConfiguration config) throws
MailRepositoryStoreException {
+ try {
+ if (mailRepository instanceof LogEnabled) {
+ ((LogEnabled) mailRepository).setLog(LOGGER);
+ }
+ if (mailRepository instanceof Configurable) {
+ ((Configurable) mailRepository).configure(config);
+ }
+ return mailRepository;
+ } catch (Exception e) {
+ throw new MailRepositoryStoreException("Cannot init mail
repository", e);
+ }
+ }
+
+ private MailRepository retrieveMailRepository(String protocol) throws
MailRepositoryStoreException {
+ MailRepositoryProvider repositoryProvider =
protocolToRepositoryProvider.get(protocol);
+ if (repositoryProvider == null) {
+ throw new MailRepositoryStoreException("No Mail Repository
associated with " + protocol);
+ }
+ return repositoryProvider.get();
+ }
+
+ private String retrieveProtocol(String destination) throws
MailRepositoryStoreException {
+ int protocolSeparatorPosition = destination.indexOf(':');
+ if (protocolSeparatorPosition == -1) {
+ throw new MailRepositoryStoreException("Destination is malformed.
Must be a valid URL: " + destination);
+ }
+ return destination.substring(0, protocolSeparatorPosition);
+ }
+
+}
Added:
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/MailRepositoryProvider.java?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/main/java/org/apache/james/utils/MailRepositoryProvider.java
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,29 @@
+/****************************************************************
+ * 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.utils;
+
+import org.apache.james.mailrepository.api.MailRepository;
+
+import javax.inject.Provider;
+
+public interface MailRepositoryProvider extends Provider<MailRepository> {
+
+ String canonicalName();
+}
Added:
james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/test/java/org/apache/james/utils/InMemoryMailRepositoryStoreTest.java
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,106 @@
+/****************************************************************
+ * 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.utils;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.fail;
+
+import org.apache.commons.configuration.ConfigurationException;
+import org.apache.james.core.JamesServerResourceLoader;
+import org.apache.james.core.filesystem.FileSystemImpl;
+import org.apache.james.mailrepository.api.MailRepositoryStore;
+import org.apache.james.mailrepository.file.FileMailRepository;
+import org.apache.james.modules.server.MailStoreRepositoryModule;
+import org.junit.Before;
+import org.junit.Test;
+
+import com.google.common.collect.Sets;
+
+public class InMemoryMailRepositoryStoreTest {
+
+ private InMemoryMailRepositoryStore repositoryStore;
+
+ @Before
+ public void setUp() throws Exception {
+ repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet(
+ new MailStoreRepositoryModule.FileMailRepositoryProvider(
+ new FileSystemImpl(new JamesServerResourceLoader()))));
+ repositoryStore.configure(new
ClassPathConfigurationProvider().getConfiguration("mailrepositorystore"));
+ repositoryStore.init();
+ }
+
+ @Test(expected = MailRepositoryStore.MailRepositoryStoreException.class)
+ public void selectingANonRegisteredProtocolShouldFail() throws Exception {
+ repositoryStore.select("proto://repo");
+ }
+
+ @Test
+ public void selectingARegisteredProtocolShouldWork() throws Exception {
+
assertThat(repositoryStore.select("file://repo")).isInstanceOf(FileMailRepository.class);
+ }
+
+ @Test
+ public void
selectingTwiceARegisteredProtocolWithSameDestinationShouldReturnTheSameResult()
throws Exception {
+
assertThat(repositoryStore.select("file://repo")).isEqualTo(repositoryStore.select("file://repo"));
+ }
+
+ @Test
+ public void
selectingTwiceARegisteredProtocolWithDifferentDestinationShouldReturnDifferentResults()
throws Exception {
+
assertThat(repositoryStore.select("file://repo")).isNotEqualTo(repositoryStore.select("file://repo1"));
+ }
+
+ @Test(expected = ConfigurationException.class)
+ public void configureShouldThrowWhenNonValidClassesAreProvided() throws
Exception {
+ try {
+ repositoryStore = new InMemoryMailRepositoryStore(Sets.newHashSet(
+ new MailStoreRepositoryModule.FileMailRepositoryProvider(
+ new FileSystemImpl(new
JamesServerResourceLoader()))));
+ repositoryStore.configure(new
ClassPathConfigurationProvider().getConfiguration("fakemailrepositorystore"));
+ } catch (Exception e) {
+ fail("Unexpected failure : ", e);
+ }
+ repositoryStore.init();
+ }
+
+ @Test
+ public void getUrlsShouldBeEmptyIfNoSelectWerePerformed() {
+ assertThat(repositoryStore.getUrls()).isEmpty();
+ }
+
+ @Test
+ public void getUrlsShouldReturnUsedUrls() throws Exception {
+ String url1 = "file://repo1";
+ String url2 = "file://repo2";
+ String url3 = "file://repo3";
+ repositoryStore.select(url1);
+ repositoryStore.select(url2);
+ repositoryStore.select(url3);
+ assertThat(repositoryStore.getUrls()).containsOnly(url1, url2, url3);
+ }
+
+ @Test
+ public void getUrlsResultsShouldNotBeDuplicated() throws Exception {
+ String url1 = "file://repo1";
+ repositoryStore.select(url1);
+ repositoryStore.select(url1);
+ assertThat(repositoryStore.getUrls()).containsExactly(url1);
+ }
+
+}
Added:
james/project/trunk/server/container/cassandra-guice/src/test/resources/fakemailrepositorystore.xml
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/test/resources/fakemailrepositorystore.xml?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/test/resources/fakemailrepositorystore.xml
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/test/resources/fakemailrepositorystore.xml
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+
+<!--
+ 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.
+ -->
+
+<mailrepositorystore>
+ <mailrepositories>
+ <mailrepository class="org.apache.james.mailrepository.None">
+ <protocols>
+ <protocol>file</protocol>
+ </protocols>
+ <config FIFO="false" CACHEKEYS="true"/>
+ </mailrepository>
+ </mailrepositories>
+</mailrepositorystore>
Added:
james/project/trunk/server/container/cassandra-guice/src/test/resources/mailrepositorystore.xml
URL:
http://svn.apache.org/viewvc/james/project/trunk/server/container/cassandra-guice/src/test/resources/mailrepositorystore.xml?rev=1712337&view=auto
==============================================================================
---
james/project/trunk/server/container/cassandra-guice/src/test/resources/mailrepositorystore.xml
(added)
+++
james/project/trunk/server/container/cassandra-guice/src/test/resources/mailrepositorystore.xml
Tue Nov 3 16:49:53 2015
@@ -0,0 +1,31 @@
+<?xml version="1.0"?>
+
+<!--
+ 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.
+ -->
+
+<mailrepositorystore>
+ <mailrepositories>
+ <mailrepository
class="org.apache.james.mailrepository.file.FileMailRepository">
+ <protocols>
+ <protocol>file</protocol>
+ </protocols>
+ <config FIFO="false" CACHEKEYS="true"/>
+ </mailrepository>
+ </mailrepositories>
+</mailrepositorystore>
---------------------------------------------------------------------
To unsubscribe, e-mail: [email protected]
For additional commands, e-mail: [email protected]