From 29e57e6d3255bcb2d400df56ad5c5bcae41fa709 Mon Sep 17 00:00:00 2001 From: gm2552 Date: Tue, 19 Mar 2019 19:14:51 -0500 Subject: [PATCH 1/2] Initial check in. --- manifest.yml | 16 + pom.xml | 499 ++++++++++++++++++ .../authfilter/WebAdminBasicAuthFilter.java | 87 +++ .../server/boot/JamesServerApplication.java | 29 + ...StreamsTimelyAndReliableLocalDelivery.java | 43 ++ .../server/mailets/ToStaAgentStream.java | 81 +++ .../modules/DirectWebAdminServerModule.java | 98 ++++ .../spring/ConfigServiceClientConfig.java | 33 ++ .../server/spring/JamesServerConfig.java | 267 ++++++++++ .../streams/STALastMileDeliveryInput.java | 12 + .../streams/SmtpGatewayMessageOutput.java | 12 + .../streams/SmtpGatewayMessageSource.java | 36 ++ .../sinks/STALastMileDeliverySink.java | 71 +++ src/main/resources/application.yml | 25 + src/main/resources/bootstrap.yml | 34 ++ src/main/resources/properties/domainlist.xml | 28 + src/main/resources/properties/imapserver.xml | 82 +++ .../properties/james-database.properties | 11 + .../properties/mailetcontainer.out.xml | 0 .../resources/properties/mailetcontainer.xml | 121 +++++ src/main/resources/properties/pop3server.xml | 44 ++ src/main/resources/properties/smtpserver.xml | 81 +++ .../resources/properties/webadmin.properties | 9 + 23 files changed, 1719 insertions(+) create mode 100644 manifest.yml create mode 100644 pom.xml create mode 100644 src/main/java/org/nhindirect/james/server/authfilter/WebAdminBasicAuthFilter.java create mode 100644 src/main/java/org/nhindirect/james/server/boot/JamesServerApplication.java create mode 100644 src/main/java/org/nhindirect/james/server/mailets/StreamsTimelyAndReliableLocalDelivery.java create mode 100644 src/main/java/org/nhindirect/james/server/mailets/ToStaAgentStream.java create mode 100644 src/main/java/org/nhindirect/james/server/modules/DirectWebAdminServerModule.java create mode 100644 src/main/java/org/nhindirect/james/server/spring/ConfigServiceClientConfig.java create mode 100644 src/main/java/org/nhindirect/james/server/spring/JamesServerConfig.java create mode 100644 src/main/java/org/nhindirect/james/server/streams/STALastMileDeliveryInput.java create mode 100644 src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageOutput.java create mode 100644 src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageSource.java create mode 100644 src/main/java/org/nhindirect/james/server/streams/sinks/STALastMileDeliverySink.java create mode 100644 src/main/resources/application.yml create mode 100644 src/main/resources/bootstrap.yml create mode 100644 src/main/resources/properties/domainlist.xml create mode 100644 src/main/resources/properties/imapserver.xml create mode 100644 src/main/resources/properties/james-database.properties create mode 100644 src/main/resources/properties/mailetcontainer.out.xml create mode 100644 src/main/resources/properties/mailetcontainer.xml create mode 100644 src/main/resources/properties/pop3server.xml create mode 100644 src/main/resources/properties/smtpserver.xml create mode 100644 src/main/resources/properties/webadmin.properties diff --git a/manifest.yml b/manifest.yml new file mode 100644 index 0000000..f4e211b --- /dev/null +++ b/manifest.yml @@ -0,0 +1,16 @@ +--- +applications: +- name: direct-james-server + health-check-type: none + instances: 1 + buildpack: java_buildpack + path: target/direct-james-server-6.0-SNAPSHOT.jar + timeout: 120 + env: + spring.cloud.config.label: master + JBP_CONFIG_DEBUG: '{enabled: true}' + JBP_CONFIG_SPRING_AUTO_RECONFIGURATION: '{enabled: false}' + services: + - directhisp-config-server + - directhisp-eureka + - directhisp-rabbit diff --git a/pom.xml b/pom.xml new file mode 100644 index 0000000..ddb721a --- /dev/null +++ b/pom.xml @@ -0,0 +1,499 @@ + + + 4.0.0 + org.nhind + direct-james-server + 6.0-SNAPSHOT + jar + Direct Java RI James Spring Boot Application + irect Java RI James Spring Boot Application + http://api.nhindirect.org/x/www/api.nhindirect.org/java/site/config/direct-james-server/${project.version} + + scm:git:https://github.com/DirectProject/direct-james-server.git + scm:git:https://github.com/DirectProject/direct-james-server.git + + + 3.0.0 + + + org.springframework.boot + spring-boot-starter-parent + 2.1.3.RELEASE + + + + + Greg Meyer + GM2552 + gm2552@cerner.com + + owner + + + + + + + New BSD License + http://nhindirect.org/BSDLicense + + + + + spring-milestone + Spring Milestone Releases + https://repo.spring.io/milestone/ + + + + UTF-8 + + + + + org.springframework.boot + spring-boot-dependencies + 2.1.3.RELEASE + pom + import + + + io.pivotal.spring.cloud + spring-cloud-services-dependencies + 2.1.1.RELEASE + pom + import + + + org.springframework.cloud + spring-cloud-starter-parent + Greenwich.SR1 + pom + import + + + io.dropwizard.metrics + metrics-core + 3.2.6 + + + io.dropwizard.metrics + metrics-jvm + 3.2.6 + + + + + + + org.springframework.boot + spring-boot-configuration-processor + + + org.springframework.boot + spring-boot-starter-actuator + + + org.springframework.cloud + spring-cloud-starter-config + + + org.springframework.cloud + spring-cloud-starter-netflix-eureka-client + + + com.google.inject + guice + 4.2.2 + + + io.pivotal.spring.cloud + spring-cloud-services-starter-config-client + + + org.codehaus.jackson + jackson-mapper-asl + + + + + org.springframework.cloud + spring-cloud-stream + + + org.springframework.cloud + spring-cloud-starter-stream-rabbit + + + org.nhind + config-service-client + 6.0 + + + + org.apache.james + james-server-jpa-guice + 3.2.0 + + + org.apache.james + james-server-guice-common + 3.2.0 + + + org.apache.james + james-server-guice-imap + 3.2.0 + + + org.apache.james + james-server-guice-lmtp + 3.2.0 + + + org.apache.james + james-server-guice-managedsieve + 3.2.0 + + + org.apache.james + james-server-guice-smtp + 3.2.0 + + + org.apache.james + james-server-guice-pop + 3.2.0 + + + org.apache.james + james-server-guice-mailbox + 3.2.0 + + + org.apache.james + james-server-guice-activemq + 3.2.0 + + + org.apache.james + james-server-guice-activemq + 3.2.0 + + + org.apache.james + james-server-guice-es-resporter + 3.2.0 + + + org.apache.james + james-server-guice-mailbox-plugin-spamassassin + 3.2.0 + + + org.apache.james + james-server-jpa-common-guice + 3.2.0 + + + org.apache.james + metrics-dropwizard + 3.2.0 + + + org.apache.james + james-server-guice-webadmin + 3.2.0 + + + org.apache.james + james-server-guice-webadmin-data + 3.2.0 + + + org.apache.james + james-server-guice-webadmin-mailbox + 3.2.0 + + + org.apache.james + james-server-guice-webadmin-mailqueue + 3.2.0 + + + org.apache.james + james-server-guice-webadmin-mailrepository + 3.2.0 + + + org.apache.james + james-server-guice-webadmin-swagger + 3.2.0 + + + + com.h2database + h2 + 1.4.194 + runtime + + + org.mariadb.jdbc + mariadb-java-client + runtime + + + org.apache.derby + derby + 10.14.2.0 + runtime + + + mysql + mysql-connector-java + 5.1.47 + runtime + + + org.postgresql + postgresql + 42.2.5 + runtime + + + + + + org.apache.maven.plugins + maven-source-plugin + 3.0.1 + + + + jar + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + + testCompile + + compile + + + + true + true + true + UTF-8 + 1.8 + 1.8 + + + + com.atlassian.maven.plugins + maven-clover2-plugin + 3.0.2 + + 1.8 + ${project.basedir}/../../licenses/clover.license + + + + pre-site + + instrument + + + + + + org.springframework.boot + spring-boot-maven-plugin + + + + + + + + org.apache.maven.plugins + maven-project-info-reports-plugin + 2.9 + + + org.apache.maven.plugins + maven-javadoc-plugin + 3.0.1 + + UTF-8 + UTF-8 + true + true + true + 1.8 + protected + + + + org.apache.maven.plugins + maven-pmd-plugin + + 1.8 + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.codehaus.mojo + findbugs-maven-plugin + 1.2 + + Max + + + + org.codehaus.mojo + taglist-maven-plugin + + + FIXME + TODO + WARN + @deprecated + + + + + com.atlassian.maven.plugins + maven-clover2-plugin + 3.0.2 + + ${project.basedir}/../../licenses/clover.license + + + + + + + nhind-site + NHIN Direct API publication site + sftp://api.nhindirect.org/x/www/api.nhindirect.org/java/site/direct-james-server/${project.version} + + + sonatype-snapshot + Sonatype OSS Maven SNAPSHOT Repository + https://oss.sonatype.org/content/repositories/snapshots/ + false + + + sonatype-release + Sonatype OSS Maven Release Repositor + https://oss.sonatype.org/service/local/staging/deploy/maven2/ + false + + + + diff --git a/src/main/java/org/nhindirect/james/server/authfilter/WebAdminBasicAuthFilter.java b/src/main/java/org/nhindirect/james/server/authfilter/WebAdminBasicAuthFilter.java new file mode 100644 index 0000000..3131baf --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/authfilter/WebAdminBasicAuthFilter.java @@ -0,0 +1,87 @@ +package org.nhindirect.james.server.authfilter; + +import static spark.Spark.halt; + +import java.nio.charset.Charset; +import java.security.MessageDigest; +import java.util.Objects; +import java.util.Optional; + +import org.apache.commons.codec.binary.Base64; +import org.apache.james.webadmin.authentication.AuthenticationFilter; +import org.eclipse.jetty.http.HttpStatus; + +import spark.Request; +import spark.Response; + +public class WebAdminBasicAuthFilter implements AuthenticationFilter +{ + public static final String AUTHORIZATION_HEADER_NAME = "Authorization"; + public static final String AUTHORIZATION_HEADER_PREFIX = "Basic "; + public static final String OPTIONS = "OPTIONS"; + + protected final String user; + protected final byte[] passHash; + protected final MessageDigest digest; + + public WebAdminBasicAuthFilter(String user, String pass) + { + try + { + digest = MessageDigest.getInstance("SHA-256"); + + this.user = user; + this.passHash = digest.digest(pass.getBytes(Charset.defaultCharset())); + } + catch (Exception e) + { + throw new IllegalStateException("Error creating webadmin password hash: " + e.getMessage()); + } + } + + @Override + public void handle(Request request, Response response) throws Exception + { + if (request.requestMethod() != OPTIONS) + { + Optional basicAuth = Optional.ofNullable(request.headers(AUTHORIZATION_HEADER_NAME)) + .filter(value -> value.startsWith(AUTHORIZATION_HEADER_PREFIX)) + .map(value -> value.substring(AUTHORIZATION_HEADER_PREFIX.length())); + + checkHeaderPresent(basicAuth); + + final String[] subjectAndSecret = new String(Base64.decodeBase64(basicAuth.get()), Charset.defaultCharset()).split(":"); + final String user = subjectAndSecret[0]; + final String pass = subjectAndSecret[1]; + + checkValidPass(pass); + checkIsAdmin(user); + } + } + + private void checkHeaderPresent(Optional basicAuth) + { + if (!basicAuth.isPresent()) + { + halt(HttpStatus.UNAUTHORIZED_401, "No Basic Auth header."); + } + } + + private void checkIsAdmin(String user) + { + if (user.compareToIgnoreCase(this.user) != 0) + { + halt(HttpStatus.UNAUTHORIZED_401, "Non authorized user."); + } + } + + private void checkValidPass(String pass) + { + final byte[] passDigest = digest.digest(pass.getBytes(Charset.defaultCharset())); + + if (!Objects.deepEquals(passDigest, this.passHash)) + { + halt(HttpStatus.UNAUTHORIZED_401, "Invalid login."); + } + } +} diff --git a/src/main/java/org/nhindirect/james/server/boot/JamesServerApplication.java b/src/main/java/org/nhindirect/james/server/boot/JamesServerApplication.java new file mode 100644 index 0000000..2b2294a --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/boot/JamesServerApplication.java @@ -0,0 +1,29 @@ +package org.nhindirect.james.server.boot; + +import org.springframework.boot.SpringApplication; +import org.springframework.boot.WebApplicationType; +import org.springframework.boot.autoconfigure.EnableAutoConfiguration; +import org.springframework.boot.autoconfigure.SpringBootApplication; +import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration; +import org.springframework.boot.autoconfigure.orm.jpa.HibernateJpaAutoConfiguration; +import org.springframework.boot.builder.SpringApplicationBuilder; +import org.springframework.cloud.netflix.eureka.EnableEurekaClient; +import org.springframework.context.annotation.ComponentScan; + +@SpringBootApplication +@ComponentScan({"org.nhindirect.james.server.spring", "org.nhindirect.james.server.streams"}) +@EnableAutoConfiguration(exclude = {DataSourceAutoConfiguration.class, HibernateJpaAutoConfiguration.class}) +@EnableEurekaClient +public class JamesServerApplication +{ + public static void main(String[] args) + { + SpringApplication springApplication = + new SpringApplicationBuilder() + .sources(JamesServerApplication.class) + .web(WebApplicationType.NONE) + .build(); + + springApplication.run(args); + } +} diff --git a/src/main/java/org/nhindirect/james/server/mailets/StreamsTimelyAndReliableLocalDelivery.java b/src/main/java/org/nhindirect/james/server/mailets/StreamsTimelyAndReliableLocalDelivery.java new file mode 100644 index 0000000..f5ad30b --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/mailets/StreamsTimelyAndReliableLocalDelivery.java @@ -0,0 +1,43 @@ +package org.nhindirect.james.server.mailets; + +import javax.inject.Inject; + +import org.apache.james.mailbox.MailboxManager; +import org.apache.james.metrics.api.MetricFactory; +import org.apache.james.transport.mailets.LocalDelivery; +import org.apache.james.user.api.UsersRepository; +import org.apache.mailet.Mailet; +//import org.nhindirect.gateway.smtp.james.mailet.TimelyAndReliableLocalDelivery; + +public class StreamsTimelyAndReliableLocalDelivery extends LocalDelivery//TimelyAndReliableLocalDelivery +{ + protected static StreamsTimelyAndReliableLocalDelivery mailetContextInstance; + + @Inject + public StreamsTimelyAndReliableLocalDelivery(UsersRepository usersRepository, MailboxManager mailboxManager, + MetricFactory metricFactory) + { + super(usersRepository, mailboxManager, metricFactory); + /* + * Set the static reference used by the Spring Cloud streams processor (i.e. the processLastMileMessage() method). + * Once this instance has been set, then notify any thread that is blocked. + */ + synchronized(StreamsTimelyAndReliableLocalDelivery.class) + { + if (usersRepository != null) + { + mailetContextInstance = this; + StreamsTimelyAndReliableLocalDelivery.class.notifyAll(); + } + } + } + + public static Mailet getStaticMailet() + { + synchronized(StreamsTimelyAndReliableLocalDelivery.class) + { + return mailetContextInstance; + } + } + +} diff --git a/src/main/java/org/nhindirect/james/server/mailets/ToStaAgentStream.java b/src/main/java/org/nhindirect/james/server/mailets/ToStaAgentStream.java new file mode 100644 index 0000000..e9be009 --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/mailets/ToStaAgentStream.java @@ -0,0 +1,81 @@ +package org.nhindirect.james.server.mailets; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; +import java.util.stream.Collectors; + +import javax.mail.Address; +import javax.mail.MessagingException; +import javax.mail.internet.InternetAddress; + +import org.apache.james.core.MailAddress; +import org.apache.mailet.Mail; +import org.apache.mailet.base.GenericMailet; +import org.nhindirect.common.mail.SMTPMailMessage; +import org.nhindirect.james.server.streams.SmtpGatewayMessageSource; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class ToStaAgentStream extends GenericMailet +{ + protected static final Logger LOGGER = LoggerFactory.getLogger(ToStaAgentStream.class); + + public ToStaAgentStream() + { + + } + + @Override + public void service(Mail mail) throws MessagingException + { + LOGGER.info("Receiving message to deliver to STA. Message id: {}", mail.getMessage().getMessageID()); + + final SMTPMailMessage smtpMailMessage = mailToSMTPMailMessage(mail); + + final SmtpGatewayMessageSource messageSource = SmtpGatewayMessageSource.getMessageSourceInstance(); + if (messageSource != null) + { + messageSource.forwardSMTPMessage(smtpMailMessage); + mail.setState(Mail.GHOST); + + LOGGER.info("Message sent to STA. Message id: {}", mail.getMessage().getMessageID()); + + return; + } + + LOGGER.warn("Message STA source is not available to process message id: {}", mail.getMessage().getMessageID()); + } + + /** + * Converts an Apache James Mail message to the common SMTPMailMessage object; + * @param mail The Apache James smtp message + * @return An SMTPMailMessage message instance container information from the Apache James mail object; + */ + @SuppressWarnings("deprecation") + public static SMTPMailMessage mailToSMTPMailMessage(Mail mail) throws MessagingException + { + if (mail == null) + return null; + + List toAddrs = new ArrayList<>(); + final InternetAddress fromAddr = (mail.getSender() == null) ? null : mail.getSender().toInternetAddress(); + // uses the RCPT TO commands + final Collection recips = mail.getRecipients(); + if (recips == null || recips.size() == 0) + { + // fall back to the mime message list of recipients + final Address[] recipsAddr = mail.getMessage().getAllRecipients(); + for (Address addr : recipsAddr) + toAddrs.add((InternetAddress)addr); + } + else + { + toAddrs = recips.stream(). + map(toAddr -> toAddr.toInternetAddress()).collect(Collectors.toList()); + + } + + return new SMTPMailMessage(mail.getMessage(), toAddrs, fromAddr); + } +} diff --git a/src/main/java/org/nhindirect/james/server/modules/DirectWebAdminServerModule.java b/src/main/java/org/nhindirect/james/server/modules/DirectWebAdminServerModule.java new file mode 100644 index 0000000..9123d9f --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/modules/DirectWebAdminServerModule.java @@ -0,0 +1,98 @@ +package org.nhindirect.james.server.modules; + +import static org.apache.james.webadmin.WebAdminConfiguration.DISABLED_CONFIGURATION; + +import java.io.FileNotFoundException; +import java.util.Optional; + +import org.apache.commons.configuration.Configuration; +import org.apache.james.modules.server.HealthCheckRoutesModule; +import org.apache.james.modules.server.TaskRoutesModule; +import org.apache.james.modules.server.WebAdminServerModule.WebAdminServerModuleConfigurationPerformer; +import org.apache.james.utils.ConfigurationPerformer; +import org.apache.james.utils.GuiceProbe; +import org.apache.james.utils.PropertiesProvider; +import org.apache.james.utils.WebAdminGuiceProbe; +import org.apache.james.webadmin.FixedPortSupplier; +import org.apache.james.webadmin.TlsConfiguration; +import org.apache.james.webadmin.WebAdminConfiguration; +import org.apache.james.webadmin.WebAdminServer; +import org.apache.james.webadmin.authentication.AuthenticationFilter; +import org.apache.james.webadmin.utils.JsonTransformer; +import org.apache.james.webadmin.utils.JsonTransformerModule; +import org.nhindirect.james.server.authfilter.WebAdminBasicAuthFilter; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import com.google.inject.AbstractModule; +import com.google.inject.Provides; +import com.google.inject.Scopes; +import com.google.inject.multibindings.Multibinder; + +public class DirectWebAdminServerModule extends AbstractModule +{ + + private static final Logger LOGGER = LoggerFactory.getLogger(DirectWebAdminServerModule.class); + private static final boolean DEFAULT_DISABLED = true; + private static final String DEFAULT_NO_CORS_ORIGIN = null; + private static final boolean DEFAULT_CORS_DISABLED = false; + private static final String DEFAULT_NO_KEYSTORE = null; + private static final boolean DEFAULT_HTTPS_DISABLED = false; + private static final String DEFAULT_NO_PASSWORD = null; + private static final String DEFAULT_NO_TRUST_KEYSTORE = null; + private static final String DEFAULT_NO_TRUST_PASSWORD = null; + + @Override + protected void configure() + { + install(new TaskRoutesModule()); + install(new HealthCheckRoutesModule()); + + bind(JsonTransformer.class).in(Scopes.SINGLETON); + bind(WebAdminServer.class).in(Scopes.SINGLETON); + + Multibinder.newSetBinder(binder(), ConfigurationPerformer.class).addBinding().to(WebAdminServerModuleConfigurationPerformer.class); + Multibinder.newSetBinder(binder(), GuiceProbe.class).addBinding().to(WebAdminGuiceProbe.class); + Multibinder.newSetBinder(binder(), JsonTransformerModule.class); + } + + @Provides + public WebAdminConfiguration provideWebAdminConfiguration(PropertiesProvider propertiesProvider) throws Exception { + try { + Configuration configurationFile = propertiesProvider.getConfiguration("webadmin"); + return WebAdminConfiguration.builder() + .enable(configurationFile.getBoolean("enabled", DEFAULT_DISABLED)) + .port(new FixedPortSupplier(configurationFile.getInt("port", WebAdminServer.DEFAULT_PORT))) + .tls(readHttpsConfiguration(configurationFile)) + .enableCORS(configurationFile.getBoolean("cors.enable", DEFAULT_CORS_DISABLED)) + .urlCORSOrigin(configurationFile.getString("cors.origin", DEFAULT_NO_CORS_ORIGIN)) + .host(configurationFile.getString("host", WebAdminConfiguration.DEFAULT_HOST)) + .build(); + } catch (FileNotFoundException e) { + LOGGER.info("No webadmin.properties file. Disabling WebAdmin interface."); + return DISABLED_CONFIGURATION; + } + } + + @Provides + public AuthenticationFilter providesAuthenticationFilter(PropertiesProvider propertiesProvider) throws Exception + { + Configuration configurationFile = propertiesProvider.getConfiguration("webadmin"); + + return new WebAdminBasicAuthFilter(configurationFile.getString("username"), configurationFile.getString("password")); + } + + private Optional readHttpsConfiguration(Configuration configurationFile) { + boolean enabled = configurationFile.getBoolean("https.enabled", DEFAULT_HTTPS_DISABLED); + if (enabled) { + return Optional.of(TlsConfiguration.builder() + .raw(configurationFile.getString("https.keystore", DEFAULT_NO_KEYSTORE), + configurationFile.getString("https.password", DEFAULT_NO_PASSWORD), + configurationFile.getString("https.trust.keystore", DEFAULT_NO_TRUST_KEYSTORE), + configurationFile.getString("https.trust.password", DEFAULT_NO_TRUST_PASSWORD)) + .build()); + } + return Optional.empty(); + } + +} diff --git a/src/main/java/org/nhindirect/james/server/spring/ConfigServiceClientConfig.java b/src/main/java/org/nhindirect/james/server/spring/ConfigServiceClientConfig.java new file mode 100644 index 0000000..7caa268 --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/spring/ConfigServiceClientConfig.java @@ -0,0 +1,33 @@ +package org.nhindirect.james.server.spring; + +import org.nhind.config.rest.AddressService; +import org.nhind.config.rest.DomainService; +import org.nhind.config.rest.feign.AddressClient; +import org.nhind.config.rest.feign.DomainClient; +import org.nhind.config.rest.impl.DefaultAddressService; +import org.nhind.config.rest.impl.DefaultDomainService; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.cloud.openfeign.EnableFeignClients; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +@Configuration +@EnableFeignClients({"org.nhind.config.rest.feign"}) +public class ConfigServiceClientConfig +{ + + @Bean + @ConditionalOnMissingBean + public DomainService domainService(DomainClient domainClient) + { + return new DefaultDomainService(domainClient); + } + + @Bean + @ConditionalOnMissingBean + public AddressService addressService(AddressClient addressClient) + { + return new DefaultAddressService(addressClient); + } + +} diff --git a/src/main/java/org/nhindirect/james/server/spring/JamesServerConfig.java b/src/main/java/org/nhindirect/james/server/spring/JamesServerConfig.java new file mode 100644 index 0000000..0f5022a --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/spring/JamesServerConfig.java @@ -0,0 +1,267 @@ +package org.nhindirect.james.server.spring; + +import java.io.File; +import java.nio.charset.Charset; +import java.util.Collection; + +import org.apache.commons.io.IOUtils; +import org.apache.commons.lang3.StringUtils; +import org.apache.james.GuiceJamesServer; +import org.apache.james.modules.MailboxModule; +import org.apache.james.modules.activemq.ActiveMQQueueModule; +import org.apache.james.modules.data.JPADataModule; +import org.apache.james.modules.data.SieveJPARepositoryModules; +import org.apache.james.modules.mailbox.DefaultEventModule; +import org.apache.james.modules.mailbox.JPAMailboxModule; +import org.apache.james.modules.mailbox.LuceneSearchMailboxModule; +import org.apache.james.modules.protocols.IMAPServerModule; +import org.apache.james.modules.protocols.LMTPServerModule; +import org.apache.james.modules.protocols.ManageSieveServerModule; +import org.apache.james.modules.protocols.POP3ServerModule; +import org.apache.james.modules.protocols.ProtocolHandlerModule; +import org.apache.james.modules.protocols.SMTPServerModule; +import org.apache.james.modules.server.DataRoutesModules; +import org.apache.james.modules.server.DefaultProcessorsConfigurationProviderModule; +import org.apache.james.modules.server.ElasticSearchMetricReporterModule; +import org.apache.james.modules.server.JMXServerModule; +import org.apache.james.modules.server.MailQueueRoutesModule; +import org.apache.james.modules.server.MailRepositoriesRoutesModule; +import org.apache.james.modules.server.MailboxRoutesModule; +import org.apache.james.modules.server.NoJwtModule; +import org.apache.james.modules.server.RawPostDequeueDecoratorModule; +import org.apache.james.modules.server.ReIndexingModule; +import org.apache.james.modules.server.SieveQuotaRoutesModule; +import org.apache.james.modules.server.SwaggerRoutesModule; +import org.apache.james.modules.spamassassin.SpamAssassinListenerModule; +import org.nhind.config.rest.DomainService; +import org.nhindirect.config.model.Domain; +import org.nhindirect.james.server.modules.DirectWebAdminServerModule; +import org.parboiled.common.FileUtils; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Value; +import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +import com.google.inject.Module; +import com.google.inject.util.Modules; + +@Configuration +public class JamesServerConfig +{ + private static final Logger LOGGER = LoggerFactory.getLogger(JamesServerConfig.class); + + public static final String DEFAULT_MAILET_CONFIG = "/properties/mailetcontainer.xml"; + public static final String DEFAULT_IMAP_CONFIG = "/properties/imapserver.xml"; + public static final String DEFAULT_POP3_CONFIG = "/properties/pop3server.xml"; + public static final String DEFAULT_SMTP_CONFIG = "/properties/smtpserver.xml"; + + + @Value("${spring.datasource.driver-class-name}") + protected String driverClassName; + + @Value("${spring.datasource.url}") + protected String datasourceUrl; + + @Value("${spring.datasource.username}") + protected String datasourceUserName; + + @Value("${spring.datasource.password}") + protected String datasourcePassword; + + @Value("${spring.datasource.adapter}") + protected String datasourceAdapter; + + @Value("${spring.datasource.streaming}") + protected String datasourceStreaming; + + @Value("${james.server.webadmin.enabled:true}") + protected String enableWebAdmin; + + @Value("${james.server.webadmin.port:8080}") + protected String webAdminPort; + + @Value("${james.server.webadmin.username}") + protected String webAdminUser; + + @Value("${james.server.webadmin.password}") + protected String webAdminPassword; + + @Value("${james.server.webadmin.https.tlsenabled:false}") + protected String webadminTlsEnabled; + + @Value("${james.server.webadmin.https.keystore:}") + protected String webAdminKeystore; + + @Value("${james.server.webadmin.https.keystorePassword:}") + protected String webAdminKeystorePassword; + + @Value("${james.server.webadmin.https.trust.keystore:}") + protected String webAdminTrustKeystore; + + @Value("${james.server.webadmin.https.trust.keystorePassword:}") + protected String webAdminTrustKeystorePassword; + + @Value("${james.server.config.mailet.configFile:}") + protected String mailetConfigFile; + + @Value("${james.server.config.imap.configFile:}") + protected String imapConfigFile; + + @Value("${james.server.config.pop3.configFile:}") + protected String pop3ConfigFile; + + @Value("${james.server.config.smtp.configFile:}") + protected String smtpConfigFile; + + @Autowired + protected DomainService domService; + + public static final Module PROTOCOLS; + public static final Module JPA_SERVER_MODULE; + public static final Module JPA_MODULE_AGGREGATE; + public static final Module WEBADMIN; + + static + { + + WEBADMIN = Modules.combine( + new DirectWebAdminServerModule(), + new DataRoutesModules(), + new MailboxRoutesModule(), + new MailQueueRoutesModule(), + new MailRepositoriesRoutesModule(), + new SwaggerRoutesModule(), + new SieveQuotaRoutesModule(), + new ReIndexingModule()); + + PROTOCOLS = Modules + .combine(new Module[]{new IMAPServerModule(), new LMTPServerModule(), new ManageSieveServerModule(), + new POP3ServerModule(), new ProtocolHandlerModule(), new SMTPServerModule(), WEBADMIN}); + + JPA_SERVER_MODULE = Modules.combine(new Module[]{new ActiveMQQueueModule(), + new DefaultProcessorsConfigurationProviderModule(), new ElasticSearchMetricReporterModule(), + new JPADataModule(), new JPAMailboxModule(), new MailboxModule(), new LuceneSearchMailboxModule(), new NoJwtModule(), + new RawPostDequeueDecoratorModule(), new SieveJPARepositoryModules(), + new DefaultEventModule(), new SpamAssassinListenerModule()}); + + JPA_MODULE_AGGREGATE = Modules.combine(new Module[]{JPA_SERVER_MODULE, PROTOCOLS}); + } + + + @Bean + @ConditionalOnMissingBean + public GuiceJamesServer jamesServer() throws Exception + { + writeJPAConfig(); + + writeWebAdminConfig(); + + writeDomainListConfig(); + + writeXMLConfigs(); + + final org.apache.james.server.core.configuration.Configuration configuration = + org.apache.james.server.core.configuration.Configuration.builder().workingDirectory(".").build(); + + final GuiceJamesServer server = GuiceJamesServer.forConfiguration(configuration) + .combineWith(new Module[]{JPA_MODULE_AGGREGATE, new JMXServerModule()}); + + server.start(); + + return server; + } + + protected void writeJPAConfig() throws Exception + { + final File file = new File("conf/james-database.properties"); + + String dbPropString = IOUtils.resourceToString("/properties/james-database.properties", Charset.defaultCharset()); + dbPropString = dbPropString.replace("${driver}", this.driverClassName); + dbPropString = dbPropString.replace("${url}", this.datasourceUrl); + dbPropString = dbPropString.replace("${username}", this.datasourceUserName); + dbPropString = dbPropString.replace("${password}", this.datasourcePassword); + dbPropString = dbPropString.replace("${dbadapter}", this.datasourceAdapter); + + dbPropString = dbPropString.replace("${streaming}", this.datasourceStreaming); + + FileUtils.writeAllText(dbPropString, file); + } + + protected void writeWebAdminConfig() throws Exception + { + final File file = new File("conf/webadmin.properties"); + + String webAdminString = IOUtils.resourceToString("/properties/webadmin.properties", Charset.defaultCharset()); + webAdminString = webAdminString.replace("${enabled}", this.enableWebAdmin); + webAdminString = webAdminString.replace("${port}", this.webAdminPort); + webAdminString = webAdminString.replace("${username}", this.webAdminUser); + webAdminString = webAdminString.replace("${password}", this.webAdminPassword); + webAdminString = webAdminString.replace("${httpsEnabled}", this.webadminTlsEnabled); + webAdminString = webAdminString.replace("${keystore}", this.webAdminKeystore); + webAdminString = webAdminString.replace("${keystorePassword}", this.webAdminKeystorePassword); + webAdminString = webAdminString.replace("${trustKeystore}", this.webAdminTrustKeystore); + webAdminString = webAdminString.replace("${trustPassword}", this.webAdminTrustKeystorePassword); + + + FileUtils.writeAllText(webAdminString, file); + } + + protected void writeDomainListConfig() throws Exception + { + final File file = new File("conf/domainlist.xml"); + + String domainlistXML = IOUtils.resourceToString("/properties/domainlist.xml", Charset.defaultCharset()); + final StringBuilder domListBuilder = new StringBuilder(); + + Collection domains = domService.searchDomains("", null); + if (domains.isEmpty()) + { + LOGGER.warn("No domains defined. A default list will be injected by James."); + return; + } + for (Domain domain : domains) + { + domListBuilder.append("").append(domain.getDomainName()).append("\r\n"); + } + + domainlistXML = domainlistXML.replace("${domainnames}", domListBuilder.toString()); + // just use the first in the list for the default damain + domainlistXML = domainlistXML.replace("${defaultdomain}", domains.iterator().next().getDomainName()); + + FileUtils.writeAllText(domainlistXML, file); + } + + protected void writeXMLConfigs() throws Exception + { + /* + * Mailet config + */ + File writeFile = new File("conf/mailetcontainer.xml"); + byte[] content = (StringUtils.isEmpty(mailetConfigFile)) ? IOUtils.resourceToByteArray(DEFAULT_MAILET_CONFIG) : FileUtils.readAllBytes(new File(mailetConfigFile)); + FileUtils.writeAllBytes(content, writeFile); + + /* + * IMAP config + */ + writeFile = new File("conf/imapserver.xml"); + content = (StringUtils.isEmpty(imapConfigFile)) ? IOUtils.resourceToByteArray(DEFAULT_IMAP_CONFIG) : FileUtils.readAllBytes(new File(imapConfigFile)); + FileUtils.writeAllBytes(content, writeFile); + + /* + * IMAP config + */ + writeFile = new File("conf/pop3server.xml"); + content = (StringUtils.isEmpty(pop3ConfigFile)) ? IOUtils.resourceToByteArray(DEFAULT_POP3_CONFIG) : FileUtils.readAllBytes(new File(pop3ConfigFile)); + FileUtils.writeAllBytes(content, writeFile); + + /* + * SMTP config + */ + writeFile = new File("conf/smtpserver.xml"); + content = (StringUtils.isEmpty(smtpConfigFile)) ? IOUtils.resourceToByteArray(DEFAULT_SMTP_CONFIG) : FileUtils.readAllBytes(new File(smtpConfigFile)); + FileUtils.writeAllBytes(content, writeFile); + } +} diff --git a/src/main/java/org/nhindirect/james/server/streams/STALastMileDeliveryInput.java b/src/main/java/org/nhindirect/james/server/streams/STALastMileDeliveryInput.java new file mode 100644 index 0000000..4f02944 --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/streams/STALastMileDeliveryInput.java @@ -0,0 +1,12 @@ +package org.nhindirect.james.server.streams; + +import org.springframework.cloud.stream.annotation.Input; +import org.springframework.messaging.SubscribableChannel; + +public interface STALastMileDeliveryInput +{ + public static final String STA_LAST_MILE_INPUT = "direct-sta-last-mile-input"; + + @Input(STA_LAST_MILE_INPUT) + SubscribableChannel staLastMileInput(); +} diff --git a/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageOutput.java b/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageOutput.java new file mode 100644 index 0000000..23a240c --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageOutput.java @@ -0,0 +1,12 @@ +package org.nhindirect.james.server.streams; + +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.MessageChannel; + +public interface SmtpGatewayMessageOutput +{ + public static final String SMTP_GATEWAY_MESSAGE_OUTPUT = "direct-smtp-mq-gateway"; + + @Output(SMTP_GATEWAY_MESSAGE_OUTPUT) + MessageChannel txOutput(); +} diff --git a/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageSource.java b/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageSource.java new file mode 100644 index 0000000..0ab4751 --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/streams/SmtpGatewayMessageSource.java @@ -0,0 +1,36 @@ +package org.nhindirect.james.server.streams; + + +import org.nhindirect.common.mail.SMTPMailMessage; +import org.nhindirect.common.mail.streams.SMTPMailMessageConverter; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.beans.factory.annotation.Qualifier; +import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.cloud.stream.annotation.Output; +import org.springframework.messaging.MessageChannel; + +@EnableBinding(SmtpGatewayMessageOutput.class) +public class SmtpGatewayMessageSource +{ + protected static SmtpGatewayMessageSource messageSourceInstance; + + @Autowired + @Qualifier(SmtpGatewayMessageOutput.SMTP_GATEWAY_MESSAGE_OUTPUT) + private MessageChannel smtpGatewayChannel; + + public SmtpGatewayMessageSource() + { + messageSourceInstance = this; + } + + @Output(SmtpGatewayMessageOutput.SMTP_GATEWAY_MESSAGE_OUTPUT) + public void forwardSMTPMessage(SMTPMailMessage msg) + { + this.smtpGatewayChannel.send(SMTPMailMessageConverter.toStreamMessage(msg)); + } + + public static SmtpGatewayMessageSource getMessageSourceInstance() + { + return messageSourceInstance; + } +} diff --git a/src/main/java/org/nhindirect/james/server/streams/sinks/STALastMileDeliverySink.java b/src/main/java/org/nhindirect/james/server/streams/sinks/STALastMileDeliverySink.java new file mode 100644 index 0000000..9c9a6e5 --- /dev/null +++ b/src/main/java/org/nhindirect/james/server/streams/sinks/STALastMileDeliverySink.java @@ -0,0 +1,71 @@ +package org.nhindirect.james.server.streams.sinks; + +import javax.mail.Address; +import javax.mail.MessagingException; +import javax.mail.internet.AddressException; +import javax.mail.internet.InternetAddress; + +import org.apache.james.core.MailAddress; +import org.apache.james.server.core.MailImpl; +import org.apache.mailet.Mail; +import org.nhindirect.common.mail.SMTPMailMessage; +import org.nhindirect.common.mail.streams.SMTPMailMessageConverter; +import org.nhindirect.james.server.mailets.StreamsTimelyAndReliableLocalDelivery; +import org.nhindirect.james.server.streams.STALastMileDeliveryInput; +import org.springframework.cloud.stream.annotation.EnableBinding; +import org.springframework.cloud.stream.annotation.StreamListener; +import org.springframework.messaging.Message; + +import com.github.fge.lambdas.Throwing; +import com.github.steveash.guavate.Guavate; +import com.google.common.base.Preconditions; +import com.google.common.collect.ImmutableList; + +@EnableBinding(STALastMileDeliveryInput.class) +public class STALastMileDeliverySink +{ + public STALastMileDeliverySink() + { + } + + @StreamListener(target = STALastMileDeliveryInput.STA_LAST_MILE_INPUT) + public void processLastMileMessage(Message streamMsg) throws MessagingException + { + /* + * This blocks the processing of messages until the mailet instance has been created + */ + synchronized(StreamsTimelyAndReliableLocalDelivery.class) + { + if (StreamsTimelyAndReliableLocalDelivery.getStaticMailet() == null) + { + try + { + STALastMileDeliverySink.class.wait(); + } + catch (InterruptedException e) {/* no-op */} + } + } + + /* + * Create the MAIL message and send it on to the mailet. + */ + final SMTPMailMessage smtpMessage = SMTPMailMessageConverter.fromStreamMessage(streamMsg); + + final ImmutableList recips = smtpMessage.getRecipientAddresses().stream() + .map(Throwing.function(STALastMileDeliverySink::castToMailAddress).sneakyThrow()) + .collect(Guavate.toImmutableList()); + + final Mail mail = MailImpl.builder() + .sender(new MailAddress(smtpMessage.getMailFrom())) + .recipients(recips) + .mimeMessage(smtpMessage.getMimeMessage()).build(); + + StreamsTimelyAndReliableLocalDelivery.getStaticMailet().service(mail); + } + + protected static MailAddress castToMailAddress(Address address) throws AddressException + { + Preconditions.checkArgument(address instanceof InternetAddress); + return new MailAddress((InternetAddress) address); + } +} diff --git a/src/main/resources/application.yml b/src/main/resources/application.yml new file mode 100644 index 0000000..9019d56 --- /dev/null +++ b/src/main/resources/application.yml @@ -0,0 +1,25 @@ +#Default the security credentials to call the config service. Override these +#for your deployment. +direct: + webservices: + security: + basic: + user: + name: admin + password: d1r3ct; + +spring: + cloud: + stream: + bindings: + direct-sta-last-mile-input: + destination: direct-sta-last-mile-delivery + group: direct-sta-last-mile-delivery-group + consumer: + concurrency: 10 + maxAttempts: 4 + backOffInitialInterval: 15000 + backOffMaxInterval: 60000 + + direct-smtp-mq-gateway: + destination: direct-smtp-mq-gateway diff --git a/src/main/resources/bootstrap.yml b/src/main/resources/bootstrap.yml new file mode 100644 index 0000000..269dfd2 --- /dev/null +++ b/src/main/resources/bootstrap.yml @@ -0,0 +1,34 @@ +spring: + datasource: + driver-class-name: org.apache.derby.jdbc.EmbeddedDriver + url: jdbc:derby:./var/store/derby;create=true + username: app + password: app + adapter: DERBY + streaming: false +#If using an MQ server that is not auto bound, the setting for the MQ service should go here. +#These place holders assume RabbitMQ is being used. Systems such as CloudFoundry may support binding +#RabbitMQ directly. + +# rabbitmq: +# host: +# port: +# username: +# password: +# virtual-host: + application: + name: direct-james-server + main: + allow-bean-definition-overriding: true + +eureka: + client: + enabled: false + +#If not using Eureka, then set the config-service URL. This should be set to a empty value +#if you are using Eureka +direct: + config: + service: + url: http://localhost:8080/config-service + diff --git a/src/main/resources/properties/domainlist.xml b/src/main/resources/properties/domainlist.xml new file mode 100644 index 0000000..ea70b1f --- /dev/null +++ b/src/main/resources/properties/domainlist.xml @@ -0,0 +1,28 @@ + + + + + + ${domainnames} + + false + false + ${defaultdomain} + diff --git a/src/main/resources/properties/imapserver.xml b/src/main/resources/properties/imapserver.xml new file mode 100644 index 0000000..1227fa6 --- /dev/null +++ b/src/main/resources/properties/imapserver.xml @@ -0,0 +1,82 @@ + + + + + + + + + + + + + + + imapserver + + + + + + + 0.0.0.0:1143 + + 200 + + + + + + + + + + + + + + + + + + + 0 + + + 0 + + + + + + diff --git a/src/main/resources/properties/james-database.properties b/src/main/resources/properties/james-database.properties new file mode 100644 index 0000000..b30c774 --- /dev/null +++ b/src/main/resources/properties/james-database.properties @@ -0,0 +1,11 @@ + +database.driverClassName=${driver} +database.url=${url} +database.username=${username} +database.password=${password} + +# Supported adapters are: +# DB2, DERBY, H2, HSQL, INFORMIX, MYSQL, ORACLE, POSTGRESQL, SQL_SERVER, SYBASE +vendorAdapter.database=${dbadapter} + +openjpa.streaming=${streaming} diff --git a/src/main/resources/properties/mailetcontainer.out.xml b/src/main/resources/properties/mailetcontainer.out.xml new file mode 100644 index 0000000..e69de29 diff --git a/src/main/resources/properties/mailetcontainer.xml b/src/main/resources/properties/mailetcontainer.xml new file mode 100644 index 0000000..d966f86 --- /dev/null +++ b/src/main/resources/properties/mailetcontainer.xml @@ -0,0 +1,121 @@ + + + + + + + + postmaster@james.minet.net + + + + 20 + + + + + + + + transport + + + + + + mailetContainerErrors + + + + + + + + + + + + + bcc + ignore + + + rrt-error + + + + + + + relay + + + + + + outgoing + 5000, 100000, 500000 + 25 + 0 + 10 + true + bounces + + + + + + mailetContainerLocalAddressError + + + none + + + + + + mailetContainerRelayDenied + + + none + + + + + + bounces + + + false + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/src/main/resources/properties/pop3server.xml b/src/main/resources/properties/pop3server.xml new file mode 100644 index 0000000..9b05666 --- /dev/null +++ b/src/main/resources/properties/pop3server.xml @@ -0,0 +1,44 @@ + + + + + + + pop3server + 0.0.0.0:1110 + 200 + + + + + 1200 + 0 + 0 + + + + + diff --git a/src/main/resources/properties/smtpserver.xml b/src/main/resources/properties/smtpserver.xml new file mode 100644 index 0000000..8e046f2 --- /dev/null +++ b/src/main/resources/properties/smtpserver.xml @@ -0,0 +1,81 @@ + + + + + + + smtpserver-global + 0.0.0.0:1025 + 200 + + + + 360 + 0 + 0 + false + 127.0.0.0/8 + true + 0 + true + DirectProject SMTP Server + + + + + + + smtpserver-authenticated + 0.0.0.0:1587 + 200 + + + + 360 + 0 + 0 + + true + 127.0.0.0/8 + + false + 0 + true + DirectProject SMTP Server + + + + + + + + diff --git a/src/main/resources/properties/webadmin.properties b/src/main/resources/properties/webadmin.properties new file mode 100644 index 0000000..0567c01 --- /dev/null +++ b/src/main/resources/properties/webadmin.properties @@ -0,0 +1,9 @@ +enabled=${enabled} +port=${port} +username=${username} +password=${password} +https.enabled=${httpsEnabled} +https.keystore=${keystore} +https.password=${keystorePassword} +https.trust.keystore=${trustKeystore} +https.trust.password=${trustPassword} From 7f86b40630401d6657f4f98a24eabd39e3af32c7 Mon Sep 17 00:00:00 2001 From: gm2552 Date: Thu, 21 Mar 2019 08:43:54 -0500 Subject: [PATCH 2/2] Adding ability to config protocol service parameters (SMTP, IMAP,etc). Also adding DSN and MDN Dispatched messages for local delivery in compliance with the implementation guide for delivery notification. --- pom.xml | 78 +++------ .../james/server/mailets/MailUtils.java | 127 +++++++++++++++ ...StreamsTimelyAndReliableLocalDelivery.java | 99 +++++++++++- .../server/mailets/ToStaAgentStream.java | 42 +---- .../server/spring/DSNCreatorFactory.java | 27 ++++ .../server/spring/JamesServerConfig.java | 152 ++++++++++++++++-- .../sinks/STALastMileDeliverySink.java | 14 +- src/main/resources/application.yml | 32 ++-- src/main/resources/bootstrap.yml | 22 ++- src/main/resources/properties/imapserver.xml | 8 +- src/main/resources/properties/keystore | Bin 0 -> 2239 bytes src/main/resources/properties/pop3server.xml | 12 +- src/main/resources/properties/smtpserver.xml | 15 +- 13 files changed, 459 insertions(+), 169 deletions(-) create mode 100644 src/main/java/org/nhindirect/james/server/mailets/MailUtils.java create mode 100644 src/main/java/org/nhindirect/james/server/spring/DSNCreatorFactory.java create mode 100644 src/main/resources/properties/keystore diff --git a/pom.xml b/pom.xml index ddb721a..dc1d6fd 100644 --- a/pom.xml +++ b/pom.xml @@ -37,14 +37,7 @@ New BSD License http://nhindirect.org/BSDLicense - - - - spring-milestone - Spring Milestone Releases - https://repo.spring.io/milestone/ - - + UTF-8 @@ -80,49 +73,7 @@ io.dropwizard.metrics metrics-jvm 3.2.6 - - + @@ -170,23 +121,23 @@ config-service-client 6.0 - + org.apache.james james-server-jpa-guice @@ -372,7 +323,16 @@ org.springframework.boot spring-boot-maven-plugin - + + + org.springframework.boot + spring-boot-maven-plugin + + + -Xdebug -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=5005 + + + - 0.0.0.0:1143 + ${bind}:${port} 200 - + - diff --git a/src/main/resources/properties/keystore b/src/main/resources/properties/keystore new file mode 100644 index 0000000000000000000000000000000000000000..84758f8147b9bbab7b47a706e5e7b2b96c113781 GIT binary patch literal 2239 zcmchYS5VX28pZQZp-Kyofb?dNW)g}44H9}s1QbG1YUstN5Rn#@b`X&+5J9*|KrnzB zYA7O2ks?KG02l~Lg?^5W2!@&qOdGAh@1-Bjl1_P` z&pOjQiEN2P*_!f)%r*zL@$|(lWrRGR;4P7+UUAo2xytXU z;wB^ppyC5r^l05;_i#*tX8SZ2 zQ5|%6CwgSC$FKK=zWB@Q9-?Vw>5!L!OXopHxC#R5)Mu9I9}JZre^I$*zLu=WIyF@> z`JSYDR?D-9$JeAj;^>OLzp?S}7TiMdQ-b?y4;>2C)=9YG(6 z_&rnjEzpMVhS~`^8<_6efbuT8K-!tCr3b*x04uh(5Xf1S= zXXPyG8BOKYZXPxbau&*{b2=sadyC1U%a2#wcM^J0Ej3};9`!%)p?&cKJhVI|SVGfd zI%>gc!c||j+CBeBplHHbtfK^R62#K!w|O3BT)tyQB9r_JKtYI*eySF#i2fm2BJ}~- zgk`!mA_H|c`Sm_L_?F%+k&#P{QbQiy;5Lm;!@l2Y?WZz+!pdpLBv+1+*{Rr?;yaJh z&$U=A-(HDnG%KEZ*4muoRGM2xbo&;)35stiRR`f^xMs;BmlR&k0Khf6F7T3b zuDnJ^w+kxbEG;Gk7OA|N%FU)>-w85SW0zUYIGi9yt}s1_@FwMM%v3{#S~rt3XT(1d zJRoV(f1Kjs=pr6;%=@Kl&Q3#HyB&9pIYxOuTjnd8X|R;(xqMzx&zfVThqt;b=8`ch zY43NZW4cYU_cH=)k@52bmjkU0HgReV^)YiZ=zpcy>ufL;x~rc`sl8oYxSAb%P6!Fx z(DN)S9n)4lttw*8j9F~o&CPh>C$u@`ELP;ji0i6bI?ELvJ`YWwvd?>wj4Im7D2ZH42}no$QKDbn!Cks#JE?k=;oUfCzi!^q5oty^ zIOw^uf_J00DDNd9a4hX1dnBQV68gfZOG}lo7u&ZJh&!4X{T(snCvUj0q0`0_1}l7H zeOeSNf07x+eG(zs`qNSG!V?XXZy&E21&kh_yPji{8}Lo?xr+?()U<;5+`2pSi7$85 zEB8;{9=;csz2%xj#8M1JI>WtsV|6+fk}H&~%>97Zgb5F?2+RJJ!9Q!!SwkDG3j#qX zXe#6~nhJI=fq(%p7^;b`Y(w*LaH}MmCvNir057{RgD`^Z!h|?MIfOZ#LW4rXB18Wo zT>l`P{~$d7BLZw|whyl`hjG9~U++tQ*+Bk#1TBr^!{9I&j3x$$Mq|)Kw$w#q+2Bw4 z|Gf+qkpFua>`eio0s`z60`P#T005%)U~SCjb&|)*$-S88aYMS0pC5oRF{B)x0Xh``7vU9|NRP5p%p(dtvbR&avxFSV`IiZj$qZoOn z-=Qz&f#kOqcT{RG|K(5HBO(f6?@JL{!%eL56DIshU4!p@^T=1Zbb=8&SMCZcEBRY9 z*8B7Z55LvDZMlCxOW?vAiH5IC42)NO^y7V5hai-TTJ1H;W=L|KfK8)9OUW)h1N0QP zY)V*fmiPO#O4*w>Fdv-P<~@!iZg)!CF(ta`!u

jTIG=}L2mk`griVEsjj?opd_2vZW(*{j1^0c#eCn%DXMQ1IE?k|W4W zOE*!M&yRR#u<(@`rw!KXhW;*+bKF?R1LdCQUy=PrE-;NlmbI%qdkao1^<9nd6b+&$ zgiC&hC)mdJKu3aU-jUy4DL_7qtlm$e{kr%f!rOFz_NvqjYk_ntEjn&U_DoY>p@1Ip z3J^AyyMO-7I5NlQ$47EKK5CdN{Gh*76!=-1bdNCyzk83wRB?Z}l;)U6lw}m;5913D iM&T!uo5h{C@+O+r3c$ literal 0 HcmV?d00001 diff --git a/src/main/resources/properties/pop3server.xml b/src/main/resources/properties/pop3server.xml index 9b05666..6b5d691 100644 --- a/src/main/resources/properties/pop3server.xml +++ b/src/main/resources/properties/pop3server.xml @@ -20,19 +20,17 @@ - + pop3server - 0.0.0.0:1110 + ${bind}:${port} 200 - + - 1200 0 diff --git a/src/main/resources/properties/smtpserver.xml b/src/main/resources/properties/smtpserver.xml index 8e046f2..17afbea 100644 --- a/src/main/resources/properties/smtpserver.xml +++ b/src/main/resources/properties/smtpserver.xml @@ -20,7 +20,7 @@ --> - + smtpserver-global 0.0.0.0:1025 200 @@ -48,15 +48,14 @@ smtpserver-authenticated - 0.0.0.0:1587 + ${bind}:${port} 200 - - + 360 0 @@ -65,7 +64,7 @@ Authorize only local users --> true - 127.0.0.0/8 + ${authAddresses} false 0