diff --git a/intermediate/mail-attachments/README.md b/intermediate/mail-attachments/README.md
new file mode 100644
index 00000000..5e71a4a9
--- /dev/null
+++ b/intermediate/mail-attachments/README.md
@@ -0,0 +1,41 @@
+Spring Integration - Processing Email Attachments Sample
+========================================================
+
+# Overview
+
+This example demonstrates how emails including their attachments can be processed using Spring Integration. This sample uses the following Spring Integration components:
+
+* Mail Inbound Channel Adapter
+* Chain
+* Transformer
+* Splitter
+* File Outbound Channel Adapter
+
+# Getting Started
+
+In order to use this sample you must have access to a mail-server. You can either use an external server (e.g. GMail) or you can also easily setup your own mail server using Apache James 3.0 (http://james.apache.org/). You can find instructions for setting up a basic instance at:
+
+* http://james.apache.org/server/3/quick-start.html
+* http://hillert.blogspot.com/2011/05/testing-email-notifications-with-apache.html
+
+In **src/main/resources/META-INF/spring/integration/spring-integration-context.xml** change the following to reflect the settings for your mail server.
+
+ store-uri="imap://test:test@localhost:143/INBOX"
+
+Lastly, before you run the example, please make sure that your email inbox contains some messages.
+
+You can run this sample by either.
+
+* running the "Main" class from within STS (Right-click on Main class --> Run As --> Java Application)
+* or from the command line:
+ - mvn package
+ - mvn exec:java
+
+Once started, the configured mail server will be polled for new email messages every 5 seconds.
+
+--------------------------------------------------------------------------------
+
+For help please take a look at the Spring Integration documentation:
+
+http://www.springsource.org/spring-integration
+
diff --git a/intermediate/mail-attachments/pom.xml b/intermediate/mail-attachments/pom.xml
new file mode 100644
index 00000000..504c8451
--- /dev/null
+++ b/intermediate/mail-attachments/pom.xml
@@ -0,0 +1,103 @@
+
+ 4.0.0
+ org.springframework.integration.samples
+ mail-attachments
+ Samples (Intermediate) - Mail Attachment Demo
+ 2.2.0.BUILD-SNAPSHOT
+
+
+ UTF-8
+ 2.2.0.RC1
+ 1.2.17
+ 4.10
+
+
+
+ 2.2.1
+
+
+
+
+ org.springframework.integration
+ spring-integration-mail
+ ${spring.integration.version}
+
+
+ org.springframework.integration
+ spring-integration-file
+ ${spring.integration.version}
+
+
+ javax.activation
+ activation
+ 1.1.1
+
+
+ javax.mail
+ mail
+ 1.4.5
+
+
+ commons-io
+ commons-io
+ 2.4
+
+
+
+ junit
+ junit
+ ${junit.version}
+ test
+
+
+ org.springframework
+ spring-test
+ 3.1.1.RELEASE
+ test
+
+
+ org.subethamail
+ subethasmtp-wiser
+ 1.2
+ test
+
+
+
+ log4j
+ log4j
+ ${log4j.version}
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 2.5.1
+
+ 1.6
+ 1.6
+ -Xlint:all
+ true
+ true
+
+
+
+ org.codehaus.mojo
+ exec-maven-plugin
+ 1.2.1
+
+ org.springframework.integration.samples.mailattachments.Main
+
+
+
+
+
+
+ repo.springsource.org.milestone
+ Spring Framework Maven Milestone Repository
+ https://repo.springsource.org/libs-milestone
+
+
+
diff --git a/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/Main.java b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/Main.java
new file mode 100644
index 00000000..795c7990
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/Main.java
@@ -0,0 +1,84 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments;
+
+import java.util.Scanner;
+
+import org.apache.log4j.Logger;
+import org.springframework.context.support.AbstractApplicationContext;
+import org.springframework.context.support.ClassPathXmlApplicationContext;
+
+/**
+ * Starts the Spring Context and will initialize the Spring Integration routes.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ *
+ */
+public final class Main {
+
+ private static final Logger LOGGER = Logger.getLogger(Main.class);
+
+ private static final String HORIZONTAL_LINE =
+ "\n=========================================================";
+
+ private Main() { }
+
+ /**
+ * Load the Spring Integration Application Context
+ *
+ * @param args - command line arguments
+ */
+ public static void main(final String... args) {
+
+ LOGGER.info(HORIZONTAL_LINE
+ + "\n"
+ + "\n Welcome to Spring Integration! "
+ + "\n"
+ + "\n For more information please visit: "
+ + "\n http://www.springsource.org/spring-integration "
+ + "\n"
+ + HORIZONTAL_LINE );
+
+ final AbstractApplicationContext context =
+ new ClassPathXmlApplicationContext("classpath:META-INF/spring/integration/*-context.xml");
+
+ context.registerShutdownHook();
+
+ final Scanner scanner = new Scanner(System.in);
+
+ LOGGER.info(HORIZONTAL_LINE
+ + "\n"
+ + "\n Please press 'q + Enter' to quit the application. "
+ + "\n"
+ + HORIZONTAL_LINE );
+
+ while (true) {
+
+ final String input = scanner.nextLine();
+
+ if("q".equals(input.trim())) {
+ break;
+ }
+
+ }
+
+ LOGGER.info("Exiting application...bye.");
+
+ System.exit(0);
+
+ }
+}
diff --git a/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailFragment.java b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailFragment.java
new file mode 100644
index 00000000..1784e2b2
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailFragment.java
@@ -0,0 +1,129 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments.support;
+
+import java.io.File;
+
+import org.springframework.util.Assert;
+
+/**
+ * Represents a part of the original email messsage. EmailFragments could be either
+ * Email messages themselves or also attachments. The sample will use {@link EmailFragment}s
+ * to ultimately write the various pieces that constitute an email message out to
+ * the file system.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ *
+ */
+public class EmailFragment {
+
+ private Object data;
+ private String filename;
+ private File directory;
+
+ /**
+ * Constructor.
+ *
+ * @param directory Must not be null
+ * @param filename Must not be null
+ * @param data Must not be null
+ */
+ public EmailFragment(File directory, String filename, Object data) {
+ super();
+
+ Assert.notNull(directory);
+ Assert.hasText(filename);
+ Assert.notNull(data);
+
+ this.directory = directory;
+ this.filename = filename;
+ this.data = data;
+ }
+
+ /**
+ * The data to save to the file system, e.g. text messages/attachments, binary
+ * file attachments etc.
+ */
+ public Object getData() {
+ return data;
+ }
+
+ /**
+ * The file name to create for the respective {@link EmailFragment}.
+ */
+ public String getFilename() {
+ return filename;
+ }
+
+ /**
+ * The directory where to store the {@link #getData()} using the specified
+ * {@link #getFilename()}.
+ *
+ */
+ public File getDirectory() {
+ return this.directory;
+ }
+
+ @Override
+ public int hashCode() {
+ final int prime = 31;
+ int result = 1;
+ result = prime * result
+ + ((directory == null) ? 0 : directory.hashCode());
+ result = prime * result
+ + ((filename == null) ? 0 : filename.hashCode());
+ return result;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (this == obj) {
+ return true;
+ }
+ if (obj == null) {
+ return false;
+ }
+ if (getClass() != obj.getClass()) {
+ return false;
+ }
+ EmailFragment other = (EmailFragment) obj;
+ if (directory == null) {
+ if (other.directory != null) {
+ return false;
+ }
+ }
+ else if (!directory.equals(other.directory)) {
+ return false;
+ }
+ if (filename == null) {
+ if (other.filename != null) {
+ return false;
+ }
+ }
+ else if (!filename.equals(other.filename)) {
+ return false;
+ }
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return "EmailFragment [filename=" + filename + ", directory="
+ + directory + "]";
+ }
+
+}
diff --git a/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailParserUtils.java b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailParserUtils.java
new file mode 100644
index 00000000..33d001a5
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailParserUtils.java
@@ -0,0 +1,258 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments.support;
+
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+import javax.mail.BodyPart;
+import javax.mail.MessagingException;
+import javax.mail.Multipart;
+import javax.mail.Part;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.MimeBodyPart;
+import javax.mail.internet.ParseException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.springframework.util.Assert;
+
+/**
+ * Utility Class for parsing mail messages.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ *
+ */
+public final class EmailParserUtils {
+
+ private static final Logger LOGGER = Logger.getLogger(EmailParserUtils.class);
+
+ /** Prevent instantiation. */
+ private EmailParserUtils() {
+ throw new AssertionError();
+ }
+
+ /**
+ * Parses a mail message. The respective message can either be the root message
+ * or another message that is attached to another message.
+ *
+ * If the mail message is an instance of {@link String}, then a {@link EmailFragment}
+ * is being created using the email message's subject line as the file name,
+ * which will contain the mail message's content.
+ *
+ * If the mail message is an instance of {@link Multipart} then we delegate
+ * to {@link #handleMultipart(File, Multipart, javax.mail.Message, List)}.
+ *
+ * @param directory The directory for storing the message. If null this is the root message.
+ * @param mailMessage The mail message to be parsed. Must not be null.
+ * @param emailFragments Must not be null.
+ */
+ public static void handleMessage(final File directory,
+ final javax.mail.Message mailMessage,
+ final List emailFragments) {
+
+ Assert.notNull(mailMessage, "The mail message to be parsed must not be null.");
+ Assert.notNull(emailFragments, "The collection of emailfragments must not be null.");
+
+ final Object content;
+ final String subject;
+
+ try {
+ content = mailMessage.getContent();
+ subject = mailMessage.getSubject();
+ } catch (IOException e) {
+ throw new IllegalStateException("Error while retrieving the email contents.", e);
+ } catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving the email contents.", e);
+ }
+
+ final File directoryToUse;
+
+ if (directory == null) {
+ directoryToUse = new File(subject);
+ } else {
+ directoryToUse = new File(directory, subject);
+ }
+
+ if (content instanceof String) {
+ emailFragments.add(new EmailFragment(new File(subject), "message.txt", content));
+ }
+ else if (content instanceof Multipart) {
+ Multipart multipart = (Multipart) content;
+ handleMultipart(directoryToUse, multipart, mailMessage, emailFragments);
+ }
+ else {
+ throw new IllegalStateException("This content type is not handled - " + content.getClass().getSimpleName());
+ }
+
+ }
+
+ /**
+ * Parses any {@link Multipart} instances that contain text or Html attachments,
+ * {@link InputStream} instances, additional instances of {@link Multipart}
+ * or other attached instances of {@link javax.mail.Message}.
+ *
+ * Will create the respective {@link EmailFragment}s representing those attachments.
+ *
+ * Instances of {@link javax.mail.Message} are delegated to
+ * {@link #handleMessage(File, javax.mail.Message, List)}. Further instances
+ * of {@link Multipart} are delegated to
+ * {@link #handleMultipart(File, Multipart, javax.mail.Message, List)}.
+ *
+ * @param directory Must not be null
+ * @param multipart Must not be null
+ * @param mailMessage Must not be null
+ * @param emailFragments Must not be null
+ */
+ public static void handleMultipart(File directory, Multipart multipart, javax.mail.Message mailMessage, List emailFragments) {
+
+ Assert.notNull(directory, "The directory must not be null.");
+ Assert.notNull(multipart, "The multipart object to be parsed must not be null.");
+ Assert.notNull(mailMessage, "The mail message to be parsed must not be null.");
+ Assert.notNull(emailFragments, "The collection of emailfragments must not be null.");
+
+ final int count;
+
+ try {
+ count = multipart.getCount();
+
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(String.format("Number of enclosed BodyPart objects: %s.", count));
+ }
+
+ }
+ catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving the number of enclosed BodyPart objects.", e);
+ }
+
+ for (int i = 0; i < count; i++) {
+
+ final BodyPart bp;
+
+ try {
+ bp = multipart.getBodyPart(i);
+ }
+ catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving body part.", e);
+ }
+
+ final String contentType;
+ String filename;
+ final String disposition;
+ final String subject;
+
+ try {
+
+ contentType = bp.getContentType();
+ filename = bp.getFileName();
+ disposition = bp.getDisposition();
+ subject = mailMessage.getSubject();
+
+ if (filename == null && bp instanceof MimeBodyPart) {
+ filename = ((MimeBodyPart) bp).getContentID();
+ }
+
+ }
+ catch (MessagingException e) {
+ throw new IllegalStateException("Unable to retrieve body part meta data.", e);
+ }
+
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(String.format("BodyPart - Content Type: '%s', filename: '%s', disposition: '%s', subject: '%s'",
+ new Object[]{contentType, filename, disposition, subject}));
+ }
+
+ if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
+ LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType));
+ }
+
+ final Object content;
+
+ try {
+ content = bp.getContent();
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Error while retrieving the email contents.", e);
+ }
+ catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving the email contents.", e);
+ }
+
+ if (content instanceof String) {
+
+ if (Part.ATTACHMENT.equalsIgnoreCase(disposition)) {
+ emailFragments.add(new EmailFragment(directory, i + "-" + filename, content));
+ LOGGER.info(String.format("Handdling attachment '%s', type: '%s'", filename, contentType));
+ }
+ else {
+
+ final String textFilename;
+ final ContentType ct;
+
+ try {
+ ct = new ContentType(contentType);
+ }
+ catch (ParseException e) {
+ throw new IllegalStateException("Error while parsing content type '" + contentType + "'.", e);
+ }
+
+ if ("text/plain".equalsIgnoreCase(ct.getBaseType())) {
+ textFilename = "message.txt";
+ }
+ else if ("text/html".equalsIgnoreCase(ct.getBaseType())) {
+ textFilename = "message.html";
+ }
+ else {
+ textFilename = "message.other";
+ }
+
+ emailFragments.add(new EmailFragment(directory, textFilename, content));
+ }
+
+
+ }
+ else if (content instanceof InputStream) {
+
+ final InputStream inputStream = (InputStream) content;
+ final ByteArrayOutputStream bis = new ByteArrayOutputStream();
+
+ try {
+ IOUtils.copy(inputStream, bis);
+ }
+ catch (IOException e) {
+ throw new IllegalStateException("Error while copying input stream to the ByteArrayOutputStream.", e);
+ }
+
+ emailFragments.add(new EmailFragment(directory, filename, bis.toByteArray()));
+
+ }
+ else if (content instanceof javax.mail.Message) {
+ handleMessage(directory, (javax.mail.Message) content, emailFragments);
+ }
+ else if (content instanceof Multipart) {
+ final Multipart mp2 = (Multipart) content;
+ handleMultipart(directory, mp2, mailMessage, emailFragments);
+ }
+ else {
+ throw new IllegalStateException("Content type not handled: " + content.getClass().getSimpleName());
+ }
+ }
+ }
+}
diff --git a/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailSplitter.java b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailSplitter.java
new file mode 100644
index 00000000..98a65593
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailSplitter.java
@@ -0,0 +1,52 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.springframework.integration.Message;
+import org.springframework.integration.annotation.Splitter;
+import org.springframework.integration.file.FileHeaders;
+import org.springframework.integration.support.MessageBuilder;
+
+/**
+ * Splits a {@link List} of {@link EmailFragment}s into individual Spring Integration
+ * {@link Message}s.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ *
+ */
+public class EmailSplitter {
+
+ @Splitter
+ public List> splitIntoMessages(final List emailFragments) {
+
+ final List> messages = new ArrayList>();
+
+ for (EmailFragment emailFragment : emailFragments) {
+ Message> message = MessageBuilder.withPayload(emailFragment.getData())
+ .setHeader(FileHeaders.FILENAME, emailFragment.getFilename())
+ .setHeader("directory", emailFragment.getDirectory())
+ .build();
+ messages.add(message);
+ }
+
+ return messages;
+ }
+
+}
diff --git a/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailTransformer.java b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailTransformer.java
new file mode 100644
index 00000000..dbe1599f
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/java/org/springframework/integration/samples/mailattachments/support/EmailTransformer.java
@@ -0,0 +1,50 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments.support;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.log4j.Logger;
+import org.springframework.integration.annotation.Transformer;
+
+/**
+ * Parses the E-mail Message and converts each containing message and/or attachment into
+ * a {@link List} of {@link EmailFragment}s.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ *
+ */
+public class EmailTransformer {
+
+ private static final Logger LOGGER = Logger.getLogger(EmailTransformer.class);
+
+ @Transformer
+ public List transformit(javax.mail.Message mailMessage) {
+
+ final List emailFragments = new ArrayList();
+
+ EmailParserUtils.handleMessage(null, mailMessage, emailFragments);
+
+ if (LOGGER.isInfoEnabled()) {
+ LOGGER.info(String.format("Email contains %s fragments.", emailFragments.size()));
+ }
+
+ return emailFragments;
+ }
+
+}
diff --git a/intermediate/mail-attachments/src/main/resources/META-INF/spring/integration/spring-integration-context.xml b/intermediate/mail-attachments/src/main/resources/META-INF/spring/integration/spring-integration-context.xml
new file mode 100644
index 00000000..7019a6c5
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/resources/META-INF/spring/integration/spring-integration-context.xml
@@ -0,0 +1,45 @@
+
+
+
+
+
+
+
+
+ pop3
+ false
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/intermediate/mail-attachments/src/main/resources/log4j.xml b/intermediate/mail-attachments/src/main/resources/log4j.xml
new file mode 100644
index 00000000..a78006b5
--- /dev/null
+++ b/intermediate/mail-attachments/src/main/resources/log4j.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/intermediate/mail-attachments/src/test/java/org/springframework/integration/samples/mailattachments/MimeMessageParsingTest.java b/intermediate/mail-attachments/src/test/java/org/springframework/integration/samples/mailattachments/MimeMessageParsingTest.java
new file mode 100644
index 00000000..0fa4560c
--- /dev/null
+++ b/intermediate/mail-attachments/src/test/java/org/springframework/integration/samples/mailattachments/MimeMessageParsingTest.java
@@ -0,0 +1,242 @@
+/*
+ * Copyright 2002-2012 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.samples.mailattachments;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.MimeMessage;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.log4j.Logger;
+import org.junit.After;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+import org.springframework.core.io.ByteArrayResource;
+import org.springframework.integration.samples.mailattachments.support.EmailFragment;
+import org.springframework.integration.samples.mailattachments.support.EmailParserUtils;
+import org.springframework.mail.MailParseException;
+import org.springframework.mail.javamail.JavaMailSenderImpl;
+import org.springframework.mail.javamail.MimeMessageHelper;
+import org.subethamail.wiser.Wiser;
+import org.subethamail.wiser.WiserMessage;
+
+/**
+ * Test to verify the correct parsing of Email Messages.
+ *
+ * @author Gunnar Hillert
+ * @since 2.2
+ */
+public class MimeMessageParsingTest {
+
+ private static final Logger LOGGER = Logger.getLogger(MimeMessageParsingTest.class);
+
+ private Wiser wiser;
+
+ @Before
+ public void startWiser() {
+ wiser = new Wiser();
+ wiser.setPort(2500);
+ wiser.start();
+ LOGGER.info("Wiser was started.");
+ }
+
+ /**
+ * This test will create a Mime Message that contains an Attachment, send it
+ * to an SMTP Server (Using Wiser) and retrieve and process the Mime Message.
+ *
+ * This test verifies that the parsing of the retrieved Mime Message is
+ * successful and that the correct number of {@link EmailFragment}s is created.
+ */
+ @Test
+ public void testProcessingOfEmailAttachments() {
+
+ final JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+ mailSender.setPort(2500);
+
+ final MimeMessage message = mailSender.createMimeMessage();
+ final String pictureName = "picture.png";
+
+ final ByteArrayResource byteArrayResource = getFileData(pictureName);
+
+ try {
+
+ final MimeMessageHelper helper = new MimeMessageHelper(message, true);
+
+ helper.setFrom("testfrom@springintegration.org");
+ helper.setTo("testto@springintegration.org");
+ helper.setSubject("Parsing of Attachments");
+ helper.setText("Spring Integration Rocks!");
+
+ helper.addAttachment(pictureName, byteArrayResource, "image/png");
+
+ }
+ catch (MessagingException e) {
+ throw new MailParseException(e);
+ }
+
+ mailSender.send(message);
+
+ final List wiserMessages = wiser.getMessages();
+
+ Assert.assertTrue(wiserMessages.size() == 1);
+
+ boolean foundTextMessage = false;
+ boolean foundPicture = false;
+
+ for (WiserMessage wiserMessage : wiserMessages) {
+
+ final List emailFragments = new ArrayList();
+
+ try {
+ final MimeMessage mailMessage = wiserMessage.getMimeMessage();
+ EmailParserUtils.handleMessage(null, mailMessage, emailFragments);
+ }
+ catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving Mime Message.");
+ }
+
+ Assert.assertTrue(emailFragments.size() == 2);
+
+ for (EmailFragment emailFragment : emailFragments) {
+ if ("picture.png".equals(emailFragment.getFilename())) {
+ foundPicture = true;
+ }
+
+ if ("message.txt".equals(emailFragment.getFilename())) {
+ foundTextMessage = true;
+ }
+ }
+
+ Assert.assertTrue(foundPicture);
+ Assert.assertTrue(foundTextMessage);
+
+ }
+ }
+
+ /**
+ * This test will create a Mime Message that in return contains another
+ * mime message. The nested mime message contains an attachment.
+ *
+ * The root message consist of both HTML and Text message.
+ *
+ */
+ @Test
+ public void testProcessingOfNestedEmailAttachments() {
+
+ final JavaMailSenderImpl mailSender = new JavaMailSenderImpl();
+ mailSender.setPort(2500);
+
+ final MimeMessage rootMessage = mailSender.createMimeMessage();
+
+ try {
+
+ final MimeMessageHelper messageHelper = new MimeMessageHelper(rootMessage, true);
+
+ messageHelper.setFrom("testfrom@springintegration.org");
+ messageHelper.setTo("testto@springintegration.org");
+ messageHelper.setSubject("Parsing of Attachments");
+ messageHelper.setText("Spring Integration Rocks!", "Spring Integration Rocks!");
+
+ final String pictureName = "picture.png";
+
+ final ByteArrayResource byteArrayResource = getFileData(pictureName);
+
+ messageHelper.addInline("picture12345", byteArrayResource, "image/png");
+
+ }
+ catch (MessagingException e) {
+ throw new MailParseException(e);
+ }
+
+ mailSender.send(rootMessage);
+
+ final List wiserMessages = wiser.getMessages();
+
+ Assert.assertTrue(wiserMessages.size() == 1);
+
+ boolean foundTextMessage = false;
+ boolean foundPicture = false;
+ boolean foundHtmlMessage = false;
+
+ for (WiserMessage wiserMessage : wiserMessages) {
+
+ List emailFragments = new ArrayList();
+
+ try {
+
+ final MimeMessage mailMessage = wiserMessage.getMimeMessage();
+ EmailParserUtils.handleMessage(null, mailMessage, emailFragments);
+
+ } catch (MessagingException e) {
+ throw new IllegalStateException("Error while retrieving Mime Message.");
+ }
+
+ Assert.assertTrue(emailFragments.size() == 3);
+
+ for (EmailFragment emailFragment : emailFragments) {
+ if ("".equals(emailFragment.getFilename())) {
+ foundPicture = true;
+ }
+
+ if ("message.txt".equals(emailFragment.getFilename())) {
+ foundTextMessage = true;
+ }
+
+ if ("message.html".equals(emailFragment.getFilename())) {
+ foundHtmlMessage = true;
+ }
+ }
+
+ Assert.assertTrue(foundPicture);
+ Assert.assertTrue(foundTextMessage);
+ Assert.assertTrue(foundHtmlMessage);
+
+ }
+ }
+
+ private ByteArrayResource getFileData(String filename) {
+
+ final InputStream attachmentInputStream = MimeMessageParsingTest.class.getResourceAsStream(filename);
+
+ Assert.assertNotNull("Resource not found: " + filename, attachmentInputStream);
+
+ ByteArrayResource byteArrayResource = null;
+
+ try {
+ byteArrayResource = new ByteArrayResource(IOUtils.toByteArray(attachmentInputStream));
+ attachmentInputStream.close();
+ }
+ catch (IOException e1) {
+ Assert.fail();
+ }
+
+ return byteArrayResource;
+
+ }
+
+ @After
+ public void stopWiser() {
+ wiser.stop();
+ LOGGER.info("Wiser stopped.");
+ }
+
+}
diff --git a/intermediate/mail-attachments/src/test/resources/org/springframework/integration/samples/mailattachments/picture.png b/intermediate/mail-attachments/src/test/resources/org/springframework/integration/samples/mailattachments/picture.png
new file mode 100644
index 00000000..01761ab0
Binary files /dev/null and b/intermediate/mail-attachments/src/test/resources/org/springframework/integration/samples/mailattachments/picture.png differ
diff --git a/intermediate/pom.xml b/intermediate/pom.xml
index a86b430a..5ff4ac00 100644
--- a/intermediate/pom.xml
+++ b/intermediate/pom.xml
@@ -17,6 +17,7 @@
stored-procedures-derbytcp-client-server-multiplextravel
+ mail-attachments