MAILET-142 Increase test coverage and refactor StripAttachment mailet
Project: http://git-wip-us.apache.org/repos/asf/james-project/repo Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/0e49d8c2 Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/0e49d8c2 Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/0e49d8c2 Branch: refs/heads/master Commit: 0e49d8c28c6784348999766a549551920746199e Parents: 993f444 Author: Laura Royet <[email protected]> Authored: Wed Dec 14 14:54:44 2016 +0100 Committer: Laura Royet <[email protected]> Committed: Wed Dec 21 17:02:32 2016 +0100 ---------------------------------------------------------------------- .../org/apache/mailet/base/GenericMailet.java | 35 +- .../apache/mailet/base/GenericMailetTest.java | 102 +++ mailet/pom.xml | 5 + mailet/standard/pom.xml | 5 + .../transport/mailets/StripAttachment.java | 544 ++++++----- .../james/transport/mailets/WrapText.java | 6 - .../transport/mailets/StripAttachmentTest.java | 894 ++++++++++++++----- server/mailet/integration-testing/pom.xml | 6 + .../james/mailets/utils/SMTPMessageSender.java | 25 + .../transport/mailets/StripAttachmentTest.java | 180 ++++ 10 files changed, 1347 insertions(+), 455 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java b/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java index c52a1bd..c56a226 100644 --- a/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java +++ b/mailet/base/src/main/java/org/apache/mailet/base/GenericMailet.java @@ -20,16 +20,21 @@ package org.apache.mailet.base; +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.HashSet; +import java.util.Iterator; + import javax.mail.MessagingException; +import org.apache.commons.lang.StringUtils; import org.apache.mailet.Mail; import org.apache.mailet.Mailet; import org.apache.mailet.MailetConfig; import org.apache.mailet.MailetContext; import org.apache.mailet.MailetContext.LogLevel; -import java.util.*; - /** * GenericMailet makes writing mailets easier. It provides simple * versions of the lifecycle methods init and destroy and of the methods @@ -42,6 +47,12 @@ import java.util.*; * @version 1.0.0, 24/04/1999 */ public abstract class GenericMailet implements Mailet, MailetConfig { + + private static final String YES = "yes"; + private static final String NO = "no"; + private static final String TRUE = "true"; + private static final String FALSE = "false"; + private MailetConfig config = null; /** @@ -70,7 +81,25 @@ public abstract class GenericMailet implements Mailet, MailetConfig { } return MailetUtil.getInitParameter(config, name, defaultValue); } - + + /** + * Gets a boolean valued init parameter that matches 'false', 'no', 'true' or 'yes' string values. + */ + public boolean getBooleanParameter(String value, boolean defaultValue) { + if (defaultValue) { + return !isFalseOrNo(value); + } + return isTrueOrYes(value); + } + + private static boolean isFalseOrNo(String value) { + return StringUtils.containsIgnoreCase(value, FALSE) || StringUtils.containsIgnoreCase(value, NO); + } + + private static boolean isTrueOrYes(String value) { + return StringUtils.containsIgnoreCase(value, TRUE) || StringUtils.containsIgnoreCase(value, YES); + } + /** * Returns a String containing the value of the named initialization * parameter, or null if the parameter does not exist. http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/base/src/test/java/org/apache/mailet/base/GenericMailetTest.java ---------------------------------------------------------------------- diff --git a/mailet/base/src/test/java/org/apache/mailet/base/GenericMailetTest.java b/mailet/base/src/test/java/org/apache/mailet/base/GenericMailetTest.java new file mode 100644 index 0000000..a8629eb --- /dev/null +++ b/mailet/base/src/test/java/org/apache/mailet/base/GenericMailetTest.java @@ -0,0 +1,102 @@ +/**************************************************************** + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + ****************************************************************/ + +package org.apache.mailet.base; + +import static org.assertj.core.api.Assertions.assertThat; + +import javax.mail.MessagingException; + +import org.apache.mailet.Mail; +import org.junit.Before; +import org.junit.Test; + +public class GenericMailetTest { + + private static class TestingMailet extends GenericMailet { + + @Override + public void service(Mail mail) throws MessagingException { + } + } + + private TestingMailet testee; + + @Before + public void setup() { + testee = new TestingMailet(); + } + + @Test + public void getBooleanParameterShouldReturnFalseWhenValueNullAndDefaultFalse() throws Exception { + String value = null; + boolean actual = testee.getBooleanParameter(value, false); + assertThat(actual).isFalse(); + } + + @Test + public void getBooleanParameterShouldReturnTrueWhenValueTrueAndDefaultFalse() throws Exception { + String value = "true"; + boolean actual = testee.getBooleanParameter(value, false); + assertThat(actual).isTrue(); + } + + @Test + public void getBooleanParameterShouldReturnTrueWhenValueYesAndDefaultFalse() throws Exception { + String value = "yes"; + boolean actual = testee.getBooleanParameter(value, false); + assertThat(actual).isTrue(); + } + + @Test + public void getBooleanParameterShouldReturnFalseWhenValueOtherAndDefaultFalse() throws Exception { + String value = "other"; + boolean actual = testee.getBooleanParameter(value, false); + assertThat(actual).isFalse(); + } + + @Test + public void getBooleanParameterShouldReturnTrueWhenValueNullAndDefaultTrue() throws Exception { + String value = null; + boolean actual = testee.getBooleanParameter(value, true); + assertThat(actual).isTrue(); + } + + @Test + public void getBooleanParameterShouldReturnFalseWhenValueNoAndDefaultTrue() throws Exception { + String value = "no"; + boolean actual = testee.getBooleanParameter(value, true); + assertThat(actual).isFalse(); + } + + @Test + public void getBooleanParameterShouldReturnFalseWhenValueFalseAndDefaultTrue() throws Exception { + String value = "false"; + boolean actual = testee.getBooleanParameter(value, true); + assertThat(actual).isFalse(); + } + + @Test + public void getBooleanParameterShouldReturnTrueWhenValueOtherAndDefaultTrue() throws Exception { + String value = "other"; + boolean actual = testee.getBooleanParameter(value, true); + assertThat(actual).isTrue(); + } + +} http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/pom.xml ---------------------------------------------------------------------- diff --git a/mailet/pom.xml b/mailet/pom.xml index fe212ca..368b27f 100644 --- a/mailet/pom.xml +++ b/mailet/pom.xml @@ -153,6 +153,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-guava</artifactId> + <version>1.3.1</version> + </dependency> + <dependency> <groupId>com.thoughtworks.qdox</groupId> <artifactId>qdox</artifactId> <version>${qdox.version}</version> http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/standard/pom.xml ---------------------------------------------------------------------- diff --git a/mailet/standard/pom.xml b/mailet/standard/pom.xml index 57a54d9..892ca71 100644 --- a/mailet/standard/pom.xml +++ b/mailet/standard/pom.xml @@ -77,6 +77,11 @@ <scope>test</scope> </dependency> <dependency> + <groupId>org.assertj</groupId> + <artifactId>assertj-guava</artifactId> + <scope>test</scope> + </dependency> + <dependency> <groupId>org.mockito</groupId> <artifactId>mockito-core</artifactId> <scope>test</scope> http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java ---------------------------------------------------------------------- diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java index dff16a4..e9c8592 100644 --- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java +++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/StripAttachment.java @@ -19,20 +19,21 @@ package org.apache.james.transport.mailets; -import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; -import java.io.InputStream; -import java.io.OutputStream; +import java.io.IOException; +import java.io.Serializable; +import java.io.UnsupportedEncodingException; import java.util.ArrayList; -import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; +import java.util.Locale; import java.util.Map; import java.util.regex.Pattern; +import javax.mail.BodyPart; import javax.mail.Message; import javax.mail.MessagingException; import javax.mail.Multipart; @@ -41,10 +42,16 @@ import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeUtility; import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; import org.apache.mailet.Mail; import org.apache.mailet.MailetException; import org.apache.mailet.base.GenericMailet; +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Optional; +import com.google.common.base.Strings; +import com.google.common.collect.ImmutableList; + /** * <p> * Remove attachments from a Message. Supports simple removal, storing to file, @@ -63,156 +70,159 @@ import org.apache.mailet.base.GenericMailet; * <remove >all </remove> <!-- either "no", "matched", "all" -- > * <!-- attribute>my.attribute.name</attribute --> * </mailet > + * + * At least one of pattern and notpattern is required. * </pre> * * </p> */ public class StripAttachment extends GenericMailet { + private static final String MULTIPART_MIME_TYPE = "multipart/*"; public static final String PATTERN_PARAMETER_NAME = "pattern"; - public static final String NOTPATTERN_PARAMETER_NAME = "notpattern"; - public static final String ATTRIBUTE_PARAMETER_NAME = "attribute"; - public static final String DIRECTORY_PARAMETER_NAME = "directory"; - // Either "no", "matched", "all" public static final String REMOVE_ATTACHMENT_PARAMETER_NAME = "remove"; - // Either "true", "false" public static final String DECODE_FILENAME_PARAMETER_NAME = "decodeFilename"; - public static final String REPLACE_FILENAME_PATTERN_PARAMETER_NAME = "replaceFilenamePattern"; - public static final String REMOVE_NONE = "no"; - public static final String REMOVE_ALL = "all"; - public static final String REMOVE_MATCHED = "matched"; - public static final String REMOVED_ATTACHMENTS_ATTRIBUTE_KEY = "org.apache.james.mailet.standard.mailets.StripAttachment.removed"; - public static final String SAVED_ATTACHMENTS_ATTRIBUTE_KEY = "org.apache.james.mailet.standard.mailets.StripAttachment.saved"; - private String removeAttachments = null; - - private String directoryName = null; - - private String attributeName = null; - - private Pattern regExPattern = null; - - private Pattern notregExPattern = null; + public static final boolean DECODE_FILENAME_DEFAULT_VALUE = false; - private boolean decodeFilename = false; + @VisibleForTesting String removeAttachments; + private String directoryName; + private String attributeName; + private Pattern regExPattern; + private Pattern notRegExPattern; + private boolean decodeFilename; - private List<ReplacingPattern> filenameReplacingPatterns = null; - - private static boolean getBooleanParameter(String v, boolean def) { - return def ? !(v != null && (v.equalsIgnoreCase("false") || v - .equalsIgnoreCase("no"))) : v != null - && (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes")); - } + private List<ReplacingPattern> filenameReplacingPatterns; /** * Checks if the mandatory parameters are present, creates the directory to - * save the files ni (if not present). + * save the files in (if not present). * * @throws MailetException */ + @Override public void init() throws MailetException { - String patternString = getInitParameter(PATTERN_PARAMETER_NAME); - String notpatternString = getInitParameter(NOTPATTERN_PARAMETER_NAME); - if (patternString == null && notpatternString == null) { - throw new MailetException("No value for " + PATTERN_PARAMETER_NAME - + " parameter was provided."); + regExPattern = regExFromParameter(PATTERN_PARAMETER_NAME); + notRegExPattern = regExFromParameter(NOTPATTERN_PARAMETER_NAME); + if (regExPattern == null && notRegExPattern == null) { + throw new MailetException("At least one of '" + PATTERN_PARAMETER_NAME + "' or '" + NOTPATTERN_PARAMETER_NAME + "' parameter should be provided."); } directoryName = getInitParameter(DIRECTORY_PARAMETER_NAME); attributeName = getInitParameter(ATTRIBUTE_PARAMETER_NAME); - removeAttachments = getInitParameter(REMOVE_ATTACHMENT_PARAMETER_NAME, - REMOVE_NONE).toLowerCase(); - if (!REMOVE_MATCHED.equals(removeAttachments) - && !REMOVE_ALL.equals(removeAttachments)) { - removeAttachments = REMOVE_NONE; - } - - try { - // if (patternString != null) regExPattern = new - // Perl5Compiler().compile(patternString); - if (patternString != null) - regExPattern = Pattern.compile(patternString); - } catch (Exception e) { - throw new MailetException("Could not compile regex [" - + patternString + "]."); - } - try { - // if (notpatternString != null) notregExPattern = new - // Perl5Compiler().compile(notpatternString); - if (notpatternString != null) - notregExPattern = Pattern.compile(notpatternString); - } catch (Exception e) { - throw new MailetException("Could not compile regex [" - + notpatternString + "]."); + removeAttachments = getInitParameter(REMOVE_ATTACHMENT_PARAMETER_NAME, REMOVE_NONE).toLowerCase(Locale.US); + if (!removeAttachments.equals(REMOVE_MATCHED) && !removeAttachments.equals(REMOVE_ALL) && !removeAttachments.equals(REMOVE_NONE)) { + throw new MailetException(String.format("Unknown remove parameter value '%s' waiting for '%s', '%s' or '%s'.", + removeAttachments, REMOVE_MATCHED, REMOVE_ALL, REMOVE_NONE)); } if (directoryName != null) { - try { - FileUtils.forceMkdir(new File(directoryName)); - } catch (Exception e) { - throw new MailetException("Could not create directory [" - + directoryName + "].", e); - } + createDirectory(); } - decodeFilename = getBooleanParameter( - getInitParameter(DECODE_FILENAME_PARAMETER_NAME), - decodeFilename); - if (getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME) != null) { - filenameReplacingPatterns = new PatternExtractor() - .getPatternsFromString(getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME)); + decodeFilename = getBooleanParameter(getInitParameter(DECODE_FILENAME_PARAMETER_NAME), DECODE_FILENAME_DEFAULT_VALUE); + String replaceFilenamePattern = getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME); + if (replaceFilenamePattern != null) { + filenameReplacingPatterns = new PatternExtractor().getPatternsFromString(replaceFilenamePattern); + } else { + filenameReplacingPatterns = ImmutableList.of(); } - String toLog = String.format("StripAttachment is initialised with regex pattern [%s / %s]", - patternString, notpatternString); - if (directoryName != null) { - toLog += String.format(" and will save to directory [%s]", directoryName); + logConfiguration(); + } + + private Pattern regExFromParameter(String patternParameterName) throws MailetException { + String patternString = getInitParameter(patternParameterName); + try { + if (patternString != null) { + return Pattern.compile(patternString); + } + return null; + } catch (Exception e) { + throw new MailetException("Could not compile regex [" + patternString + "]."); } - if (attributeName != null) { - toLog += String.format(" and will store attachments to attribute [%s]", attributeName); + } + + private void createDirectory() throws MailetException { + try { + FileUtils.forceMkdir(new File(directoryName)); + } catch (Exception e) { + throw new MailetException("Could not create directory [" + directoryName + "].", e); } - log(toLog); } + private void logConfiguration() { + StringBuilder logMessage = new StringBuilder(); + logMessage.append("StripAttachment is initialised with regex pattern ["); + if (regExPattern != null) { + logMessage.append(regExPattern.pattern()); + } + logMessage.append(" / "); + if (notRegExPattern != null) { + logMessage.append(notRegExPattern.pattern()); + } + logMessage.append("]"); + + if (directoryName != null) { + logMessage.append(" and will save to directory ["); + logMessage.append(directoryName); + logMessage.append("]"); + } + if (attributeName != null) { + logMessage.append(" and will store attachments to attribute ["); + logMessage.append(attributeName); + logMessage.append("]"); + } + log(logMessage.toString()); + } + /** - * Service the mail: scan it for attchemnts matching the pattern, store the - * content of a matchin attachment in the given directory. + * Service the mail: scan it for attachments matching the pattern. + * If a filename matches the pattern: + * - the file is stored (using its name) in the given directory (if directoryName is given in the mailet configuration) + * and the filename is stored in 'saved' mail list attribute + * - the part is removed (when removeAttachments mailet configuration property is 'all' or 'matched') + * and the filename is stored in 'removed' mail list attribute + * - the part filename and its content is stored in mail map attribute (if attributeName is given in the mailet configuration) * * @param mail * The mail to service * @throws MailetException * Thrown when an error situation is encountered. */ + @Override public void service(Mail mail) throws MailetException { - MimeMessage message; + MimeMessage message = getMessageFromMail(mail); + if (isMultipart(message)) { + processMultipartPartMessage(message, mail); + } + } + + private boolean isMultipart(Part part) throws MailetException { try { - message = mail.getMessage(); + return part.isMimeType(MULTIPART_MIME_TYPE); } catch (MessagingException e) { - throw new MailetException( - "Could not retrieve message from Mail object", e); + throw new MailetException("Could not retrieve contenttype of MimePart.", e); } - // All MIME messages with an attachment are multipart, so we do nothing - // if it is not mutlipart + } + + private MimeMessage getMessageFromMail(Mail mail) throws MailetException { try { - if (message.isMimeType("multipart/*")) { - analyseMultipartPartMessage(message, mail); - } + return mail.getMessage(); } catch (MessagingException e) { - throw new MailetException("Could not retrieve contenttype of message.", e); - } catch (Exception e) { - throw new MailetException("Could not analyse message.", e); + throw new MailetException("Could not retrieve message from Mail object", e); } } @@ -221,122 +231,158 @@ public class StripAttachment extends GenericMailet { * * @return A desciption of this mailet */ + @Override public String getMailetInfo() { return "StripAttachment"; } /** * Checks every part in this part (if it is a Multipart) for having a - * filename that matches the pattern. If the name matches, the content of - * the part is stored (using its name) in te given diretcory. + * filename that matches the pattern. + * If the name matches: + * - the file is stored (using its name) in the given directory (if directoryName is given in the mailet configuration) + * and the filename is stored in 'saved' mail list attribute + * - the part is removed (when removeAttachments mailet configuration property is 'all' or 'matched') + * and the filename is stored in 'removed' mail list attribute + * - the part filename and its content is stored in mail map attribute (if attributeName is given in the mailet configuration) * * Note: this method is recursive. * * @param part * The part to analyse. * @param mail - * @return + * @return True if one of the subpart was removed * @throws Exception */ - private boolean analyseMultipartPartMessage(Part part, Mail mail) - throws Exception { - if (part.isMimeType("multipart/*")) { - try { - Multipart multipart = (Multipart) part.getContent(); - boolean atLeastOneRemoved = false; - int numParts = multipart.getCount(); - for (int i = 0; i < numParts; i++) { - Part p = multipart.getBodyPart(i); - if (p.isMimeType("multipart/*")) { - atLeastOneRemoved |= analyseMultipartPartMessage(p, - mail); - } else { - boolean removed = checkMessageRemoved(p, mail); - if (removed) { - multipart.removeBodyPart(i); - atLeastOneRemoved = true; - i--; - numParts--; - } + @VisibleForTesting boolean processMultipartPartMessage(Part part, Mail mail) throws MailetException { + if (!isMultipart(part)) { + return false; + } + + try { + Multipart multipart = (Multipart) part.getContent(); + boolean atLeastOneRemoved = false; + boolean subpartHasBeenChanged = false; + List<BodyPart> bodyParts = retrieveBodyParts(multipart); + for (BodyPart bodyPart: bodyParts) { + if (isMultipart(bodyPart)) { + if (processMultipartPartMessage(bodyPart, mail)) { + subpartHasBeenChanged = true; } - } - if (atLeastOneRemoved) { - part.setContent(multipart); - if (part instanceof Message) { - ((Message) part).saveChanges(); + } else { + if (shouldBeRemoved(bodyPart, mail)) { + multipart.removeBodyPart(bodyPart); + atLeastOneRemoved = true; } } - return atLeastOneRemoved; - } catch (Exception e) { - log("Could not analyse part.", e); } + if (atLeastOneRemoved || subpartHasBeenChanged) { + updateBodyPart(part, multipart); + } + return atLeastOneRemoved || subpartHasBeenChanged; + } catch (Exception e) { + log("Failing while analysing part for attachments (StripAttachment mailet).", e); + return false; } - return false; } - private boolean checkMessageRemoved(Part part, Mail mail) - throws MessagingException, Exception { - String fileName; - fileName = part.getFileName(); + private void updateBodyPart(Part part, Multipart newPartContent) throws MessagingException { + part.setContent(newPartContent); + if (part instanceof Message) { + ((Message) part).saveChanges(); + } + } - // filename or name of part can be null, so we have to be careful - boolean ret = false; + private List<BodyPart> retrieveBodyParts(Multipart multipart) throws MessagingException { + ImmutableList.Builder<BodyPart> builder = ImmutableList.builder(); + for (int i = 0; i < multipart.getCount(); i++) { + builder.add(multipart.getBodyPart(i)); + } + return builder.build(); + } - if (fileName != null) { - if (decodeFilename) - fileName = MimeUtility.decodeText(fileName); - - if (filenameReplacingPatterns != null) - fileName = new ContentReplacer(false, this).applyPatterns(filenameReplacingPatterns, fileName); - - if (fileNameMatches(fileName)) { - if (directoryName != null) { - String filename = saveAttachmentToFile(part, fileName); - if (filename != null) { - @SuppressWarnings("unchecked") - Collection<String> c = (Collection<String>) mail - .getAttribute(SAVED_ATTACHMENTS_ATTRIBUTE_KEY); - if (c == null) { - c = new ArrayList<String>(); - mail.setAttribute(SAVED_ATTACHMENTS_ATTRIBUTE_KEY, - (ArrayList<String>) c); - } - c.add(filename); - } - } - if (attributeName != null) { - @SuppressWarnings("unchecked") - Map<String, byte[]> m = (Map<String, byte[]>) mail.getAttribute(attributeName); - if (m == null) { - m = new LinkedHashMap<String, byte[]>(); - mail.setAttribute(attributeName, (LinkedHashMap<String, byte[]>) m); - } - ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); - OutputStream os = new BufferedOutputStream( - byteArrayOutputStream); - part.writeTo(os); - m.put(fileName, byteArrayOutputStream.toByteArray()); - } - if (removeAttachments.equals(REMOVE_MATCHED)) { - ret = true; - } - } - if (!ret) { - ret = removeAttachments.equals(REMOVE_ALL); + private boolean shouldBeRemoved(BodyPart bodyPart, Mail mail) throws MessagingException, Exception { + String fileName = getFilename(bodyPart); + if (fileName == null) { + return false; + } + + boolean shouldRemove = removeAttachments.equals(REMOVE_ALL); + if (fileNameMatches(fileName)) { + storeBodyPartAsFile(bodyPart, mail, fileName); + storeBodyPartAsMailAttribute(bodyPart, mail, fileName); + if (removeAttachments.equals(REMOVE_MATCHED)) { + shouldRemove = true; } - if (ret) { - @SuppressWarnings("unchecked") - Collection<String> c = (Collection<String>) mail - .getAttribute(REMOVED_ATTACHMENTS_ATTRIBUTE_KEY); - if (c == null) { - c = new ArrayList<String>(); - mail.setAttribute(REMOVED_ATTACHMENTS_ATTRIBUTE_KEY, - (ArrayList<String>) c); - } - c.add(fileName); + } + storeFileNameAsAttribute(mail, fileName, shouldRemove); + return shouldRemove; + } + + private void storeBodyPartAsFile(BodyPart bodyPart, Mail mail, String fileName) throws Exception { + if (directoryName != null) { + Optional<String> filename = saveAttachmentToFile(bodyPart, Optional.of(fileName)); + if (filename.isPresent()) { + addFilenameToAttribute(mail, filename.get(), SAVED_ATTACHMENTS_ATTRIBUTE_KEY); } } - return ret; + } + + private void addFilenameToAttribute(Mail mail, String filename, String attributeName) { + @SuppressWarnings("unchecked") + List<String> attributeValues = (List<String>) mail.getAttribute(attributeName); + if (attributeValues == null) { + attributeValues = new ArrayList<String>(); + mail.setAttribute(attributeName, (Serializable) attributeValues); + } + attributeValues.add(filename); + } + + private void storeBodyPartAsMailAttribute(BodyPart bodyPart, Mail mail, String fileName) throws IOException, MessagingException { + if (attributeName != null) { + addPartContent(bodyPart, mail, fileName); + } + } + + private void addPartContent(BodyPart bodyPart, Mail mail, String fileName) throws IOException, MessagingException { + @SuppressWarnings("unchecked") + Map<String, byte[]> fileNamesToPartContent = (Map<String, byte[]>) mail.getAttribute(attributeName); + if (fileNamesToPartContent == null) { + fileNamesToPartContent = new LinkedHashMap<String, byte[]>(); + mail.setAttribute(attributeName, (Serializable) fileNamesToPartContent); + } + ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream(); + bodyPart.writeTo(new BufferedOutputStream(byteArrayOutputStream)); + fileNamesToPartContent.put(fileName, byteArrayOutputStream.toByteArray()); + } + + private void storeFileNameAsAttribute(Mail mail, String fileName, boolean hasToBeStored) { + if (hasToBeStored) { + addFilenameToAttribute(mail, fileName, REMOVED_ATTACHMENTS_ATTRIBUTE_KEY); + } + } + + private String getFilename(BodyPart bodyPart) throws UnsupportedEncodingException, MessagingException { + String fileName = bodyPart.getFileName(); + if (fileName != null) { + return renameWithConfigurationPattern(decodeFilename(fileName)); + } + return fileName; + } + + private String renameWithConfigurationPattern(String fileName) { + if (filenameReplacingPatterns != null) { + boolean debug = false; + return new ContentReplacer(debug, this).applyPatterns(filenameReplacingPatterns, fileName); + } + return fileName; + } + + private String decodeFilename(String fileName) throws UnsupportedEncodingException { + if (decodeFilename) { + return MimeUtility.decodeText(fileName); + } + return fileName; } /** @@ -346,71 +392,97 @@ public class StripAttachment extends GenericMailet { * The name to check for a match. * @return True if a match is found, false otherwise. */ - private boolean fileNameMatches(String name) { - boolean result = true; - if (regExPattern != null) - result = regExPattern.matcher(name).matches(); - if (result && notregExPattern != null) - result = !notregExPattern.matcher(name).matches(); - - String log = "attachment " + name + " "; - if (!result) - log += "does not match"; - else - log += "matches"; - log(log); + @VisibleForTesting boolean fileNameMatches(String name) { + if (patternsAreEquals()) { + return false; + } + boolean result = isMatchingPattern(name, regExPattern).or(false) + || !isMatchingPattern(name, notRegExPattern).or(true); + + log("attachment " + name + " " + ((result) ? "matches" : "does not match")); return result; } + private boolean patternsAreEquals() { + return regExPattern != null && notRegExPattern != null + && regExPattern.pattern().equals(notRegExPattern.pattern()); + } + + private Optional<Boolean> isMatchingPattern(String name, Pattern pattern) { + if (pattern != null) { + return Optional.of(pattern.matcher(name).matches()); + } + return Optional.absent(); + } + /** - * Saves the content of the part to a file in the given directoy, using the - * name of the part. If a file with that name already exists, it will + * Saves the content of the part to a file in the given directory, using the + * name of the part. Created files have unique names. * * @param part * The MIME part to save. * @return * @throws Exception */ - private String saveAttachmentToFile(Part part, String fileName) - throws Exception { - BufferedOutputStream os = null; - InputStream is = null; - File f = null; + @VisibleForTesting Optional<String> saveAttachmentToFile(Part part, Optional<String> fileName) throws Exception { try { - if (fileName == null) - fileName = part.getFileName(); - int pos = -1; - if (fileName != null) { - pos = fileName.lastIndexOf("."); - } - String prefix = pos > 0 ? (fileName.substring(0, pos)) : fileName; - String suffix = pos > 0 ? (fileName.substring(pos)) : ".bin"; - while (prefix.length() < 3) - prefix += "_"; - if (suffix.length() == 0) - suffix = ".bin"; - f = File.createTempFile(prefix, suffix, new File(directoryName)); - log("saving content of " + f.getName() + "..."); - os = new BufferedOutputStream(new FileOutputStream(f)); - is = part.getInputStream(); - if (!(is instanceof BufferedInputStream)) { - is = new BufferedInputStream(is); - } - int c; - while ((c = is.read()) != -1) { - os.write(c); - } + File outputFile = outputFile(part, fileName); - return f.getName(); + log("saving content of " + outputFile.getName() + "..."); + IOUtils.copy(part.getInputStream(), new FileOutputStream(outputFile)); + + return Optional.of(outputFile.getName()); } catch (Exception e) { - log("Error while saving contents of [" - + (f != null ? f.getName() : (part != null ? part - .getFileName() : "NULL")) + "].", e); - throw e; - } finally { - is.close(); - os.close(); + log("Error while saving contents of", e); + return Optional.absent(); } } + private File outputFile(Part part, Optional<String> fileName) throws MessagingException, IOException { + Optional<String> maybePartFileName = Optional.fromNullable(part.getFileName()); + return createTempFile(fileName.or(maybePartFileName).orNull()); + } + + private File createTempFile(String originalFileName) throws IOException { + OutputFileName outputFileName = OutputFileName.from(originalFileName); + return File.createTempFile(outputFileName.getPrefix(), outputFileName.getSuffix(), new File(directoryName)); + } + + @VisibleForTesting static class OutputFileName { + + private static final char PAD_CHAR = '_'; + private static final int MIN_LENGTH = 3; + private static final String DEFAULT_SUFFIX = ".bin"; + + public static OutputFileName from(String originalFileName) { + if (!originalFileName.contains(".")) { + return new OutputFileName(prependedPrefix(originalFileName), DEFAULT_SUFFIX); + } + + int lastDotPosition = originalFileName.lastIndexOf("."); + return new OutputFileName(prependedPrefix(originalFileName.substring(0, lastDotPosition)), + originalFileName.substring(lastDotPosition)); + } + + @VisibleForTesting static String prependedPrefix(String prefix) { + return Strings.padStart(prefix, MIN_LENGTH, PAD_CHAR); + } + + private final String prefix; + private final String suffix; + + private OutputFileName(String prefix, String suffix) { + this.prefix = prefix; + this.suffix = suffix; + } + + public String getPrefix() { + return prefix; + } + + public String getSuffix() { + return suffix; + } + } } + http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/standard/src/main/java/org/apache/james/transport/mailets/WrapText.java ---------------------------------------------------------------------- diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/WrapText.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/WrapText.java index a964bf4..04b41a6 100644 --- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/WrapText.java +++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/WrapText.java @@ -46,12 +46,6 @@ public class WrapText extends GenericMailet { public String getMailetInfo() { return "WrapText"; } - - private static boolean getBooleanParameter(String v, boolean def) { - return def ? - !(v != null && (v.equalsIgnoreCase("false") || v.equalsIgnoreCase("no"))) : - v != null && (v.equalsIgnoreCase("true") || v.equalsIgnoreCase("yes")) ; - } public void init() throws MailetException { optionFlowedDelsp = getBooleanParameter(getInitParameter(PARAMETER_NAME_FLOWED_DELSP), optionFlowedDelsp); http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java ---------------------------------------------------------------------- diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java index a9bd6e8..add3c55 100644 --- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java +++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/StripAttachmentTest.java @@ -19,134 +19,171 @@ package org.apache.james.transport.mailets; +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.guava.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + import java.io.ByteArrayInputStream; -import java.io.ByteArrayOutputStream; import java.io.File; -import java.io.FileInputStream; import java.io.IOException; -import java.io.InputStream; +import java.io.UnsupportedEncodingException; import java.util.Collection; +import java.util.List; +import java.util.Map; import java.util.Properties; import javax.mail.MessagingException; +import javax.mail.Part; import javax.mail.Session; +import javax.mail.internet.InternetHeaders; import javax.mail.internet.MimeBodyPart; import javax.mail.internet.MimeMessage; import javax.mail.internet.MimeMultipart; -import org.apache.commons.io.FileUtils; +import org.apache.commons.io.IOUtils; +import org.apache.james.transport.mailets.StripAttachment.OutputFileName; import org.apache.mailet.Mail; import org.apache.mailet.Mailet; +import org.apache.mailet.MailetException; import org.apache.mailet.base.test.FakeMail; import org.apache.mailet.base.test.FakeMailetConfig; -import org.junit.Assert; +import org.junit.After; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; + +import com.google.common.base.Charsets; +import com.google.common.base.Optional; public class StripAttachmentTest { + private static final String EXPECTED_ATTACHMENT_CONTENT = "\u0023\u00A4\u00E3\u00E0\u00E9"; + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public TemporaryFolder folder = new TemporaryFolder(); + + private String folderPath; + + @Before + public void setUp() throws IOException { + folderPath = folder.getRoot().getPath() + "/"; + } + + @After + public void tearDown() throws IOException { + folder.delete(); + } + @Test - public void testSimpleAttachment() throws MessagingException, IOException { + public void serviceShouldNotModifyMailWhenNotMultipart() throws MessagingException, IOException { Mailet mailet = initMailet(); + MimeMessage message = mimeMessage(); - MimeMessage message = new MimeMessage(Session - .getDefaultInstance(new Properties())); + MimeBodyPart part = new MimeBodyPart(); + part.setText("simple text"); + + message.setSubject("test"); + message.setContent(part, "text/plain"); + message.saveChanges(); - MimeMultipart mm = new MimeMultipart(); - MimeBodyPart mp = new MimeBodyPart(); - mp.setText("simple text"); - mm.addBodyPart(mp); - String body = "\u0023\u00A4\u00E3\u00E0\u00E9"; - MimeBodyPart mp2 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\nContent-Type: application/octet-stream; charset=utf-8\r\n\r\n" - + body).getBytes("UTF-8"))); - mp2.setDisposition("attachment"); - mp2.setFileName("10.tmp"); - mm.addBodyPart(mp2); - String body2 = "\u0014\u00A3\u00E1\u00E2\u00E4"; - MimeBodyPart mp3 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\nContent-Type: application/octet-stream; charset=utf-8\r\n\r\n" - + body2).getBytes("UTF-8"))); - mp3.setDisposition("attachment"); - mp3.setFileName("temp.zip"); - mm.addBodyPart(mp3); + MimeMessage expectedMessage = mimeMessage(); message.setSubject("test"); - message.setContent(mm); + message.setContent(part, "text/plain"); message.saveChanges(); Mail mail = FakeMail.builder() .mimeMessage(message) .build(); + Mail expectedMail = FakeMail.builder() + .mimeMessage(expectedMessage) + .build(); mailet.service(mail); - ByteArrayOutputStream rawMessage = new ByteArrayOutputStream(); - mail.getMessage().writeTo(rawMessage, - new String[]{"Bcc", "Content-Length", "Message-ID"}); + assertThat(mail).isEqualToComparingFieldByField(expectedMail); + assertThat(mail.getMessage()).isEqualToComparingFieldByField(expectedMessage); + assertThat(mail.getMessage().getContent()).isEqualTo(part); + } + + @Test + public void serviceShouldSaveAttachmentInAFolderWhenPatternMatch() throws MessagingException, IOException { + Mailet mailet = initMailet(); + MimeMessage message = mimeMessage(); + + MimeMultipart multiPart = new MimeMultipart(); + MimeBodyPart textPart = new MimeBodyPart(); + textPart.setText("simple text"); + multiPart.addBodyPart(textPart); + String expectedAttachmentContent = EXPECTED_ATTACHMENT_CONTENT; + multiPart.addBodyPart(createAttachmentBodyPart(expectedAttachmentContent, "10.tmp")); + multiPart.addBodyPart(createAttachmentBodyPart("\u0014\u00A3\u00E1\u00E2\u00E4", "temp.zip")); + + message.setSubject("test"); + message.setContent(multiPart); + message.saveChanges(); + + Mail mail = FakeMail.builder() + .mimeMessage(message) + .build(); + + mailet.service(mail); @SuppressWarnings("unchecked") - Collection<String> c = (Collection<String>) mail - .getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); - Assert.assertNotNull(c); + Collection<String> savedAttachments = (Collection<String>) mail.getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); + assertThat(savedAttachments).isNotNull(); + assertThat(savedAttachments).hasSize(1); - Assert.assertEquals(1, c.size()); + String attachmentFilename = savedAttachments.iterator().next(); - String name = c.iterator().next(); + assertThat(new File(folderPath + attachmentFilename)).hasContent(expectedAttachmentContent); + } - File f = new File("./" + name); - try { - InputStream is = new FileInputStream(f); - String savedFile = toString(is); - is.close(); - Assert.assertEquals(body, savedFile); - } finally { - FileUtils.deleteQuietly(f); - } + private MimeMessage mimeMessage() { + return new MimeMessage(Session + .getDefaultInstance(new Properties())); + } + + private MimeBodyPart createAttachmentBodyPart(String body, String fileName) throws MessagingException, UnsupportedEncodingException { + MimeBodyPart part = createBodyPart(body); + part.setDisposition("attachment"); + part.setFileName(fileName); + return part; } - public String toString(InputStream is) throws IOException { - final ByteArrayOutputStream sw = new ByteArrayOutputStream(); - final byte[] buffer = new byte[1024]; - int n; - while (-1 != (n = is.read(buffer))) { - System.err.println(new String(buffer, 0, n)); - sw.write(buffer, 0, n); - } - return sw.toString("UTF-8"); + private MimeBodyPart createBodyPart(String body) throws MessagingException, UnsupportedEncodingException { + return new MimeBodyPart(new ByteArrayInputStream( + ("Content-Transfer-Encoding: 8bit\r\nContent-Type: application/octet-stream; charset=utf-8\r\n\r\n" + + body).getBytes("UTF-8"))); } @Test - public void testSimpleAttachment2() throws MessagingException, IOException { + public void serviceShouldSaveAttachmentInAFolderWhenNotPatternDoesntMatch() throws MessagingException, IOException { Mailet mailet = new StripAttachment(); FakeMailetConfig mci = FakeMailetConfig.builder() .mailetName("Test") - .setProperty("directory", "./") + .setProperty("directory", folderPath) .setProperty("remove", "all") .setProperty("notpattern", "^(winmail\\.dat$)") .build(); mailet.init(mci); - MimeMessage message = new MimeMessage(Session - .getDefaultInstance(new Properties())); + MimeMessage message = mimeMessage(); - MimeMultipart mm = new MimeMultipart(); - MimeBodyPart mp = new MimeBodyPart(); - mp.setText("simple text"); - mm.addBodyPart(mp); - String body = "\u0023\u00A4\u00E3\u00E0\u00E9"; - MimeBodyPart mp2 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\n\r\n" + body).getBytes("UTF-8"))); - mp2.setDisposition("attachment"); - mp2.setFileName("temp.tmp"); - mm.addBodyPart(mp2); - String body2 = "\u0014\u00A3\u00E1\u00E2\u00E4"; - MimeBodyPart mp3 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\n\r\n" + body2).getBytes("UTF-8"))); - mp3.setDisposition("attachment"); - mp3.setFileName("winmail.dat"); - mm.addBodyPart(mp3); + MimeMultipart multiPart = new MimeMultipart(); + MimeBodyPart part = new MimeBodyPart(); + part.setText("simple text"); + multiPart.addBodyPart(part); + String expectedAttachmentContent = EXPECTED_ATTACHMENT_CONTENT; + multiPart.addBodyPart(createAttachmentBodyPart(expectedAttachmentContent, "temp.tmp")); + multiPart.addBodyPart(createAttachmentBodyPart("\u0014\u00A3\u00E1\u00E2\u00E4", "winmail.dat")); + message.setSubject("test"); - message.setContent(mm); + message.setContent(multiPart); message.saveChanges(); Mail mail = FakeMail.builder() @@ -155,201 +192,533 @@ public class StripAttachmentTest { mailet.service(mail); - ByteArrayOutputStream rawMessage = new ByteArrayOutputStream(); - mail.getMessage().writeTo(rawMessage, - new String[]{"Bcc", "Content-Length", "Message-ID"}); - // String res = rawMessage.toString(); - @SuppressWarnings("unchecked") - Collection<String> c = (Collection<String>) mail - .getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); - Assert.assertNotNull(c); - - Assert.assertEquals(1, c.size()); + Collection<String> savedAttachments = (Collection<String>) mail.getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); + assertThat(savedAttachments).isNotNull(); + assertThat(savedAttachments).hasSize(1); - String name = c.iterator().next(); + String attachmentFilename = savedAttachments.iterator().next(); - File f = new File("./" + name); - try { - InputStream is = new FileInputStream(f); - String savedFile = toString(is); - is.close(); - Assert.assertEquals(body, savedFile); - } finally { - FileUtils.deleteQuietly(f); - } + assertThat(new File(folderPath + attachmentFilename)).hasContent(expectedAttachmentContent); } @Test - public void testSimpleAttachment3() throws MessagingException, IOException { + public void serviceShouldDecodeFilenameAndSaveAttachmentInAFolderWhenPatternMatchAndDecodeFilenameTrue() throws MessagingException, IOException { Mailet mailet = initMailet(); - // System.setProperty("mail.mime.decodefilename", "true"); + MimeMessage message = mimeMessage(); - MimeMessage message = new MimeMessage(Session - .getDefaultInstance(new Properties())); - - MimeMultipart mm = new MimeMultipart(); - MimeBodyPart mp = new MimeBodyPart(); - mp.setText("simple text"); - mm.addBodyPart(mp); - String body = "\u0023\u00A4\u00E3\u00E0\u00E9"; - MimeBodyPart mp2 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\n\r\n" + body).getBytes("UTF-8"))); - mp2.setDisposition("attachment"); - mp2 - .setFileName("=?iso-8859-15?Q?=E9_++++Pubblicit=E0_=E9_vietata____Milano9052.tmp?="); - mm.addBodyPart(mp2); - String body2 = "\u0014\u00A3\u00E1\u00E2\u00E4"; - MimeBodyPart mp3 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\n\r\n" + body2).getBytes("UTF-8"))); - mp3.setDisposition("attachment"); - mp3.setFileName("temp.zip"); - mm.addBodyPart(mp3); + MimeMultipart multiPart = new MimeMultipart(); + MimeBodyPart part = new MimeBodyPart(); + part.setText("simple text"); + multiPart.addBodyPart(part); + String expectedAttachmentContent = EXPECTED_ATTACHMENT_CONTENT; + multiPart.addBodyPart(createAttachmentBodyPart(expectedAttachmentContent, "=?iso-8859-15?Q?=E9_++++Pubblicit=E0_=E9_vietata____Milano9052.tmp?=")); + multiPart.addBodyPart(createAttachmentBodyPart("\u0014\u00A3\u00E1\u00E2\u00E4", "temp.zip")); + message.setSubject("test"); - message.setContent(mm); + message.setContent(multiPart); message.saveChanges(); - // message.writeTo(System.out); - // System.out.println("--------------------------\n\n\n"); - Mail mail = FakeMail.builder() .mimeMessage(message) .build(); mailet.service(mail); - ByteArrayOutputStream rawMessage = new ByteArrayOutputStream(); - mail.getMessage().writeTo(rawMessage, - new String[]{"Bcc", "Content-Length", "Message-ID"}); - // String res = rawMessage.toString(); + @SuppressWarnings("unchecked") + Collection<String> savedAttachments = (Collection<String>) mail.getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); + assertThat(savedAttachments).isNotNull(); + assertThat(savedAttachments).hasSize(1); + + String name = savedAttachments.iterator().next(); + + assertThat(name.startsWith("e_Pubblicita_e_vietata_Milano9052")).isTrue(); + + assertThat(new File(folderPath + name)).hasContent(expectedAttachmentContent); + } + + @Test + public void serviceShouldSaveFilenameAttachmentAndFileContentInCustomAttribute() throws MessagingException, IOException { + StripAttachment mailet = new StripAttachment(); + + String customAttribute = "my.custom.attribute"; + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("directory", folderPath) + .setProperty("pattern", ".*\\.tmp") + .setProperty("attribute", customAttribute) + .build(); + mailet.init(mci); + + MimeMessage message = mimeMessage(); + + MimeMultipart multiPart = new MimeMultipart(); + MimeBodyPart part = new MimeBodyPart(); + part.setText("simple text"); + multiPart.addBodyPart(part); + String expectedKey = "10.tmp"; + multiPart.addBodyPart(createAttachmentBodyPart(EXPECTED_ATTACHMENT_CONTENT, expectedKey)); + multiPart.addBodyPart(createAttachmentBodyPart("\u0014\u00A3\u00E1\u00E2\u00E4", "temp.zip")); + + message.setSubject("test"); + message.setContent(multiPart); + message.saveChanges(); + + Mail mail = FakeMail.builder() + .mimeMessage(message) + .build(); + + mailet.service(mail); @SuppressWarnings("unchecked") - Collection<String> c = (Collection<String>) mail - .getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); - Assert.assertNotNull(c); + Map<String, byte[]> saved = (Map<String, byte[]>) mail.getAttribute(customAttribute); + assertThat(saved).hasSize(1); + assertThat(saved).containsKey(expectedKey); + MimeBodyPart savedBodyPart = new MimeBodyPart(new ByteArrayInputStream(saved.get(expectedKey))); + String content = IOUtils.toString(savedBodyPart.getInputStream()); + assertThat(content).isEqualTo(EXPECTED_ATTACHMENT_CONTENT); + } - Assert.assertEquals(1, c.size()); + @Test + public void initShouldThrowWhenPatternAndNotPatternAreNull() throws MessagingException { + Mailet mailet = new StripAttachment(); - String name = c.iterator().next(); - // System.out.println("--------------------------\n\n\n"); - // System.out.println(name); + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .build(); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("At least one of 'pattern' or 'notpattern' parameter should be provided."); + mailet.init(mci); + } - Assert.assertTrue(name.startsWith("e_Pubblicita_e_vietata_Milano9052")); + @Test + public void initShouldThrowWhenWrongPattern() throws MessagingException { + Mailet mailet = new StripAttachment(); - File f = new File("./" + name); - try { - InputStream is = new FileInputStream(f); - String savedFile = toString(is); - is.close(); - Assert.assertEquals(body, savedFile); - } finally { - FileUtils.deleteQuietly(f); - } + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("pattern", ".****\\.tmp") + .build(); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("Could not compile regex [.****\\.tmp]"); + mailet.init(mci); + } + + @Test + public void initShouldThrowWhenWrongNotPattern() throws MessagingException { + Mailet mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("notpattern", ".****\\.tmp") + .build(); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("Could not compile regex [.****\\.tmp]"); + mailet.init(mci); + } + + @Test + public void initShouldThrowWhenRemoveParameterIsUnknown() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "unknown") + .setProperty("pattern", ".*\\.tmp") + .build(); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("Unknown remove parameter value 'unknown' waiting for 'matched', 'all' or 'no'."); + mailet.init(mci); + } + + @Test + public void initShouldSetRemoveParameterWhenEqualsMatched() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("pattern", ".*\\.tmp") + .build(); + + mailet.init(mci); + assertThat(mailet.removeAttachments).isEqualTo(StripAttachment.REMOVE_MATCHED); } @Test - public void testToAndFromAttributes() throws MessagingException, - IOException { - Mailet strip = new StripAttachment(); + public void initShouldSetRemoveParameterWhenEqualsAll() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() .mailetName("Test") - .setProperty("attribute", "my.attribute") .setProperty("remove", "all") - .setProperty("notpattern", ".*\\.tmp.*") + .setProperty("pattern", ".*\\.tmp") .build(); - strip.init(mci); - Mailet recover = new RecoverAttachment(); - FakeMailetConfig mci2 = FakeMailetConfig.builder() + mailet.init(mci); + assertThat(mailet.removeAttachments).isEqualTo(StripAttachment.REMOVE_ALL); + } + + @Test + public void initShouldSetRemoveParameterWhenEqualsNo() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() .mailetName("Test") - .setProperty("attribute", "my.attribute") + .setProperty("remove", "no") + .setProperty("pattern", ".*\\.tmp") .build(); - recover.init(mci2); - Mailet onlyText = new OnlyText(); - onlyText.init(FakeMailetConfig.builder() + mailet.init(mci); + assertThat(mailet.removeAttachments).isEqualTo(StripAttachment.REMOVE_NONE); + } + + @Test + public void initShouldSetRemoveParameterDefaultValueWhenNotGiven() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() .mailetName("Test") - .build()); + .setProperty("pattern", ".*\\.tmp") + .build(); - MimeMessage message = new MimeMessage(Session - .getDefaultInstance(new Properties())); + mailet.init(mci); + assertThat(mailet.removeAttachments).isEqualTo("no"); + } - MimeMultipart mm = new MimeMultipart(); - MimeBodyPart mp = new MimeBodyPart(); - mp.setText("simple text"); - mm.addBodyPart(mp); - String body = "\u0023\u00A4\u00E3\u00E0\u00E9"; - MimeBodyPart mp2 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\nContent-Type: application/octet-stream; charset=utf-8\r\n\r\n" - + body).getBytes("UTF-8"))); - mp2.setDisposition("attachment"); - mp2 - .setFileName("=?iso-8859-15?Q?=E9_++++Pubblicit=E0_=E9_vietata____Milano9052.tmp?="); - mm.addBodyPart(mp2); - String body2 = "\u0014\u00A3\u00E1\u00E2\u00E4"; - MimeBodyPart mp3 = new MimeBodyPart(new ByteArrayInputStream( - ("Content-Transfer-Encoding: 8bit\r\nContent-Type: application/octet-stream; charset=utf-8\r\n\r\n" - + body2).getBytes("UTF-8"))); - mp3.setDisposition("attachment"); - mp3.setFileName("temp.zip"); - mm.addBodyPart(mp3); - message.setSubject("test"); - message.setContent(mm); - message.saveChanges(); - Mail mail = FakeMail.builder() - .mimeMessage(message) + @Test + public void serviceShouldThrowWhenUnretrievableMessage() throws MessagingException { + Mailet mailet = initMailet(); + + Mail mail = mock(Mail.class); + when(mail.getMessage()) + .thenThrow(new MessagingException("Test exception")); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("Could not retrieve message from Mail object"); + + mailet.service(mail); + } + + @Test + public void serviceShouldThrowWhenUnretrievableContentTypeMessage() throws MessagingException { + Mailet mailet = initMailet(); + + MimeMessage message = mock(MimeMessage.class); + Mail mail = mock(Mail.class); + when(mail.getMessage()) + .thenReturn(message); + when(message.isMimeType("multipart/*")) + .thenThrow(new MessagingException("Test exception")); + + expectedException.expect(MailetException.class); + expectedException.expectMessage("Could not retrieve contenttype of MimePart."); + + mailet.service(mail); + } + + @Test + public void getMailetInfoShouldReturn() throws MessagingException { + StripAttachment mailet = new StripAttachment(); + + assertThat(mailet.getMailetInfo()).isEqualTo("StripAttachment"); + } + + @Test + public void processMultipartPartMessageShouldReturnFalseWhenPartIsNotMultipart() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); + Part part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + Mail mail = mock(Mail.class); + //When + boolean actual = mailet.processMultipartPartMessage(part, mail); + //Then + assertThat(actual).isFalse(); + } + + @Test + public void processMultipartPartMessageShouldReturnTrueWhenAtLeastOneMultipartShouldHaveBeenRemoved() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); + + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "all") + .setProperty("pattern", ".*") .build(); + mailet.init(mci); + MimeMultipart multiPart = new MimeMultipart(); + + MimeBodyPart part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("removeMe.tmp"); + multiPart.addBodyPart(part); + MimeMessage message = mimeMessage(); + message.setContent(multiPart); + message.saveChanges(); + Mail mail = mock(Mail.class); + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(actual).isTrue(); + } - Assert.assertTrue(mail.getMessage().getContent() instanceof MimeMultipart); - Assert.assertEquals(3, ((MimeMultipart) mail.getMessage().getContent()) - .getCount()); + @Test + public void processMultipartPartMessageShouldReturnTrueWhenAtLeastOneMultipartShouldHaveBeenRemovedAndPartialRemove() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - strip.service(mail); + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("pattern", ".*") + .build(); + mailet.init(mci); + MimeMultipart multiPart = new MimeMultipart(); + + MimeBodyPart part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("removeMe.tmp"); + multiPart.addBodyPart(part); + MimeMessage message = mimeMessage(); + message.setContent(multiPart); + message.saveChanges(); + Mail mail = mock(Mail.class); + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(actual).isTrue(); + } - Assert.assertTrue(mail.getMessage().getContent() instanceof MimeMultipart); - Assert.assertEquals(1, ((MimeMultipart) mail.getMessage().getContent()) - .getCount()); + @Test + public void processMultipartPartMessageShouldPutTwoPartsInDefaultAttributeWhenTwoPartsMatch() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - onlyText.service(mail); + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("directory", folderPath) + .setProperty("pattern", ".*") + .build(); + mailet.init(mci); + MimeMultipart multiPart = new MimeMultipart(); + + MimeBodyPart part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("removeMe.tmp"); + multiPart.addBodyPart(part); + multiPart.addBodyPart(part); + MimeMessage message = mimeMessage(); + message.setContent(multiPart); + message.saveChanges(); + Mail mail = FakeMail.builder().build(); + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(actual).isTrue(); + @SuppressWarnings("unchecked") + List<String> values = (List<String>)mail.getAttribute(StripAttachment.SAVED_ATTACHMENTS_ATTRIBUTE_KEY); + assertThat(values).hasSize(2); + } - Assert.assertFalse(mail.getMessage().getContent() instanceof MimeMultipart); + @Test + public void processMultipartPartMessageShouldPutTwoPartsInCustomAttributeWhenTwoPartsMatch() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - Assert.assertEquals("simple text", mail.getMessage().getContent()); + String customAttribute = "my.custom.attribute"; + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("directory", folderPath) + .setProperty("pattern", ".*") + .setProperty("attribute", customAttribute) + .build(); + mailet.init(mci); + + // Message with two matching attachments + MimeMultipart multiPart = new MimeMultipart(); + MimeBodyPart attachmentPart1 = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + attachmentPart1.setFileName("removeMe1.tmp"); + multiPart.addBodyPart(attachmentPart1); + MimeBodyPart attachmentPart2 = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + attachmentPart2.setFileName("removeMe2.tmp"); + multiPart.addBodyPart(attachmentPart2); + + MimeMessage message = mimeMessage(); + message.setContent(multiPart); + message.saveChanges(); + + Mail mail = FakeMail.builder().build(); + + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + + //Then + assertThat(actual).isTrue(); + @SuppressWarnings("unchecked") + Map<String, byte[]> values = (Map<String, byte[]>)mail.getAttribute(customAttribute); + assertThat(values).hasSize(2); + } - // prova per caricare il mime message da input stream che altrimenti - // javamail si comporta differentemente. - String mimeSource = "Message-ID: <26194423.21197328775426.JavaMail.bago@bagovista>\r\nSubject: test\r\nMIME-Version: 1.0\r\nContent-Type: text/plain; charset=us-ascii\r\nContent-Transfer-Encoding: 7bit\r\n\r\nsimple text"; + @Test + public void processMultipartPartMessageShouldReturnTrueWhenAtLeastOneSubMultipartShouldHaveBeenRemoved() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - MimeMessage mmNew = new MimeMessage(Session - .getDefaultInstance(new Properties()), - new ByteArrayInputStream(mimeSource.getBytes("UTF-8"))); + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "all") + .setProperty("pattern", ".*\\.tmp") + .build(); + mailet .init(mci); + + MimeBodyPart attachmentPart = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + attachmentPart.setFileName("removeMe.tmp"); + + MimeMultipart subMultiPart = new MimeMultipart(); + subMultiPart.addBodyPart(attachmentPart); + + MimeMessage subMessage = mimeMessage(); + subMessage.setContent(subMultiPart); + subMessage.saveChanges(); + + MimeMultipart multiPartMixed = new MimeMultipart(); + multiPartMixed.addBodyPart(new MimeBodyPart(new InternetHeaders(new ByteArrayInputStream("Content-Type: multipart/mixed".getBytes(Charsets.US_ASCII))) + , IOUtils.toByteArray(subMessage.getInputStream()))); + + MimeMessage message = mimeMessage(); + message.setContent(multiPartMixed); + message.saveChanges(); + Mail mail = mock(Mail.class); + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(actual).isTrue(); + } - mmNew.writeTo(System.out); - mail.setMessage(mmNew); + @Test + public void processMultipartPartMessageShouldReturnFalseWhenNoPartHasBeenRemovedInSubMultipart() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - recover.service(mail); + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("pattern", ".*\\.tmp") + .build(); + mailet.init(mci); + MimeMultipart mainMultiPart = new MimeMultipart(); + MimeMessage subMessage = mimeMessage(); + MimeMultipart subMultiPart = new MimeMultipart(); + MimeBodyPart part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("dontRemoveMe.other"); + subMultiPart.addBodyPart(part); + subMessage.setContent(subMultiPart); + subMessage.saveChanges(); + mainMultiPart.addBodyPart(new MimeBodyPart(new InternetHeaders(new ByteArrayInputStream("Content-Type: multipart/mixed".getBytes(Charsets.US_ASCII))) + , + IOUtils.toByteArray(subMessage.getInputStream()))); + MimeMessage message = mimeMessage(); + message.setContent(mainMultiPart); + message.saveChanges(); + Mail mail = mock(Mail.class); + //When + boolean actual = mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(actual).isFalse(); + } - Assert.assertTrue(mail.getMessage().getContent() instanceof MimeMultipart); - Assert.assertEquals(2, ((MimeMultipart) mail.getMessage().getContent()) - .getCount()); + @Test + public void processMultipartPartMessageShouldRemovePartWhenOnePartShouldHaveBeenRemoved() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); - Object actual = ((MimeMultipart) mail.getMessage().getContent()) - .getBodyPart(1).getContent(); - if (actual instanceof ByteArrayInputStream) { - Assert.assertEquals(body2, toString((ByteArrayInputStream) actual)); - } else { - Assert.assertEquals(body2, actual); - } + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "all") + .setProperty("pattern", ".*") + .build(); + mailet.init(mci); + MimeMultipart multiPart = new MimeMultipart(); + + MimeBodyPart part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("removeMe.tmp"); + multiPart.addBodyPart(part); + MimeMessage message = mimeMessage(); + message.setContent(multiPart); + message.saveChanges(); + Mail mail = mock(Mail.class); + //When + mailet.processMultipartPartMessage(message, mail); + //Then + assertThat(multiPart.getCount()).isZero(); + } + @Test + public void saveAttachmentShouldUsePartNameIfNoFilename() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("directory", folderPath) + .setProperty("pattern", ".*\\.tmp") + .build(); + mailet.init(mci); + Part part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + part.setFileName("example.tmp"); + //When + Optional<String> maybeFilename = mailet.saveAttachmentToFile(part, Optional.<String> absent()); + //Then + assertThat(maybeFilename).isPresent(); + String filename = maybeFilename.get(); + assertThat(filename).startsWith("example"); + assertThat(filename).endsWith(".tmp"); } + + @Test + public void saveAttachmentShouldReturnAbsentWhenNoFilenameAtAll() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("directory", folderPath) + .setProperty("pattern", ".*\\.tmp") + .build(); + mailet.init(mci); + Part part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + Optional<String> maybeFilename = mailet.saveAttachmentToFile(part, Optional.<String> absent()); + assertThat(maybeFilename).isAbsent(); + } + + @Test + public void saveAttachmentShouldAddBinExtensionWhenNoFileNameExtension() throws Exception { + //Given + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("directory", folderPath) + .setProperty("pattern", ".*") + .build(); + mailet.init(mci); + Part part = new MimeBodyPart(new ByteArrayInputStream(new byte[0])); + String fileName = "exampleWithoutSuffix"; + //When + Optional<String> maybeFilename = mailet.saveAttachmentToFile(part, Optional.of(fileName)); + //Then + assertThat(maybeFilename).isPresent(); + String filename = maybeFilename.get(); + assertThat(filename).startsWith("exampleWithoutSuffix"); + assertThat(filename).endsWith(".bin"); + } + private Mailet initMailet() throws MessagingException { Mailet mailet = new StripAttachment(); FakeMailetConfig mci = FakeMailetConfig.builder() .mailetName("Test") - .setProperty("directory", "./") + .setProperty("directory", folderPath) .setProperty("remove", "all") .setProperty("pattern", ".*\\.tmp") .setProperty("decodeFilename", "true") @@ -373,4 +742,109 @@ public class StripAttachmentTest { return mailet; } + @Test + public void fileNameMatchesShouldThrowWhenPatternIsNull() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .build(); + mailet.init(mci); + + expectedException.expect(NullPointerException.class); + mailet.fileNameMatches(null); + } + + @Test + public void fileNameMatchesShouldReturnFalseWhenPatternDoesntMatch() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("not matching")).isFalse(); + } + + @Test + public void fileNameMatchesShouldReturnTrueWhenPatternMatches() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("I've got a pattern.")).isTrue(); + } + + @Test + public void fileNameMatchesShouldReturnFalseWhenNotPatternMatches() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("notpattern", ".*pattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("I've got a pattern.")).isFalse(); + } + + @Test + public void fileNameMatchesShouldReturnTrueWhenNotPatternDoesntMatch() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("notpattern", ".*pattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("not matching")).isTrue(); + } + + @Test + public void fileNameMatchesShouldReturnFalseWhenPatternAndNotPatternAreTheSame() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .setProperty("notpattern", ".*pattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("not matching")).isFalse(); + assertThat(mailet.fileNameMatches("I've got a pattern.")).isFalse(); + } + + @Test + public void fileNameMatchesShouldReturnTrueWhenPatternMatchesAndNotPatternDoesntMatch() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .setProperty("notpattern", ".*notpattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("I've got a pattern.")).isTrue(); + } + + @Test + public void fileNameMatchesShouldReturnTrueWhenPatternDoesntMatchesAndNotPatternDoesntMatch() throws Exception { + StripAttachment mailet = new StripAttachment(); + FakeMailetConfig mci = FakeMailetConfig.builder() + .setProperty("pattern", ".*pattern.*") + .setProperty("notpattern", ".*notpattern.*") + .build(); + mailet.init(mci); + + assertThat(mailet.fileNameMatches("o.")).isTrue(); + } + + @Test + public void prependedPrefixShouldAddUnderscoreWhenPrefixIsLessThanThreeCharacters() { + String prefix = OutputFileName.prependedPrefix("a"); + assertThat(prefix).isEqualTo("__a"); + } + + @Test + public void prependedPrefixShouldReturnPrefixWhenPrefixIsGreaterThanThreeCharacters() { + String expectedPrefix = "abcd"; + String prefix = OutputFileName.prependedPrefix(expectedPrefix); + assertThat(prefix).isEqualTo(expectedPrefix); + } } http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/server/mailet/integration-testing/pom.xml ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/pom.xml b/server/mailet/integration-testing/pom.xml index 44c011d..51a9ac3 100644 --- a/server/mailet/integration-testing/pom.xml +++ b/server/mailet/integration-testing/pom.xml @@ -176,6 +176,12 @@ <version>${project.version}</version> </dependency> <dependency> + <groupId>org.apache.james</groupId> + <artifactId>apache-mailet-base</artifactId> + <type>test-jar</type> + <scope>test</scope> + </dependency> + <dependency> <groupId>ch.qos.logback</groupId> <artifactId>logback-classic</artifactId> <version>1.1.6</version> http://git-wip-us.apache.org/repos/asf/james-project/blob/0e49d8c2/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/utils/SMTPMessageSender.java ---------------------------------------------------------------------- diff --git a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/utils/SMTPMessageSender.java b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/utils/SMTPMessageSender.java index 410bd52..5ee5931 100644 --- a/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/utils/SMTPMessageSender.java +++ b/server/mailet/integration-testing/src/test/java/org/apache/james/mailets/utils/SMTPMessageSender.java @@ -19,15 +19,22 @@ package org.apache.james.mailets.utils; +import java.io.ByteArrayOutputStream; import java.io.Closeable; import java.io.IOException; import java.security.InvalidKeyException; import java.security.NoSuchAlgorithmException; import java.security.spec.InvalidKeySpecException; +import javax.mail.Message; +import javax.mail.MessagingException; + import org.apache.commons.net.smtp.AuthenticatingSMTPClient; import org.apache.commons.net.smtp.SMTPClient; +import org.apache.mailet.Mail; +import com.google.common.base.Charsets; +import com.google.common.base.Joiner; import com.google.common.base.Throwables; public class SMTPMessageSender implements Closeable { @@ -69,6 +76,24 @@ public class SMTPMessageSender implements Closeable { } } + public void sendMessage(Mail mail) throws MessagingException { + try { + String from = mail.getSender().asString(); + smtpClient.helo(senderDomain); + smtpClient.setSender(from); + smtpClient.rcpt("<" + Joiner.on(", ").join(mail.getRecipients()) + ">"); + smtpClient.sendShortMessageData(asString(mail.getMessage())); + } catch (IOException e) { + throw Throwables.propagate(e); + } + } + + private String asString(Message message) throws IOException, MessagingException { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + message.writeTo(outputStream); + return new String(outputStream.toByteArray(), Charsets.UTF_8); + } + public boolean messageHasBeenSent() throws IOException { return smtpClient.getReplyString() .contains("250 2.6.0 Message received"); --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
