DSL: Mail namespace & MailSendingMessageHandler
DSL:Add SMTP Mail Server Polishing - PR Comments DSL: Mail: add `PropertiesConfigurer` lambda * Move `IntegrationFlowTests` to the `flows` package to avoid cross scanning for components * Make `MailTests` as integration test and move `Mail.outboundAdapter` to the `IntegrationFlow` `@Bean` definition
This commit is contained in:
committed by
Artem Bilan
parent
325ee9a4f3
commit
ba4f52d59c
@@ -0,0 +1,28 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.mail;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class Mail {
|
||||
|
||||
public static MailSendingMessageHandlerSpec outboundAdapter(String host) {
|
||||
return new MailSendingMessageHandlerSpec(host);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,84 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.mail;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import javax.activation.FileTypeMap;
|
||||
|
||||
import org.springframework.integration.dsl.core.MessageHandlerSpec;
|
||||
import org.springframework.integration.dsl.support.PropertiesBuilder;
|
||||
import org.springframework.integration.dsl.support.PropertiesConfigurer;
|
||||
import org.springframework.integration.mail.MailSendingMessageHandler;
|
||||
import org.springframework.mail.javamail.JavaMailSenderImpl;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public class MailSendingMessageHandlerSpec extends
|
||||
MessageHandlerSpec<MailSendingMessageHandlerSpec, MailSendingMessageHandler> {
|
||||
|
||||
private final JavaMailSenderImpl sender = new JavaMailSenderImpl();
|
||||
|
||||
MailSendingMessageHandlerSpec (String host) {
|
||||
this.sender.setHost(host);
|
||||
this.target = new MailSendingMessageHandler(this.sender);
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec javaMailProperties(Properties javaMailProperties) {
|
||||
this.sender.setJavaMailProperties(javaMailProperties);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec javaMailProperties(PropertiesConfigurer propertiesConfigurer) {
|
||||
PropertiesBuilder properties = new PropertiesBuilder();
|
||||
propertiesConfigurer.configure(properties);
|
||||
return javaMailProperties(properties.get());
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec protocol(String protocol) {
|
||||
this.sender.setProtocol(protocol);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec port(int port) {
|
||||
this.sender.setPort(port);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec credentials(String username, String password) {
|
||||
this.sender.setUsername(username);
|
||||
this.sender.setPassword(password);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec defaultEncoding(String defaultEncoding) {
|
||||
this.sender.setDefaultEncoding(defaultEncoding);
|
||||
return this;
|
||||
}
|
||||
|
||||
public MailSendingMessageHandlerSpec defaultFileTypeMap(FileTypeMap defaultFileTypeMap) {
|
||||
this.sender.setDefaultFileTypeMap(defaultFileTypeMap);
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected MailSendingMessageHandler doGet() {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
/**
|
||||
* Provides Mail Components support for Spring Integration Java DSL.
|
||||
*/
|
||||
package org.springframework.integration.dsl.mail;
|
||||
@@ -0,0 +1,38 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.support;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class PropertiesBuilder {
|
||||
|
||||
private final Properties properties = new Properties();
|
||||
|
||||
public PropertiesBuilder put(Object key, Object value) {
|
||||
properties.put(key, value);
|
||||
return this;
|
||||
}
|
||||
|
||||
public Properties get() {
|
||||
return this.properties;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.support;
|
||||
|
||||
/**
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
public interface PropertiesConfigurer {
|
||||
|
||||
void configure(PropertiesBuilder propertiesBuilder);
|
||||
|
||||
}
|
||||
@@ -14,7 +14,7 @@
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package org.springframework.integration.dsl.test;
|
||||
package org.springframework.integration.dsl.test.flows;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
@@ -86,6 +86,7 @@ import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.ComponentScan;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.context.annotation.DependsOn;
|
||||
import org.springframework.context.annotation.Import;
|
||||
import org.springframework.data.mongodb.MongoDbFactory;
|
||||
import org.springframework.data.mongodb.core.SimpleMongoDbFactory;
|
||||
import org.springframework.integration.IntegrationMessageHeaderAccessor;
|
||||
@@ -114,6 +115,8 @@ import org.springframework.integration.dsl.jms.Jms;
|
||||
import org.springframework.integration.dsl.sftp.Sftp;
|
||||
import org.springframework.integration.dsl.support.Pollers;
|
||||
import org.springframework.integration.dsl.support.Transformers;
|
||||
import org.springframework.integration.dsl.test.TestFtpServer;
|
||||
import org.springframework.integration.dsl.test.TestSftpServer;
|
||||
import org.springframework.integration.endpoint.MethodInvokingMessageSource;
|
||||
import org.springframework.integration.event.core.MessagingEvent;
|
||||
import org.springframework.integration.event.outbound.ApplicationEventPublishingMessageHandler;
|
||||
@@ -1275,6 +1278,7 @@ public class IntegrationFlowTests {
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@Import({TestFtpServer.class, TestSftpServer.class})
|
||||
@EnableAutoConfiguration
|
||||
@IntegrationComponentScan
|
||||
public static class ContextConfiguration {
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.test.mail;
|
||||
|
||||
import static org.hamcrest.Matchers.containsString;
|
||||
import static org.hamcrest.Matchers.endsWith;
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertThat;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.util.Properties;
|
||||
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
import org.springframework.integration.config.EnableIntegration;
|
||||
import org.springframework.integration.dsl.IntegrationFlow;
|
||||
import org.springframework.integration.dsl.IntegrationFlows;
|
||||
import org.springframework.integration.dsl.mail.Mail;
|
||||
import org.springframework.integration.dsl.test.mail.PoorMansMailServer.SmtpServer;
|
||||
import org.springframework.integration.mail.MailHeaders;
|
||||
import org.springframework.integration.support.MessageBuilder;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.messaging.MessageChannel;
|
||||
import org.springframework.messaging.MessageHandler;
|
||||
import org.springframework.test.annotation.DirtiesContext;
|
||||
import org.springframework.test.context.ContextConfiguration;
|
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner;
|
||||
import org.springframework.util.SocketUtils;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
* @author Artem Bilan
|
||||
*/
|
||||
@ContextConfiguration
|
||||
@RunWith(SpringJUnit4ClassRunner.class)
|
||||
@DirtiesContext
|
||||
public class MailTests {
|
||||
|
||||
private final static int port = SocketUtils.findAvailableTcpPort();
|
||||
|
||||
private static SmtpServer server = PoorMansMailServer.smtp(port);
|
||||
|
||||
|
||||
@BeforeClass
|
||||
public static void setup() throws InterruptedException {
|
||||
int n = 0;
|
||||
while (n++ < 100 && !server.isListening()) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
assertTrue(n < 100);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDown() {
|
||||
server.stop();
|
||||
}
|
||||
|
||||
@Autowired
|
||||
@Qualifier("sendMailChannel")
|
||||
private MessageChannel sendMailChannel;
|
||||
|
||||
@Autowired
|
||||
@Qualifier("sendMailEndpoint.handler")
|
||||
private MessageHandler sendMailHandler;
|
||||
|
||||
@Test
|
||||
public void testOutbound() throws Exception {
|
||||
assertEquals("localhost", TestUtils.getPropertyValue(this.sendMailHandler, "mailSender.host"));
|
||||
|
||||
Properties javaMailProperties = TestUtils.getPropertyValue(this.sendMailHandler,
|
||||
"mailSender.javaMailProperties", Properties.class);
|
||||
assertEquals("true", javaMailProperties.getProperty("mail.debug"));
|
||||
|
||||
this.sendMailChannel.send(MessageBuilder.withPayload("foo")
|
||||
.setHeader(MailHeaders.SUBJECT, "foo")
|
||||
.setHeader(MailHeaders.FROM, "foo@bar")
|
||||
.setHeader(MailHeaders.TO, "bar@baz")
|
||||
.build());
|
||||
|
||||
int n = 0;
|
||||
while (n++ < 100 && server.getMessages().size() == 0) {
|
||||
Thread.sleep(100);
|
||||
}
|
||||
|
||||
assertTrue(server.getMessages().size() > 0);
|
||||
String message = server.getMessages().get(0);
|
||||
assertThat(message, endsWith("foo\n"));
|
||||
assertThat(message, containsString("foo@bar"));
|
||||
assertThat(message, containsString("bar@baz"));
|
||||
assertThat(message, containsString("user:user"));
|
||||
assertThat(message, containsString("password:pw"));
|
||||
|
||||
}
|
||||
|
||||
@Configuration
|
||||
@EnableIntegration
|
||||
public static class ContextConfiguration {
|
||||
|
||||
@Bean
|
||||
public IntegrationFlow sendMailFlow() {
|
||||
return IntegrationFlows.from("sendMailChannel")
|
||||
.handle(Mail.outboundAdapter("localhost")
|
||||
.port(port)
|
||||
.credentials("user", "pw")
|
||||
.protocol("smtp")
|
||||
.javaMailProperties(p -> p.put("mail.debug", "true")),
|
||||
e -> e.id("sendMailEndpoint"))
|
||||
.get();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,177 @@
|
||||
/*
|
||||
* Copyright 2014 the original author or authors.
|
||||
*
|
||||
* Licensed 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.springframework.integration.dsl.test.mail;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.BufferedWriter;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.net.ServerSocket;
|
||||
import java.net.Socket;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
import java.util.concurrent.ExecutorService;
|
||||
import java.util.concurrent.Executors;
|
||||
|
||||
import javax.net.ServerSocketFactory;
|
||||
|
||||
import org.apache.sshd.common.util.Base64;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
*
|
||||
*/
|
||||
public class PoorMansMailServer {
|
||||
|
||||
public static SmtpServer smtp(int port) {
|
||||
try {
|
||||
return new SmtpServer(port);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new RuntimeException(e);
|
||||
}
|
||||
}
|
||||
|
||||
public static class SmtpServer implements Runnable {
|
||||
|
||||
private final ServerSocket socket;
|
||||
|
||||
private final ExecutorService exec = Executors.newCachedThreadPool();
|
||||
|
||||
private final List<String> messages = new ArrayList<String>();
|
||||
|
||||
private volatile boolean listening;
|
||||
|
||||
public SmtpServer(int port) throws IOException {
|
||||
this.socket = ServerSocketFactory.getDefault().createServerSocket(port);
|
||||
this.listening = true;
|
||||
exec.execute(this);
|
||||
}
|
||||
|
||||
public boolean isListening() {
|
||||
return listening;
|
||||
}
|
||||
|
||||
public List<String> getMessages() {
|
||||
return messages;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
while (!socket.isClosed()) {
|
||||
Socket socket = this.socket.accept();
|
||||
exec.execute(new SmtpHandler(socket));
|
||||
}
|
||||
}
|
||||
catch (IOException e) {
|
||||
this.listening = false;
|
||||
}
|
||||
}
|
||||
|
||||
public void stop() {
|
||||
try {
|
||||
this.socket.close();
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
this.exec.shutdownNow();
|
||||
}
|
||||
|
||||
public class SmtpHandler implements Runnable {
|
||||
|
||||
private final Socket socket;
|
||||
|
||||
private BufferedWriter writer;
|
||||
|
||||
public SmtpHandler(Socket socket) {
|
||||
this.socket = socket;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run() {
|
||||
try {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
BufferedReader reader = new BufferedReader(new InputStreamReader(this.socket.getInputStream()));
|
||||
this.writer = new BufferedWriter(new OutputStreamWriter(this.socket.getOutputStream()));
|
||||
write("220 foo SMTP");
|
||||
while (!socket.isClosed()) {
|
||||
String line = reader.readLine();
|
||||
if (line.contains("EHLO")) {
|
||||
write("250-foo hello [0,0,0,0], foo");
|
||||
write("250-AUTH LOGIN PLAIN");
|
||||
write("250 OK");
|
||||
}
|
||||
else if (line.contains("MAIL FROM")) {
|
||||
write("250 OK");
|
||||
}
|
||||
else if (line.contains("RCPT TO")) {
|
||||
write("250 OK");
|
||||
}
|
||||
else if (line.contains("AUTH LOGIN")) {
|
||||
write("334 VXNlcm5hbWU6");
|
||||
}
|
||||
else if (line.contains("dXNlcg==")) { // base64 'user'
|
||||
sb.append("user:");
|
||||
sb.append((new String(new Base64().decode(line.getBytes()))));
|
||||
sb.append("\n");
|
||||
write("334 UGFzc3dvcmQ6");
|
||||
}
|
||||
else if (line.contains("cHc=")) { // base64 'pw'
|
||||
sb.append("password:");
|
||||
sb.append((new String(new Base64().decode(line.getBytes()))));
|
||||
sb.append("\n");
|
||||
write("235");
|
||||
}
|
||||
else if (line.equals("DATA")) {
|
||||
write("354");
|
||||
}
|
||||
else if (line.equals(".")) {
|
||||
write("250");
|
||||
}
|
||||
else if (line.equals("QUIT")) {
|
||||
write("221");
|
||||
socket.close();
|
||||
}
|
||||
else {
|
||||
sb.append(line);
|
||||
sb.append("\n");
|
||||
}
|
||||
}
|
||||
messages.add(sb.toString());
|
||||
}
|
||||
catch (IOException e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
|
||||
private void write(String str) throws IOException {
|
||||
this.writer.write(str);
|
||||
this.writer.write("\r\n");
|
||||
this.writer.flush();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
private PoorMansMailServer() {
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user