Spring Integration mail
I'm working more and more often with Spring Integration and I find it great. The only problem is that most of the basic examples are based on the XML configuration and my projects are more annotation/dsl oriented.
This is the first of a series of demos about some use cases of Spring Integration. The examples will be integrated in the javademo.io website.
As usual the goal of these articles is to remember how to implement the solution in the future (it's kind of funny to look for a solution on the web and find your own article written 4 or 5 year before).
For an extensive documentation you can look in the spring.io website/source code.
Where is the code
https://github.com/marco76/spring-integration-demo
To run the code you can start the unit tests, they simulate a smtp server and they submit some MailMessages to Spring Integration.
Annotations: EmailTest.java
DSL: EmailDslTest.java:
Send a mail using annotations
We define a JavaMailSender bean in the configuration that connect to the mailserver.
@Configuration
@PropertySource("classpath:/smtp.properties")
public class MailConfig {
@Value("${smtp.host}")
private String smptHost;
@Value("${smtp.port}")
private Integer smtpPort;
@Bean
public JavaMailSenderImpl mailSender() {
JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
mailSender.setHost(smptHost);
mailSender.setPort(smtpPort);
return mailSender;
}
We create the channel that will receive an email and we use a @ServiceActivator to send the email to the smtp.
@Bean
public MessageChannel smtpChannel() {
return new DirectChannel();
}
@ServiceActivator(inputChannel = "smtpChannel", outputChannel = "nullChannel")
public MessageHandler mailsSenderMessagingHandler (Message<MailMessage> message) {
MailSendingMessageHandler mailSendingMessageHandler =
new MailSendingMessageHandler(mailSender());
mailSendingMessageHandler.handleMessage(message);
return mailSendingMessageHandler;
}
We declare explicitly a channel (smtpChannel) that receives the messages to send. This is optional, if you don't create the bean Spring will do it for you.
We use a MailSendingMessageHandler to send the message.
As you can see it does a lot of magic, it receives a Message, if the payload of the message is a MailMessage this one is passed to the smtp server.
You can see how the class is used in the test class EmailTest.java
@RunWith(SpringRunner.class)
@ContextConfiguration(classes = {IntegrationConfig.class, MailConfig.class})
public class EmailTest {
@Autowired
MessageChannel smtpChannel;
@Test
public void mailsend() throws IOException {
SimpleSmtpServer mailServer = SimpleSmtpServer.start(12345);
smtpChannel.send(new GenericMessage<>(buildMailMessage("Test 1", "content 1")));
smtpChannel.send(new GenericMessage<>(buildMailMessage("Test 2", "content 2")));
mailServer.stop();
List<SmtpMessage> messagesSent = mailServer.getReceivedEmails();
assertEquals(2, messagesSent.size());
}
private MailMessage buildMailMessage(String subject, String content){
MailMessage mailMessage = new SimpleMailMessage();
mailMessage.setTo("marco.molteni@j.ch");
mailMessage.setFrom("marco@j.ch");
mailMessage.setText(content);
mailMessage.setSubject(subject);
return mailMessage;
}
}
To simulate the server we use com.dumbster.smtp.SimpleSmtpServer;
, the library simulates a local mail server and records the messages sent.
To send the mail message in the channel it's enough to send a MailMessage in an integration Message. Spring automatically read the payload of the integration's message and send it.
Send a message using DSL
If you want to use some code that is better suited for your lambda expressions, you can use Spring Integration DSL. Since the version 5.0 of Spring integration the DSL is integrated in Integration Core.
@Bean
public IntegrationFlow smtpFlow() {
return IntegrationFlows.from("smtpFlowChannel")
.handle(new MailSendingMessageHandler(mailSender()))
.get();
}
The smtpFlowChannel
is created directly by Spring because there are no channels configured with this name.
The message received is sent to the Mail handler.
To use this code EmailDslTest.java:
@Autowired
MessageChannel smtpFlowChannel;
@Test
public void mailsend() throws IOException {
SimpleSmtpServer mailServer = SimpleSmtpServer.start(12345);
smtpFlowChannel.send(new GenericMessage<>(buildMailMessage("Test 2", "content 1")));
Spring configuration
Don't forget to declare that your project is using Spring integration or Spring won't find your interfaces.
@EnableIntegration
@IntegrationComponentScan
public class IntegrationConfig {
}
Maven
Dumbster as fake smtp:
<dependency>
<groupId>com.github.kirviq</groupId>
<artifactId>dumbster</artifactId>
<version>1.7.1</version>
<scope>test</scope>
</dependency>
JavaMail:
<dependency>
<groupId>javax.mail</groupId>
<artifactId>mail</artifactId>
<version>1.4</version>
</dependency>
Spring dependencies:
<dependency>
<groupId>org.springframework.integration</groupId>
<artifactId>spring-integration-mail</artifactId>
</dependency>
What's next
Everything is ready for more complicated e-mails in HTML and with attachments. If you are interested drop me a mail or open an issue on GitHub.