You are viewing a plain text version of this content. The canonical link for it is here.
Posted to server-dev@james.apache.org by ro...@apache.org on 2016/09/07 12:00:38 UTC

[1/3] james-project git commit: MAILET-110 Define own classes for pattern extracting and content replacement

Repository: james-project
Updated Branches:
  refs/heads/master 35c541597 -> baae24e23


MAILET-110 Define own classes for pattern extracting and content replacement


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/ef80d94a
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/ef80d94a
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/ef80d94a

Branch: refs/heads/master
Commit: ef80d94a960feb1b76fac91d912e9c8f75fc921e
Parents: af067c6
Author: Antoine Duprat <ad...@linagora.com>
Authored: Tue Aug 30 09:05:43 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Wed Sep 7 10:35:09 2016 +0200

----------------------------------------------------------------------
 .../transport/mailets/ContentReplacer.java      | 147 +++++++++++
 .../transport/mailets/PatternExtractor.java     | 188 ++++++++++++++
 .../james/transport/mailets/ReplaceContent.java | 245 ++-----------------
 .../transport/mailets/StripAttachment.java      |   4 +-
 .../transport/mailets/ContentReplacerTest.java  | 151 ++++++++++++
 .../transport/mailets/PatternExtractorTest.java | 103 ++++++++
 .../transport/mailets/ReplaceContentTest.java   | 128 ++++------
 .../transport/mailets/StripAttachmentTest.java  |   4 +-
 8 files changed, 657 insertions(+), 313 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContentReplacer.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContentReplacer.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContentReplacer.java
new file mode 100644
index 0000000..92fb945
--- /dev/null
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ContentReplacer.java
@@ -0,0 +1,147 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import java.io.IOException;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.regex.Matcher;
+
+import javax.mail.MessagingException;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.ParseException;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailetException;
+import org.apache.mailet.base.GenericMailet;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+
+public class ContentReplacer {
+
+    private final boolean debug;
+    private final GenericMailet logOwner;
+
+    public ContentReplacer(boolean debug, GenericMailet logOwner) {
+        this.debug = debug;
+        this.logOwner = logOwner;
+    }
+
+    public String applyPatterns(List<ReplacingPattern> patterns, String text) {
+        String textCopy = new String(text);
+        for (ReplacingPattern replacingPattern : patterns) {
+            textCopy = applyPattern(replacingPattern, textCopy);
+        }
+        return textCopy;
+    }
+
+    private String applyPattern(ReplacingPattern replacingPattern, String text) {
+        boolean changed;
+        int index = 0;
+        do {
+            changed = false;
+            Matcher matcher = replacingPattern.getMatcher().matcher(text);
+            if (matcher.find(index)) {
+                text = replaceFirst(replacingPattern, matcher);
+                changed = true;
+                index++;
+            }
+        } while (shouldRepeat(replacingPattern, changed));
+        return text;
+    }
+
+    private String replaceFirst(ReplacingPattern replacingPattern, Matcher matcher) {
+        if (debug) {
+            logOwner.log("Subject rule match: " + replacingPattern.getMatcher());
+        }
+        return matcher.replaceFirst(replacingPattern.getSubstitution());
+    }
+
+    private boolean shouldRepeat(ReplacingPattern replacingPattern, boolean changed) {
+        return replacingPattern.isRepeat() && changed;
+    }
+
+    public void replaceMailContentAndSubject(Mail mail, ReplaceConfig replaceConfig, Optional<Charset> charset) throws MailetException {
+        try {
+            boolean subjectChanged = applySubjectReplacingUnits(mail, replaceConfig, charset);
+            boolean contentChanged = applyBodyReplacingUnits(mail, replaceConfig, charset);
+
+            if (subjectChanged || contentChanged) {
+                mail.getMessage().saveChanges();
+            }
+        } catch (MessagingException e) {
+            throw new MailetException("Error in replace", e);
+            
+        } catch (IOException e) {
+            throw new MailetException("Error in replace", e);
+        }
+    }
+
+    private boolean applySubjectReplacingUnits(Mail mail, ReplaceConfig replaceConfig, Optional<Charset> charset) throws MessagingException {
+        if (!replaceConfig.getSubjectReplacingUnits().isEmpty()) {
+            String subject = applyPatterns(replaceConfig.getSubjectReplacingUnits(), 
+                    Strings.nullToEmpty(mail.getMessage().getSubject()));
+            if (charset.isPresent()) {
+                mail.getMessage().setSubject(subject, charset.get().name());
+                return true;
+            }
+            else {
+                String previousCharset = previousCharset(mail);
+                mail.getMessage().setSubject(subject, previousCharset);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private String previousCharset(Mail mail) throws ParseException, MessagingException {
+        ContentType contentType = new ContentType(mail.getMessage().getContentType());
+        return contentType.getParameter("Charset");
+    }
+
+    private boolean applyBodyReplacingUnits(Mail mail, ReplaceConfig replaceConfig, Optional<Charset> charset) throws IOException, MessagingException, ParseException {
+        if (!replaceConfig.getBodyReplacingUnits().isEmpty()) {
+            Object bodyObj = mail.getMessage().getContent();
+            if (bodyObj instanceof String) {
+                String body = applyPatterns(replaceConfig.getBodyReplacingUnits(), 
+                        Strings.nullToEmpty((String) bodyObj));
+                setContent(mail, body, charset);
+                return true;
+            }
+        }
+        return false;
+    }
+
+    private void setContent(Mail mail, String body, Optional<Charset> charset) throws MessagingException, ParseException {
+        mail.getMessage().setContent(body, getContentType(mail, charset));
+    }
+
+    private String getContentType(Mail mail, Optional<Charset> charset) throws MessagingException, ParseException {
+        String contentTypeAsString = mail.getMessage().getContentType();
+        if (charset.isPresent()) {
+            ContentType contentType = new ContentType(contentTypeAsString);
+            contentType.setParameter("charset", charset.get().name());
+            return contentType.toString();
+        }
+        return contentTypeAsString;
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternExtractor.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternExtractor.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternExtractor.java
new file mode 100644
index 0000000..dbeb42c
--- /dev/null
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternExtractor.java
@@ -0,0 +1,188 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.IOException;
+import java.io.InputStream;
+import java.nio.charset.Charset;
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.mailet.MailetException;
+import org.apache.mailet.base.StringUtils;
+
+import com.google.common.base.Optional;
+import com.google.common.base.Splitter;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
+public class PatternExtractor {
+
+    private static final int PATTERN = 0;
+    private static final int SUBSTITUTION = 1;
+    private static final int OPTIONS = 2;
+
+    public List<ReplacingPattern> getPatternsFromString(String pattern) throws MailetException {
+        String trimPattern = pattern.trim();
+        assertPatternSurroundedWithSlashes(trimPattern);
+        
+        ImmutableList.Builder<ReplacingPattern> patternList = ImmutableList.builder();
+        for (String aPatternArray : extractPatternParts(trimPattern)) {
+            patternList.add(stripSurroundingSlashes(aPatternArray));
+        }
+        return patternList.build();
+    }
+
+    private void assertPatternSurroundedWithSlashes(String pattern) throws MailetException {
+        if (pattern.length() < 2 || (!pattern.startsWith("/") && !pattern.endsWith("/"))) {
+            throw new MailetException("Invalid expression: " + pattern);
+        }
+    }
+
+    private String[] extractPatternParts(String trimPattern) {
+        String trimSurroundingSlashes = trimPattern.substring(1, trimPattern.length() - 1);
+        return StringUtils.split(trimSurroundingSlashes, "/,/");
+    }
+
+    private ReplacingPattern stripSurroundingSlashes(String line) throws MailetException {
+        String[] parts = StringUtils.split(line, "/");
+        if (parts.length < 3) {
+            throw new MailetException("Invalid expression: " + line);
+        }
+        return new ReplacingPattern(Pattern.compile(parts[PATTERN], extractOptions(parts[OPTIONS])), 
+                extractRepeat(parts[OPTIONS]), 
+                unescapeSubstitutions(parts[SUBSTITUTION]));
+    }
+
+    private int extractOptions(String optionsAsString) {
+        int options = 0;
+        if (optionsAsString.contains("i")) {
+            options |= Pattern.CASE_INSENSITIVE;
+        }
+        if (optionsAsString.contains("m")) {
+            options |= Pattern.MULTILINE;
+        }
+        if (optionsAsString.contains("s")) {
+            options |= Pattern.DOTALL;
+        }
+        return options;
+    }
+
+    private boolean extractRepeat(String flagsAsString) {
+        return flagsAsString.contains("r");
+    }
+
+    private String unescapeSubstitutions(String substitutions) {
+        String unescaped = substitutions;
+        if (unescaped.contains("\\r")) {
+            unescaped = unescaped.replaceAll("\\\\r", "\r");
+        }
+        if (unescaped.contains("\\n")) {
+            unescaped = unescaped.replaceAll("\\\\n", "\n");
+        }
+        if (unescaped.contains("\\t")) {
+            unescaped = unescaped.replaceAll("\\\\t", "\t");
+        }
+        return unescaped;
+    }
+
+    public List<ReplacingPattern> getPatternsFromFileList(String filepar) throws MailetException, IOException {
+        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
+        for (String file : Splitter.on(",").split(filepar)) {
+            FileNameWithCharset fileNameWithCharset = FileNameWithCharset.from(file);
+            Optional<? extends InputStream> inputStream = retrieveInputStream(fileNameWithCharset.getFileName());
+            if (inputStream.isPresent()) {
+                patternList.addAll(getPatternsFromStream(inputStream.get(), fileNameWithCharset.getCharset()));
+            }
+        }
+        return patternList.build();
+    }
+
+    private static class FileNameWithCharset {
+
+        public static FileNameWithCharset from(String fileName) {
+            Optional<Integer> charsetOffset = charsetIndex(fileName);
+            if (charsetOffset.isPresent()) {
+                return new FileNameWithCharset(fileName.substring(0, charsetOffset.get()), 
+                        charset(fileName, charsetOffset.get()));
+            }
+            return new FileNameWithCharset(fileName, null);
+        }
+
+        private static Optional<Integer> charsetIndex(String fileName) {
+            int charsetOffset = fileName.lastIndexOf('?');
+            if (charsetOffset >= 0) {
+                return Optional.of(charsetOffset);
+            }
+            return Optional.absent();
+        }
+
+        private static Charset charset(String fileName, int charsetOffset) {
+            return Charset.forName(fileName.substring(charsetOffset + 1));
+        }
+
+        private final String fileName;
+        private final Charset charset;
+
+        private FileNameWithCharset(String fileName, Charset charset) {
+            this.fileName = fileName;
+            this.charset = charset;
+        }
+
+        public String getFileName() {
+            return fileName;
+        }
+
+        public Charset getCharset() {
+            return charset;
+        }
+    }
+
+    private List<ReplacingPattern> getPatternsFromStream(InputStream stream, Charset charset) throws MailetException, IOException {
+        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
+        for (String line: IOUtils.readLines(stream, charset)) {
+            line = line.trim();
+            if (!isComment(line)) {
+                assertPatternSurroundedWithSlashes(line);
+                patternList.add(stripSurroundingSlashes(line.substring(1, line.length() - 1)));
+            }
+        }
+        return patternList.build();
+    }
+
+    private boolean isComment(String line) {
+        return Strings.isNullOrEmpty(line) || line.startsWith("#");
+    }
+
+    private Optional<? extends InputStream> retrieveInputStream(String fileAsString) throws FileNotFoundException {
+        if (fileAsString.startsWith("#")) {
+            return Optional.of(getClass().getResourceAsStream(fileAsString.substring(1)));
+        }
+        File file = new File(fileAsString);
+        if (file.isFile()) {
+            return Optional.of(new FileInputStream(file));
+        }
+        return Optional.absent();
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
index c2d6c42..3656522 100644
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
@@ -19,25 +19,14 @@
 
 package org.apache.james.transport.mailets;
 
-import java.io.File;
-import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
-import java.io.InputStream;
 import java.nio.charset.Charset;
 import java.util.List;
-import java.util.regex.Matcher;
-import java.util.regex.Pattern;
 
-import javax.mail.MessagingException;
-import javax.mail.internet.ContentType;
-import javax.mail.internet.ParseException;
-
-import org.apache.commons.io.IOUtils;
 import org.apache.mailet.Mail;
 import org.apache.mailet.MailetException;
 import org.apache.mailet.base.GenericMailet;
-import org.apache.mailet.base.StringUtils;
 
 import com.google.common.annotations.VisibleForTesting;
 import com.google.common.base.Optional;
@@ -78,7 +67,7 @@ import com.google.common.collect.ImmutableList;
  * </p>
  * 
  * <p>
- * This mailet allow also to enforce the resulting charset for messages processed.
+ * This mailet allow also to enforce the resulting charset for messages processed, when a replacement has been done.
  * To do that the tag &lt;charset&gt; must be specified.
  * </p>
  * 
@@ -101,8 +90,6 @@ public class ReplaceContent extends GenericMailet {
     private static final String PARAMETER_NAME_BODY_PATTERNFILE = "bodyPatternFile";
     private static final String PARAMETER_NAME_CHARSET = "charset";
 
-    public static final int FLAG_REPEAT = 1;
-
     private Optional<Charset> charset;
     private boolean debug;
     @VisibleForTesting ReplaceConfig replaceConfig;
@@ -128,20 +115,17 @@ public class ReplaceContent extends GenericMailet {
     }
 
     private boolean isDebug() {
-        if (Integer.valueOf(getInitParameter("debug", "0")) == 1) {
-            return true;
-        }
-        return false;
+        return Integer.valueOf(getInitParameter("debug", "0")) == 1;
     }
 
     private ReplaceConfig initPatterns() throws MailetException {
         try {
-            ReplaceConfig.Builder builder = ReplaceConfig.builder();
-            initSubjectPattern(builder);
-            initBodyPattern(builder);
-            initSubjectPatternFile(builder);
-            initBodyPatternFile(builder);
-            return builder.build();
+            return ReplaceConfig.builder()
+                    .addAllSubjectReplacingUnits(subjectPattern())
+                    .addAllBodyReplacingUnits(bodyPattern())
+                    .addAllSubjectReplacingUnits(subjectPatternFile())
+                    .addAllBodyReplacingUnits(bodyPatternFile())
+                    .build();
         } catch (FileNotFoundException e) {
             throw new MailetException("Failed initialization", e);
             
@@ -154,227 +138,40 @@ public class ReplaceContent extends GenericMailet {
         }
     }
 
-    private void initSubjectPattern(ReplaceConfig.Builder builder) throws MailetException {
+    private List<ReplacingPattern> subjectPattern() throws MailetException {
         String pattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERN);
         if (pattern != null) {
-            builder.addAllSubjectReplacingUnits(getPatternsFromString(pattern));
+            return new PatternExtractor().getPatternsFromString(pattern);
         }
+        return ImmutableList.of();
     }
 
-    private void initBodyPattern(ReplaceConfig.Builder builder) throws MailetException {
+    private List<ReplacingPattern> bodyPattern() throws MailetException {
         String pattern = getInitParameter(PARAMETER_NAME_BODY_PATTERN);
         if (pattern != null) {
-            builder.addAllBodyReplacingUnits(getPatternsFromString(pattern));
+            return new PatternExtractor().getPatternsFromString(pattern);
         }
+        return ImmutableList.of();
     }
 
-    private void initSubjectPatternFile(ReplaceConfig.Builder builder) throws MailetException, IOException {
+    private List<ReplacingPattern> subjectPatternFile() throws MailetException, IOException {
         String filePattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERNFILE);
         if (filePattern != null) {
-            builder.addAllSubjectReplacingUnits(getPatternsFromFileList(filePattern));
+            return new PatternExtractor().getPatternsFromFileList(filePattern);
         }
+        return ImmutableList.of();
     }
 
-    private void initBodyPatternFile(ReplaceConfig.Builder builder) throws MailetException, IOException {
+    private List<ReplacingPattern> bodyPatternFile() throws MailetException, IOException {
         String filePattern = getInitParameter(PARAMETER_NAME_BODY_PATTERNFILE);
         if (filePattern != null) {
-            builder.addAllBodyReplacingUnits(getPatternsFromFileList(filePattern));
-        }
-    }
-
-    protected static List<ReplacingPattern> getPatternsFromString(String pattern) throws MailetException {
-        String patternProcessing = pattern.trim();
-        ensurePatternIsValid(patternProcessing);
-        patternProcessing = patternProcessing.substring(1, patternProcessing.length() - 1);
-        String[] patternArray = StringUtils.split(patternProcessing, "/,/");
-        
-        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
-        for (String aPatternArray : patternArray) {
-            patternList.add(getPattern(aPatternArray));
-        }
-        return patternList.build();
-    }
-
-    protected static List<ReplacingPattern> getPatternsFromStream(InputStream stream, String charset) throws MailetException, IOException {
-        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
-        for (String line: IOUtils.readLines(stream, charset)) {
-            line = line.trim();
-            if (!Strings.isNullOrEmpty(line) && !line.startsWith("#")) {
-                ensurePatternIsValid(line);
-                patternList.add(getPattern(line.substring(1, line.length() - 1)));
-            }
-        }
-        return patternList.build();
-    }
-
-    private static void ensurePatternIsValid(String pattern) throws MailetException {
-        if (pattern.length() < 2 || (!pattern.startsWith("/") && !pattern.endsWith("/"))) {
-            throw new MailetException("Invalid expression: " + pattern);
-        }
-    }
-
-    private static ReplacingPattern getPattern(String line) throws MailetException {
-        String[] pieces = StringUtils.split(line, "/");
-        if (pieces.length < 3) {
-            throw new MailetException("Invalid expression: " + line);
-        }
-        return new ReplacingPattern(Pattern.compile(pieces[0], extractOptions(pieces[2])), 
-                extractRepeat(pieces[2]), 
-                unescapeSubstitutions(pieces[1]));
-    }
-
-    private static int extractOptions(String optionsAsString) {
-        int options = 0;
-        if (optionsAsString.indexOf('i') >= 0) {
-            options += Pattern.CASE_INSENSITIVE;
-        }
-        if (optionsAsString.indexOf('m') >= 0) {
-            options += Pattern.MULTILINE;
-        }
-        if (optionsAsString.indexOf('s') >= 0) {
-            options += Pattern.DOTALL;
-        }
-        return options;
-    }
-
-    private static boolean extractRepeat(String flagsAsString) {
-        if (flagsAsString.indexOf('r') >= 0) {
-            return true;
-        }
-        return false;
-    }
-
-    private static String unescapeSubstitutions(String substitutions) {
-        String unescaped = substitutions;
-        if (unescaped.contains("\\r")) {
-            unescaped = unescaped.replaceAll("\\\\r", "\r");
-        }
-        if (unescaped.contains("\\n")) {
-            unescaped = unescaped.replaceAll("\\\\n", "\n");
-        }
-        if (unescaped.contains("\\t")) {
-            unescaped = unescaped.replaceAll("\\\\t", "\t");
+            return new PatternExtractor().getPatternsFromFileList(filePattern);
         }
-        return unescaped;
-    }
-
-    /**
-     * @param filepar File path list (or resources if the path starts with #) comma separated
-     */
-    private List<ReplacingPattern> getPatternsFromFileList(String filepar) throws MailetException, IOException {
-        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
-        String[] files = filepar.split(",");
-        for (String file : files) {
-            file = file.trim();
-            if (debug) {
-                log("Loading patterns from: " + file);
-            }
-            String charset = null;
-            int charsetOffset = file.lastIndexOf('?');
-            if (charsetOffset >= 0) {
-                charset = file.substring(charsetOffset + 1);
-                file = file.substring(0, charsetOffset);
-            }
-            Optional<? extends InputStream> inputStream = retrieveInputStream(file);
-            if (inputStream.isPresent()) {
-                patternList.addAll(getPatternsFromStream(inputStream.get(), charset));
-            }
-        }
-        return patternList.build();
-    }
-
-    private Optional<? extends InputStream> retrieveInputStream(String fileAsString) throws FileNotFoundException {
-        if (fileAsString.startsWith("#")) {
-            return Optional.of(getClass().getResourceAsStream(fileAsString.substring(1)));
-        }
-        File file = new File(fileAsString);
-        if (file.isFile()) {
-            return Optional.of(new FileInputStream(file));
-        }
-        return Optional.absent();
-    }
-    
-    protected static String applyPatterns(List<ReplacingPattern> patterns, String text, boolean debug, GenericMailet logOwner) {
-        for (ReplacingPattern replacingPattern : patterns) {
-            boolean changed;
-            do {
-                changed = false;
-                Matcher matcher = replacingPattern.getMatcher().matcher(text);
-                if (matcher.find()) {
-                    String replaced = matcher.replaceAll(replacingPattern.getSubstitution());
-                    if (debug) {
-                        logOwner.log("Subject rule match: " + replacingPattern.getMatcher());
-                    }
-                    text = replaced;
-                    changed = true;
-                }
-            } while (replacingPattern.isRepeat() && changed);
-        }
-        
-        return text;
+        return ImmutableList.of();
     }
 
     @Override
     public void service(Mail mail) throws MailetException {
-        try {
-            boolean subjectChanged = applySubjectReplacingUnits(mail);
-            boolean contentChanged = applyBodyReplacingUnits(mail);
-
-            if (charset.isPresent() && !contentChanged) {
-                mail.getMessage().setContent(mail.getMessage().getContent(), getContentType(mail));
-            }
-
-            if (subjectChanged || contentChanged) {
-                mail.getMessage().saveChanges();
-            }
-        } catch (MessagingException e) {
-            throw new MailetException("Error in replace", e);
-            
-        } catch (IOException e) {
-            throw new MailetException("Error in replace", e);
-        }
-    }
-
-    private boolean applySubjectReplacingUnits(Mail mail) throws MessagingException {
-        if (!replaceConfig.getSubjectReplacingUnits().isEmpty()) {
-            String subject = applyPatterns(replaceConfig.getSubjectReplacingUnits(), 
-                    Strings.nullToEmpty(mail.getMessage().getSubject()), debug, this);
-            if (charset.isPresent()) {
-                mail.getMessage().setSubject(subject, charset.get().name());
-            }
-            else {
-                mail.getMessage().setSubject(subject);
-            }
-            return true;
-        }
-        return false;
-    }
-
-    private boolean applyBodyReplacingUnits(Mail mail) throws IOException, MessagingException, ParseException {
-        if (!replaceConfig.getBodyReplacingUnits().isEmpty()) {
-            Object bodyObj = mail.getMessage().getContent();
-            if (bodyObj instanceof String) {
-                String body = applyPatterns(replaceConfig.getBodyReplacingUnits(), 
-                        Strings.nullToEmpty((String) bodyObj), debug, this);
-                setContent(mail, body);
-                return true;
-            }
-        }
-        return false;
+        new ContentReplacer(debug, this).replaceMailContentAndSubject(mail, replaceConfig, charset);
     }
-
-    private void setContent(Mail mail, String body) throws MessagingException, ParseException {
-        mail.getMessage().setContent(body, getContentType(mail));
-    }
-
-    private String getContentType(Mail mail) throws MessagingException, ParseException {
-        String contentTypeAsString = mail.getMessage().getContentType();
-        if (charset.isPresent()) {
-            ContentType contentType = new ContentType(contentTypeAsString);
-            contentType.setParameter("charset", charset.get().name());
-            return contentType.toString();
-        }
-        return contentTypeAsString;
-    }
-
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/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 d385567..dff16a4 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
@@ -171,7 +171,7 @@ public class StripAttachment extends GenericMailet {
                 getInitParameter(DECODE_FILENAME_PARAMETER_NAME),
                 decodeFilename);
         if (getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME) != null) {
-            filenameReplacingPatterns = ReplaceContent
+            filenameReplacingPatterns = new PatternExtractor()
                     .getPatternsFromString(getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME));
         }
 
@@ -287,7 +287,7 @@ public class StripAttachment extends GenericMailet {
                 fileName = MimeUtility.decodeText(fileName);
 
             if (filenameReplacingPatterns != null)
-                fileName = ReplaceContent.applyPatterns(filenameReplacingPatterns, fileName, false, this);
+                fileName = new ContentReplacer(false, this).applyPatterns(filenameReplacingPatterns, fileName);
 
             if (fileNameMatches(fileName)) {
                 if (directoryName != null) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContentReplacerTest.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContentReplacerTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContentReplacerTest.java
new file mode 100644
index 0000000..0144623
--- /dev/null
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ContentReplacerTest.java
@@ -0,0 +1,151 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.when;
+
+import java.nio.charset.Charset;
+import java.util.regex.Pattern;
+
+import javax.mail.internet.MimeMessage;
+
+import org.apache.mailet.Mail;
+import org.apache.mailet.base.GenericMailet;
+import org.junit.Test;
+
+import com.google.common.base.Charsets;
+import com.google.common.base.Optional;
+import com.google.common.collect.ImmutableList;
+
+public class ContentReplacerTest {
+
+    @Test
+    public void applyPatternsShouldModifyWhenMatching() {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), false, "TEST"),
+            new ReplacingPattern(Pattern.compile("a"), true, "e"),
+            new ReplacingPattern(Pattern.compile("o"), false, "o"));
+        String value = testee.applyPatterns(patterns, "test aa o");
+
+        assertThat(value).isEqualTo("TEST ee o");
+    }
+
+    @Test
+    public void applyPatternsShouldNotRepeatWhenNotAskedFor() {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), false, "TEST"));
+        String value = testee.applyPatterns(patterns, "test test");
+
+        assertThat(value).isEqualTo("TEST test");
+    }
+
+    @Test
+    public void applyPatternsShouldRepeatWhenAskedFor() {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), true, "TEST"));
+        String value = testee.applyPatterns(patterns, "test test");
+
+        assertThat(value).isEqualTo("TEST TEST");
+    }
+
+    @Test
+    public void applyPatternShouldModifyWhenMatchingBody() throws Exception {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        Mail mail = mock(Mail.class);
+        MimeMessage mimeMessage = mock(MimeMessage.class);
+        when(mail.getMessage())
+            .thenReturn(mimeMessage);
+        when(mimeMessage.getContent())
+            .thenReturn("test aa o");
+        when(mimeMessage.getContentType())
+            .thenReturn("text/plain");
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), false, "TEST"),
+            new ReplacingPattern(Pattern.compile("a"), true, "e"),
+            new ReplacingPattern(Pattern.compile("o"), false, "o"));
+        ReplaceConfig replaceConfig = ReplaceConfig.builder()
+                .addAllBodyReplacingUnits(patterns)
+                .build();
+        testee.replaceMailContentAndSubject(mail, replaceConfig, Optional.of(Charsets.UTF_8));
+
+        verify(mimeMessage).setContent("TEST ee o", "text/plain; charset=UTF-8");
+    }
+
+    @Test
+    public void applyPatternShouldModifyWhenMatchingSubject() throws Exception {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        Mail mail = mock(Mail.class);
+        MimeMessage mimeMessage = mock(MimeMessage.class);
+        when(mail.getMessage())
+            .thenReturn(mimeMessage);
+        when(mimeMessage.getSubject())
+            .thenReturn("test aa o");
+        when(mimeMessage.getContentType())
+            .thenReturn("text/plain");
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), false, "TEST"),
+            new ReplacingPattern(Pattern.compile("a"), true, "e"),
+            new ReplacingPattern(Pattern.compile("o"), false, "o"));
+        ReplaceConfig replaceConfig = ReplaceConfig.builder()
+                .addAllSubjectReplacingUnits(patterns)
+                .build();
+        testee.replaceMailContentAndSubject(mail, replaceConfig, Optional.of(Charsets.UTF_8));
+
+        verify(mimeMessage).setSubject("TEST ee o", Charsets.UTF_8.name());
+    }
+
+    @Test
+    public void applyPatternShouldKeepPreviousCharsetWhenNoneSet() throws Exception {
+        GenericMailet mailet = mock(GenericMailet.class);
+        ContentReplacer testee = new ContentReplacer(false, mailet);
+
+        Mail mail = mock(Mail.class);
+        MimeMessage mimeMessage = mock(MimeMessage.class);
+        when(mail.getMessage())
+            .thenReturn(mimeMessage);
+        when(mimeMessage.getSubject())
+            .thenReturn("test aa o");
+        when(mimeMessage.getContentType())
+            .thenReturn("text/plain; charset= UTF-8");
+
+        ImmutableList<ReplacingPattern> patterns = ImmutableList.of(new ReplacingPattern(Pattern.compile("test"), false, "TEST"),
+            new ReplacingPattern(Pattern.compile("a"), true, "e"),
+            new ReplacingPattern(Pattern.compile("o"), false, "o"));
+        ReplaceConfig replaceConfig = ReplaceConfig.builder()
+                .addAllSubjectReplacingUnits(patterns)
+                .build();
+        testee.replaceMailContentAndSubject(mail, replaceConfig, Optional.<Charset> absent());
+
+        verify(mimeMessage).setSubject("TEST ee o", Charsets.UTF_8.name());
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/test/java/org/apache/james/transport/mailets/PatternExtractorTest.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/PatternExtractorTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/PatternExtractorTest.java
new file mode 100644
index 0000000..72ab701
--- /dev/null
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/PatternExtractorTest.java
@@ -0,0 +1,103 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+import java.util.List;
+import java.util.regex.Pattern;
+
+import org.apache.mailet.MailetException;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+public class PatternExtractorTest {
+
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
+
+    private PatternExtractor testee;
+
+    @Before
+    public void setup() {
+        testee = new PatternExtractor();
+    }
+
+    @Test
+    public void getPatternsFromStringShouldReturnValuesWhenMultiplePatterns() throws Exception {
+        List<ReplacingPattern> patternsFromString = testee.getPatternsFromString("/test/TEST/i/,/a/e//,/o/o/ir/");
+
+        assertThat(patternsFromString).containsOnly(
+                new ReplacingPattern(Pattern.compile("test"), false, "TEST"),
+                new ReplacingPattern(Pattern.compile("a"), false, "e"),
+                new ReplacingPattern(Pattern.compile("o"), true, "o"));
+    }
+
+    @Test
+    public void getPatternsFromFileListShouldReturnValuesWhenMultiplePatterns() throws Exception {
+        List<ReplacingPattern> patternsFromFileList = testee.getPatternsFromFileList("#/org/apache/james/mailet/standard/mailets/replaceSubject.patterns");
+
+        assertThat(patternsFromFileList).containsOnly(
+                new ReplacingPattern(Pattern.compile("re:[ ]*"), false, "Re: "),
+                new ReplacingPattern(Pattern.compile("ri:[ ]*"), false, "Re: "),
+                new ReplacingPattern(Pattern.compile("r:[ ]*"), false, "Re: "));
+    }
+
+    @Test
+    public void getPatternsFromStringShouldThrowWhenPatternIsLessThanTwoCharacters() throws Exception {
+        expectedException.expect(MailetException.class);
+
+        testee.getPatternsFromString("a");
+    }
+
+    @Test
+    public void getPatternsFromStringShouldThrowWhenPatternDoesNotStartWithSlash() throws Exception {
+        expectedException.expect(MailetException.class);
+
+        testee.getPatternsFromString("abc/");
+    }
+
+    @Test
+    public void getPatternsFromStringShouldThrowWhenPatternDoesNotEndWithSlash() throws Exception {
+        expectedException.expect(MailetException.class);
+
+        testee.getPatternsFromString("/abc");
+    }
+
+    @Test
+    public void serviceShouldUnescapeCarriageReturn() throws Exception {
+        List<ReplacingPattern> patternsFromString = testee.getPatternsFromString("/a/\\\\r/i/");
+        assertThat(patternsFromString).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\r"));
+    }
+
+    @Test
+    public void serviceShouldUnescapeLineBreak() throws Exception {
+        List<ReplacingPattern> patternsFromString = testee.getPatternsFromString("/a/\\\\n/i/");
+        assertThat(patternsFromString).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\n"));
+    }
+
+    @Test
+    public void serviceShouldUnescapeTabReturn() throws Exception {
+        List<ReplacingPattern> patternsFromString = testee.getPatternsFromString("/a/\\\\t/i/");
+        assertThat(patternsFromString).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\t"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
index caacd51..a258fb8 100644
--- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
@@ -23,13 +23,11 @@ import static org.assertj.core.api.Assertions.assertThat;
 
 import java.io.ByteArrayInputStream;
 import java.util.Properties;
-import java.util.regex.Pattern;
 
 import javax.mail.Session;
 import javax.mail.internet.MimeMessage;
 
 import org.apache.mailet.Mail;
-import org.apache.mailet.MailetException;
 import org.apache.mailet.base.test.FakeMail;
 import org.apache.mailet.base.test.FakeMailContext;
 import org.apache.mailet.base.test.FakeMailetConfig;
@@ -60,90 +58,53 @@ public class ReplaceContentTest {
     }
 
     @Test
-    public void serviceShouldThrowWhenPatternIsLessThanTwoCharacters() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "a");
-        expectedException.expect(MailetException.class);
-
-        mailet.init(mailetConfig);
-    }
-
-    @Test
-    public void serviceShouldThrowWhenPatternDoesNotStartWithSlash() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "abc/");
-        expectedException.expect(MailetException.class);
-
-        mailet.init(mailetConfig);
-    }
-
-    @Test
-    public void serviceShouldThrowWhenPatternDoesNotEndWithSlash() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/abc");
-        expectedException.expect(MailetException.class);
-
-        mailet.init(mailetConfig);
-    }
-
-    @Test
-    public void serviceShouldUnescapeCarriageReturn() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/a/\\\\r/i/");
-
+    public void serviceShouldReplaceSubjectWhenMatching() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/test/TEST/i/,/o/a//,/s/s/i/");
         mailet.init(mailetConfig);
-        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\r"));
-    }
-
-    @Test
-    public void serviceShouldUnescapeLineBreak() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/a/\\\\n/i/");
 
-        mailet.init(mailetConfig);
-        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\n"));
-    }
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        message.setSubject("one test");
 
-    @Test
-    public void serviceShouldUnescapeTabReturn() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/a/\\\\t/i/");
+        Mail mail = new FakeMail(message);
+        mailet.service(mail);
 
-        mailet.init(mailetConfig);
-        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\t"));
+        assertThat(mail.getMessage().getSubject()).isEqualTo("ane TEsT");
     }
 
     @Test
-    public void serviceShouldReplaceSubjectWhenMatching() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
-        mailetConfig.setProperty("bodyPattern", "/prova/PROVA/i/," + "/a/e//,"
-                + "/o/o/i/,/\\u00E8/e'//," + "/prova([^\\/]*?)ble/X$1Y/im/,"
-                + "/X(.\\n)Y/P$1Q//," + "/\\/\\/,//");
+    public void serviceShouldReplaceBodyWhenMatching() throws Exception {
+        mailetConfig.setProperty("bodyPattern", 
+                "/test/TEST/i/," +
+                "/o/a/r/," +
+                "/S/s/r/,/\\u00E8/e'//," +
+                "/test([^\\/]*?)bla/X$1Y/im/," +
+                "/X(.\\n)Y/P$1Q//," +
+                "/\\/\\/,//");
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("una prova");
-        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
-                + "Bla bla bla bla.\n");
+        message.setText("This is one simple test/ \u00E8 one simple test.\n"
+                + "Blo blo blo blo.\n");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getSubject()).isEqualTo("une PRoVA");
+        assertThat(mail.getMessage().getContent()).isEqualTo("This is ane simple TEsT, e' ane simple P.\n"
+                + "Q bla bla bla.\n");
     }
 
     @Test
-    public void serviceShouldReplaceBodyWhenMatching() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
-        mailetConfig.setProperty("bodyPattern", "/prova/PROVA/i/," + "/a/e//,"
-                + "/o/o/i/,/\\u00E8/e'//," + "/prova([^\\/]*?)ble/X$1Y/im/,"
-                + "/X(.\\n)Y/P$1Q//," + "/\\/\\/,//");
+    public void serviceShouldNotLoopWhenCaseInsensitiveAndRepeat() throws Exception {
+        mailetConfig.setProperty("bodyPattern", "/a/a/ir/");
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("una prova");
-        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
-                + "Bla bla bla bla.\n");
+        message.setText("aaa");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getContent()).isEqualTo("Sto fecendo une PRoVA di scritture, e' solo une P.\n"
-                + "Q ble ble ble.\n");
+        assertThat(mail.getMessage().getContent()).isEqualTo("aaa");
     }
 
     @Test
@@ -152,51 +113,48 @@ public class ReplaceContentTest {
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("re: r:ri:una prova");
-        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
-                + "Bla bla bla bla.\n");
+        message.setSubject("re: r:ri:one test");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getSubject()).isEqualTo("Re: Re: Re: una prova");
+        assertThat(mail.getMessage().getSubject()).isEqualTo("Re: Re: Re: one test");
     }
 
     @Test
     public void serviceShouldRemoveOrAddTextInBody() throws Exception {
-        mailetConfig.setProperty("bodyPattern", "/--messaggio originale--/<quote>/i/,"
+        mailetConfig.setProperty("bodyPattern", "/--original message--/<quote>/i/,"
                 + "/<quote>(.*)(\\r\\n)([^>]+)/<quote>$1$2>$3/imrs/,"
                 + "/<quote>\\r\\n//im/");
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("una prova");
-        message.setText("Prova.\r\n" + "\r\n" + "--messaggio originale--\r\n"
-                + "parte del\r\n" + "messaggio\\ che\\0 deve0 essere\r\n"
-                + "quotato. Vediamo se\r\n" + "ce la fa.");
+        message.setText("Test.\r\n" + "\r\n" + "--original message--\r\n"
+                + "part of\r\n" + "message\\ that\\0 must0 be\r\n"
+                + "quoted. Let's see if\r\n" + "he can do it.");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getContent()).isEqualTo("Prova.\r\n" + "\r\n" + ">parte del\r\n"
-                + ">messaggio\\ che\\0 deve0 essere\r\n"
-                + ">quotato. Vediamo se\r\n" + ">ce la fa.");
+        assertThat(mail.getMessage().getContent()).isEqualTo("Test.\r\n" + "\r\n" + ">part of\r\n"
+                + ">message\\ that\\0 must0 be\r\n"
+                + ">quoted. Let's see if\r\n" + ">he can do it.");
     }
 
 
     @Test
     public void serviceShouldReplaceBodyWhenMatchingASCIICharacter() throws Exception {
-        mailetConfig.setProperty("bodyPattern", "/\\u2026/...//");
+        mailetConfig.setProperty("bodyPattern", "/\\u2026/.../r/");
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("una prova");
-        message.setText("Prova \u2026 di replace \u2026");
+        message.setSubject("one test");
+        message.setText("Replacement \u2026 one test \u2026");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getContent()).isEqualTo("Prova ... di replace ...");
+        assertThat(mail.getMessage().getContent()).isEqualTo("Replacement ... one test ...");
     }
 
     @Test
@@ -204,11 +162,11 @@ public class ReplaceContentTest {
         String messageSource = "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"
                 + "Content-Transfer-Encoding: quoted-printable\r\n"
                 + "\r\n"
-                + "=93prova=94 con l=92apice";
+                + "=93test=94 with th=92 apex";
 
         mailetConfig.setProperty("bodyPattern", "/[\\u2018\\u2019\\u201A]/'//,"
                 + "/[\\u201C\\u201D\\u201E]/\"//," + "/[\\x91\\x92\\x82]/'//,"
-                + "/[\\x93\\x94\\x84]/\"//," + "/\\x85/...//," + "/\\x8B/<//,"
+                + "/[\\x93\\x94\\x84]/\"/r/," + "/\\x85/...//," + "/\\x8B/<//,"
                 + "/\\x9B/>//," + "/\\x96/-//," + "/\\x97/--//,");
         mailet.init(mailetConfig);
 
@@ -218,19 +176,19 @@ public class ReplaceContentTest {
         Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        assertThat(mail.getMessage().getContent()).isEqualTo("\"prova\" con l'apice");
+        assertThat(mail.getMessage().getContent()).isEqualTo("\"test\" with th' apex");
     }
 
     @Test
     public void serviceShouldSetContenTypeWhenInitialized() throws Exception {
-        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
+        mailetConfig.setProperty("subjectPattern", "/test/TEST/i/,/o/a//,/s/s/i/");
         mailetConfig.setProperty("charset", Charsets.UTF_8.name());
         mailet.init(mailetConfig);
 
         MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
-        message.setSubject("una prova");
-        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
-                + "Bla bla bla bla.\n");
+        message.setSubject("one test");
+        message.setText("This is one simple test/ \u00E8 one simple test.\n"
+                + "Blo blo blo blo.\n");
 
         Mail mail = new FakeMail(message);
         mailet.service(mail);

http://git-wip-us.apache.org/repos/asf/james-project/blob/ef80d94a/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 7c8dd71..a36bc11 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
@@ -354,11 +354,11 @@ public class StripAttachmentTest {
                         + "/[\u00D7]/x//," + "/[\u00D9\u00DA\u00DB\u00DC]/U//,"
                         + "/[\u00E0\u00E1\u00E2\u00E3\u00E4\u00E5]/a//,"
                         + "/[\u00E6]/ae//,"
-                        + "/[\u00E8\u00E9\u00EA\u00EB]/e//,"
+                        + "/[\u00E8\u00E9\u00EA\u00EB]/e/r/,"
                         + "/[\u00EC\u00ED\u00EE\u00EF]/i//,"
                         + "/[\u00F2\u00F3\u00F4\u00F5\u00F6]/o//,"
                         + "/[\u00F9\u00FA\u00FB\u00FC]/u//,"
-                        + "/[^A-Za-z0-9._-]+/_//");
+                        + "/[^A-Za-z0-9._-]+/_/r/");
 
         mailet.init(mci);
         return mailet;


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[3/3] james-project git commit: Merge remote-tracking branch 'aduprat/MAILET-110'

Posted by ro...@apache.org.
Merge remote-tracking branch 'aduprat/MAILET-110'


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/baae24e2
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/baae24e2
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/baae24e2

Branch: refs/heads/master
Commit: baae24e231edc543e61a9515eadb98f4bcb57dcb
Parents: 35c5415 ef80d94
Author: Raphael Ouazana <ra...@linagora.com>
Authored: Wed Sep 7 13:59:27 2016 +0200
Committer: Raphael Ouazana <ra...@linagora.com>
Committed: Wed Sep 7 13:59:27 2016 +0200

----------------------------------------------------------------------
 .../transport/mailets/ContentReplacer.java      | 147 +++++++++
 .../james/transport/mailets/PatternBean.java    |  64 ----
 .../transport/mailets/PatternExtractor.java     | 188 +++++++++++
 .../james/transport/mailets/PatternList.java    |  58 ----
 .../james/transport/mailets/ReplaceConfig.java  |  72 +++++
 .../james/transport/mailets/ReplaceContent.java | 313 +++++--------------
 .../transport/mailets/ReplacingPattern.java     |  75 +++++
 .../transport/mailets/StripAttachment.java      |  20 +-
 .../transport/mailets/ContentReplacerTest.java  | 151 +++++++++
 .../transport/mailets/PatternExtractorTest.java | 103 ++++++
 .../transport/mailets/ReplaceContentTest.java   | 206 +++++++-----
 .../transport/mailets/StripAttachmentTest.java  |   4 +-
 12 files changed, 935 insertions(+), 466 deletions(-)
----------------------------------------------------------------------



---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org


[2/3] james-project git commit: MAILET-110 Refactor ReplaceContent

Posted by ro...@apache.org.
MAILET-110 Refactor ReplaceContent


Project: http://git-wip-us.apache.org/repos/asf/james-project/repo
Commit: http://git-wip-us.apache.org/repos/asf/james-project/commit/af067c68
Tree: http://git-wip-us.apache.org/repos/asf/james-project/tree/af067c68
Diff: http://git-wip-us.apache.org/repos/asf/james-project/diff/af067c68

Branch: refs/heads/master
Commit: af067c6877e1edd810e19d484ce99f295389ef19
Parents: 39d0cda
Author: Antoine Duprat <ad...@linagora.com>
Authored: Mon Aug 29 16:13:14 2016 +0200
Committer: Antoine Duprat <ad...@linagora.com>
Committed: Wed Sep 7 10:35:09 2016 +0200

----------------------------------------------------------------------
 .../james/transport/mailets/PatternBean.java    |  64 ---
 .../james/transport/mailets/PatternList.java    |  58 ---
 .../james/transport/mailets/ReplaceConfig.java  |  72 +++
 .../james/transport/mailets/ReplaceContent.java | 458 ++++++++++---------
 .../transport/mailets/ReplacingPattern.java     |  75 +++
 .../transport/mailets/StripAttachment.java      |  20 +-
 .../transport/mailets/ReplaceContentTest.java   | 212 ++++++---
 7 files changed, 542 insertions(+), 417 deletions(-)
----------------------------------------------------------------------


http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternBean.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternBean.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternBean.java
deleted file mode 100644
index 4836d6a..0000000
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternBean.java
+++ /dev/null
@@ -1,64 +0,0 @@
-/****************************************************************
- * 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.james.transport.mailets;
-
-import java.util.regex.Pattern;
-
-/**
- * A data helper bean holding patterns, substitutions and flags
- */
-public class PatternBean {
-
-    private Pattern patterns = null;
-    private String substitutions = null;
-    private Integer flag = null;
-
-    public PatternBean(Pattern patterns, String substitutions, Integer flag) {
-        super();
-        this.patterns = patterns;
-        this.substitutions = substitutions;
-        this.flag = flag;
-    }
-
-    public Pattern getPatterns() {
-        return patterns;
-    }
-
-    public void setPatterns(Pattern patterns) {
-        this.patterns = patterns;
-    }
-
-    public String getSubstitutions() {
-        return substitutions;
-    }
-
-    public void setSubstitutions(String substitutions) {
-        this.substitutions = substitutions;
-    }
-
-    public Integer getFlag() {
-        return flag;
-    }
-
-    public void setFlag(Integer flag) {
-        this.flag = flag;
-    }
-
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternList.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternList.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternList.java
deleted file mode 100644
index 7fc7143..0000000
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/PatternList.java
+++ /dev/null
@@ -1,58 +0,0 @@
-/****************************************************************
- * 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.james.transport.mailets;
-
-import java.util.ArrayList;
-import java.util.List;
-import java.util.regex.Pattern;
-
-/**
- * A data helper bean holding a lists of patterns, substitutions and flags
- */
-public class PatternList {
-
-    private List<Pattern> patterns = new ArrayList<Pattern>();
-    private List<String> substitutions = new ArrayList<String>();
-    private List<Integer> flags = new ArrayList<Integer>();
-
-    public List<Pattern> getPatterns() {
-        return patterns;
-    }
-
-    public void setPatterns(List<Pattern> patterns) {
-        this.patterns = patterns;
-    }
-
-    public List<String> getSubstitutions() {
-        return substitutions;
-    }
-
-    public void setSubstitutions(List<String> substitutions) {
-        this.substitutions = substitutions;
-    }
-
-    public List<Integer> getFlags() {
-        return flags;
-    }
-
-    public void setFlags(List<Integer> flags) {
-        this.flags = flags;
-    }
-}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceConfig.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceConfig.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceConfig.java
new file mode 100644
index 0000000..5f867f5
--- /dev/null
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceConfig.java
@@ -0,0 +1,72 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import java.util.List;
+
+import com.google.common.collect.ImmutableList;
+
+public class ReplaceConfig {
+
+    public static ReplaceConfig.Builder builder() {
+        return new Builder();
+    }
+
+    public static class Builder {
+
+        private ImmutableList.Builder<ReplacingPattern> subjectReplacingUnits;
+        private ImmutableList.Builder<ReplacingPattern> bodyReplacingUnits;
+
+        private Builder() {
+            subjectReplacingUnits = ImmutableList.builder();
+            bodyReplacingUnits = ImmutableList.builder();
+        }
+
+        public ReplaceConfig.Builder addAllSubjectReplacingUnits(List<ReplacingPattern> subjectReplacingUnits) {
+            this.subjectReplacingUnits.addAll(subjectReplacingUnits);
+            return this;
+        }
+
+        public ReplaceConfig.Builder addAllBodyReplacingUnits(List<ReplacingPattern> bodyReplacingUnits) {
+            this.bodyReplacingUnits.addAll(bodyReplacingUnits);
+            return this;
+        }
+
+        public ReplaceConfig build() {
+            return new ReplaceConfig(subjectReplacingUnits.build(), bodyReplacingUnits.build());
+        }
+    }
+
+    private final List<ReplacingPattern> subjectReplacingUnits;
+    private final List<ReplacingPattern> bodyReplacingUnits;
+
+    public ReplaceConfig(List<ReplacingPattern> subjectReplacingUnits, List<ReplacingPattern> bodyReplacingUnits) {
+        this.subjectReplacingUnits = subjectReplacingUnits;
+        this.bodyReplacingUnits = bodyReplacingUnits;
+    }
+
+    public List<ReplacingPattern> getSubjectReplacingUnits() {
+        return subjectReplacingUnits;
+    }
+
+    public List<ReplacingPattern> getBodyReplacingUnits() {
+        return bodyReplacingUnits;
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
index e52a41a..c2d6c42 100644
--- a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplaceContent.java
@@ -19,25 +19,31 @@
 
 package org.apache.james.transport.mailets;
 
-import org.apache.mailet.base.StringUtils;
-import org.apache.mailet.base.GenericMailet;
-import org.apache.mailet.Mail;
-import org.apache.mailet.MailetException;
-
-import javax.mail.MessagingException;
-import javax.mail.internet.ContentType;
-
-import java.io.BufferedReader;
 import java.io.File;
 import java.io.FileInputStream;
 import java.io.FileNotFoundException;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
-import java.util.ArrayList;
+import java.nio.charset.Charset;
 import java.util.List;
+import java.util.regex.Matcher;
 import java.util.regex.Pattern;
 
+import javax.mail.MessagingException;
+import javax.mail.internet.ContentType;
+import javax.mail.internet.ParseException;
+
+import org.apache.commons.io.IOUtils;
+import org.apache.mailet.Mail;
+import org.apache.mailet.MailetException;
+import org.apache.mailet.base.GenericMailet;
+import org.apache.mailet.base.StringUtils;
+
+import com.google.common.annotations.VisibleForTesting;
+import com.google.common.base.Optional;
+import com.google.common.base.Strings;
+import com.google.common.collect.ImmutableList;
+
 /**
  * Replace text contents
  * <p>This mailet allow to specific regular expression to replace text in subject and content.
@@ -88,263 +94,287 @@ import java.util.regex.Pattern;
  * </p>
  */
 public class ReplaceContent extends GenericMailet {
+
     private static final String PARAMETER_NAME_SUBJECT_PATTERN = "subjectPattern";
     private static final String PARAMETER_NAME_BODY_PATTERN = "bodyPattern";
     private static final String PARAMETER_NAME_SUBJECT_PATTERNFILE = "subjectPatternFile";
     private static final String PARAMETER_NAME_BODY_PATTERNFILE = "bodyPatternFile";
     private static final String PARAMETER_NAME_CHARSET = "charset";
-    
+
     public static final int FLAG_REPEAT = 1;
-    
-    private static class ReplaceConfig {
-        private Pattern[] subjectPatterns;
-        private String[] subjectSubstitutions;
-        private Integer[] subjectFlags;
-        private Pattern[] bodyPatterns;
-        private String[] bodySubstitutions;
-        private Integer[] bodyFlags;
-    }
-    
-    private String charset;
-    private int debug = 0;
-    
-    /**
-     * returns a String describing this mailet.
-     * 
-     * @return A desciption of this mailet
-     */
+
+    private Optional<Charset> charset;
+    private boolean debug;
+    @VisibleForTesting ReplaceConfig replaceConfig;
+
+    @Override
     public String getMailetInfo() {
         return "ReplaceContent";
     }
 
-    /**
-     * @return an array containing Pattern and Substitution of the input stream
-     * @throws MailetException 
-     */
-    protected static PatternBean getPattern(String line) throws MailetException {
-        String[] pieces = StringUtils.split(line, "/");
-        if (pieces.length < 3) throw new MailetException("Invalid expression: " + line);
-        int options = 0;
-        //if (pieces[2].indexOf('x') >= 0) options += Pattern.EXTENDED;
-        if (pieces[2].indexOf('i') >= 0) options += Pattern.CASE_INSENSITIVE;
-        if (pieces[2].indexOf('m') >= 0) options += Pattern.MULTILINE;
-        if (pieces[2].indexOf('s') >= 0) options += Pattern.DOTALL;
-        
-        int flags = 0;
-        if (pieces[2].indexOf('r') >= 0) flags += FLAG_REPEAT;
-        
-        if (pieces[1].contains("\\r")) pieces[1] = pieces[1].replaceAll("\\\\r", "\r");
-        if (pieces[1].contains("\\n")) pieces[1] = pieces[1].replaceAll("\\\\n", "\n");
-        if (pieces[1].contains("\\t")) pieces[1] = pieces[1].replaceAll("\\\\t", "\t");
+    @Override
+    public void init() throws MailetException {
+        charset = initCharset();
+        debug = isDebug();
+        replaceConfig = initPatterns();
+    }
 
-        return new PatternBean (Pattern.compile(pieces[0], options), pieces[1] , flags);
+    private Optional<Charset> initCharset() {
+        String charsetName = getInitParameter(PARAMETER_NAME_CHARSET);
+        if (Strings.isNullOrEmpty(charsetName)) {
+            return Optional.absent();
+        }
+        return Optional.of(Charset.forName(charsetName));
     }
-    
-    protected static PatternList getPatternsFromString(String pattern) throws MailetException {
-        pattern = pattern.trim();
-        if (pattern.length() < 2 && !pattern.startsWith("/") && !pattern.endsWith("/")) throw new MailetException("Invalid parameter value: " + PARAMETER_NAME_SUBJECT_PATTERN);
-        pattern = pattern.substring(1, pattern.length() - 1);
-        String[] patternArray = StringUtils.split(pattern, "/,/");
+
+    private boolean isDebug() {
+        if (Integer.valueOf(getInitParameter("debug", "0")) == 1) {
+            return true;
+        }
+        return false;
+    }
+
+    private ReplaceConfig initPatterns() throws MailetException {
+        try {
+            ReplaceConfig.Builder builder = ReplaceConfig.builder();
+            initSubjectPattern(builder);
+            initBodyPattern(builder);
+            initSubjectPatternFile(builder);
+            initBodyPatternFile(builder);
+            return builder.build();
+        } catch (FileNotFoundException e) {
+            throw new MailetException("Failed initialization", e);
+            
+        } catch (MailetException e) {
+            throw new MailetException("Failed initialization", e);
+            
+        } catch (IOException e) {
+            throw new MailetException("Failed initialization", e);
+            
+        }
+    }
+
+    private void initSubjectPattern(ReplaceConfig.Builder builder) throws MailetException {
+        String pattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERN);
+        if (pattern != null) {
+            builder.addAllSubjectReplacingUnits(getPatternsFromString(pattern));
+        }
+    }
+
+    private void initBodyPattern(ReplaceConfig.Builder builder) throws MailetException {
+        String pattern = getInitParameter(PARAMETER_NAME_BODY_PATTERN);
+        if (pattern != null) {
+            builder.addAllBodyReplacingUnits(getPatternsFromString(pattern));
+        }
+    }
+
+    private void initSubjectPatternFile(ReplaceConfig.Builder builder) throws MailetException, IOException {
+        String filePattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERNFILE);
+        if (filePattern != null) {
+            builder.addAllSubjectReplacingUnits(getPatternsFromFileList(filePattern));
+        }
+    }
+
+    private void initBodyPatternFile(ReplaceConfig.Builder builder) throws MailetException, IOException {
+        String filePattern = getInitParameter(PARAMETER_NAME_BODY_PATTERNFILE);
+        if (filePattern != null) {
+            builder.addAllBodyReplacingUnits(getPatternsFromFileList(filePattern));
+        }
+    }
+
+    protected static List<ReplacingPattern> getPatternsFromString(String pattern) throws MailetException {
+        String patternProcessing = pattern.trim();
+        ensurePatternIsValid(patternProcessing);
+        patternProcessing = patternProcessing.substring(1, patternProcessing.length() - 1);
+        String[] patternArray = StringUtils.split(patternProcessing, "/,/");
         
-        PatternList patternList= new PatternList();
+        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
         for (String aPatternArray : patternArray) {
-            PatternBean o = getPattern(aPatternArray);
-            patternList.getPatterns().add(o.getPatterns());
-            patternList.getSubstitutions().add(o.getSubstitutions());
-            patternList.getFlags().add(o.getFlag());
+            patternList.add(getPattern(aPatternArray));
         }
-        
-        return patternList;
+        return patternList.build();
     }
 
-    protected static PatternList getPatternsFromStream(InputStream stream, String charset) throws MailetException, IOException {
-        PatternList patternList= new PatternList();
-        BufferedReader reader = new BufferedReader(charset != null ? new InputStreamReader(stream, charset) : new InputStreamReader(stream));
-        //BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream("q:\\correzioniout"), "utf-8"));
-        
-        String line;
-        while ((line = reader.readLine()) != null) {
+    protected static List<ReplacingPattern> getPatternsFromStream(InputStream stream, String charset) throws MailetException, IOException {
+        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
+        for (String line: IOUtils.readLines(stream, charset)) {
             line = line.trim();
-            if (line.length() > 0 && !line.startsWith("#")) {
-                if (line.length() < 2 && !line.startsWith("/") && !line.endsWith("/")) throw new MailetException("Invalid expression: " + line);
-                PatternBean o = getPattern(line.substring(1, line.length() - 1));
-                patternList.getPatterns().add(o.getPatterns());
-                patternList.getSubstitutions().add(o.getSubstitutions());
-                patternList.getFlags().add(o.getFlag());
+            if (!Strings.isNullOrEmpty(line) && !line.startsWith("#")) {
+                ensurePatternIsValid(line);
+                patternList.add(getPattern(line.substring(1, line.length() - 1)));
             }
         }
-        reader.close();
-        return patternList;
+        return patternList.build();
     }
-    
+
+    private static void ensurePatternIsValid(String pattern) throws MailetException {
+        if (pattern.length() < 2 || (!pattern.startsWith("/") && !pattern.endsWith("/"))) {
+            throw new MailetException("Invalid expression: " + pattern);
+        }
+    }
+
+    private static ReplacingPattern getPattern(String line) throws MailetException {
+        String[] pieces = StringUtils.split(line, "/");
+        if (pieces.length < 3) {
+            throw new MailetException("Invalid expression: " + line);
+        }
+        return new ReplacingPattern(Pattern.compile(pieces[0], extractOptions(pieces[2])), 
+                extractRepeat(pieces[2]), 
+                unescapeSubstitutions(pieces[1]));
+    }
+
+    private static int extractOptions(String optionsAsString) {
+        int options = 0;
+        if (optionsAsString.indexOf('i') >= 0) {
+            options += Pattern.CASE_INSENSITIVE;
+        }
+        if (optionsAsString.indexOf('m') >= 0) {
+            options += Pattern.MULTILINE;
+        }
+        if (optionsAsString.indexOf('s') >= 0) {
+            options += Pattern.DOTALL;
+        }
+        return options;
+    }
+
+    private static boolean extractRepeat(String flagsAsString) {
+        if (flagsAsString.indexOf('r') >= 0) {
+            return true;
+        }
+        return false;
+    }
+
+    private static String unescapeSubstitutions(String substitutions) {
+        String unescaped = substitutions;
+        if (unescaped.contains("\\r")) {
+            unescaped = unescaped.replaceAll("\\\\r", "\r");
+        }
+        if (unescaped.contains("\\n")) {
+            unescaped = unescaped.replaceAll("\\\\n", "\n");
+        }
+        if (unescaped.contains("\\t")) {
+            unescaped = unescaped.replaceAll("\\\\t", "\t");
+        }
+        return unescaped;
+    }
+
     /**
      * @param filepar File path list (or resources if the path starts with #) comma separated
      */
-    private PatternList getPatternsFromFileList(String filepar) throws MailetException, IOException {
-        PatternList patternList= new PatternList();
+    private List<ReplacingPattern> getPatternsFromFileList(String filepar) throws MailetException, IOException {
+        ImmutableList.Builder<ReplacingPattern> patternList= ImmutableList.builder();
         String[] files = filepar.split(",");
-        for (int i = 0; i < files.length; i++) {
-            files[i] = files[i].trim();
-            if (debug > 0) log("Loading patterns from: " + files[i]);
-            String charset = null;
-            int pc = files[i].lastIndexOf('?');
-            if (pc >= 0) {
-                charset = files[i].substring(pc + 1);
-                files[i] = files[i].substring(0, pc);
+        for (String file : files) {
+            file = file.trim();
+            if (debug) {
+                log("Loading patterns from: " + file);
             }
-            InputStream is = null;
-            if (files[i].startsWith("#")) is = getClass().getResourceAsStream(files[i].substring(1));
-            else {
-                File f = new File(files[i]);
-                if (f.isFile()) is = new FileInputStream(f);
+            String charset = null;
+            int charsetOffset = file.lastIndexOf('?');
+            if (charsetOffset >= 0) {
+                charset = file.substring(charsetOffset + 1);
+                file = file.substring(0, charsetOffset);
             }
-            if (is != null) {
-                PatternList o = getPatternsFromStream(is, charset);
-                patternList.getPatterns().addAll(o.getPatterns());
-                patternList.getSubstitutions().addAll(o.getSubstitutions());
-                patternList.getFlags().addAll(o.getFlags());
-                is.close();
+            Optional<? extends InputStream> inputStream = retrieveInputStream(file);
+            if (inputStream.isPresent()) {
+                patternList.addAll(getPatternsFromStream(inputStream.get(), charset));
             }
         }
-        return patternList;
+        return patternList.build();
+    }
+
+    private Optional<? extends InputStream> retrieveInputStream(String fileAsString) throws FileNotFoundException {
+        if (fileAsString.startsWith("#")) {
+            return Optional.of(getClass().getResourceAsStream(fileAsString.substring(1)));
+        }
+        File file = new File(fileAsString);
+        if (file.isFile()) {
+            return Optional.of(new FileInputStream(file));
+        }
+        return Optional.absent();
     }
     
-    protected static String applyPatterns(Pattern[] patterns, String[] substitutions, Integer[] pflags, String text, int debug, GenericMailet logOwner) {
-        for (int i = 0; i < patterns.length; i ++) {
-            int flags = pflags[i];
+    protected static String applyPatterns(List<ReplacingPattern> patterns, String text, boolean debug, GenericMailet logOwner) {
+        for (ReplacingPattern replacingPattern : patterns) {
             boolean changed;
             do {
                 changed = false;
-                String replaced = patterns[i].matcher(text).replaceAll(substitutions[i]);
-                if (!replaced.equals(text)) {
-                    if (debug > 0) logOwner.log("Subject rule match: " + patterns[i].pattern());
+                Matcher matcher = replacingPattern.getMatcher().matcher(text);
+                if (matcher.find()) {
+                    String replaced = matcher.replaceAll(replacingPattern.getSubstitution());
+                    if (debug) {
+                        logOwner.log("Subject rule match: " + replacingPattern.getMatcher());
+                    }
                     text = replaced;
                     changed = true;
                 }
-            } while ((flags & FLAG_REPEAT) > 0 && changed);
+            } while (replacingPattern.isRepeat() && changed);
         }
         
         return text;
     }
-    
 
-    public void init() throws MailetException {
-        charset = getInitParameter(PARAMETER_NAME_CHARSET);
-        debug = Integer.parseInt(getInitParameter("debug", "0"));
-    }
-    
-    private ReplaceConfig initPatterns() throws MailetException {
+    @Override
+    public void service(Mail mail) throws MailetException {
         try {
-            List<Pattern> bodyPatternsList = new ArrayList<Pattern>();
-            List<String> bodySubstitutionsList = new ArrayList<String>();
-            List<Integer> bodyFlagsList = new ArrayList<Integer>();
-            List<Pattern> subjectPatternsList = new ArrayList<Pattern>();
-            List<String> subjectSubstitutionsList = new ArrayList<String>();
-            List<Integer> subjectFlagsList = new ArrayList<Integer>();
-
-            String pattern = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERN);
-            if (pattern != null) {
-                PatternList o = getPatternsFromString(pattern);
-                subjectPatternsList.addAll(o.getPatterns());
-                subjectSubstitutionsList.addAll(o.getSubstitutions());
-                subjectFlagsList.addAll(o.getFlags());
-            }
-            
-            pattern = getInitParameter(PARAMETER_NAME_BODY_PATTERN);
-            if (pattern != null) {
-                PatternList o = getPatternsFromString(pattern);
-                bodyPatternsList.addAll(o.getPatterns());
-                bodySubstitutionsList.addAll(o.getSubstitutions());
-                bodyFlagsList.addAll(o.getFlags());
-            }
-            
-            String filepar = getInitParameter(PARAMETER_NAME_SUBJECT_PATTERNFILE);
-            if (filepar != null) {
-                PatternList o = getPatternsFromFileList(filepar);
-                subjectPatternsList.addAll(o.getPatterns());
-                subjectSubstitutionsList.addAll(o.getSubstitutions());
-                subjectFlagsList.addAll(o.getFlags());
+            boolean subjectChanged = applySubjectReplacingUnits(mail);
+            boolean contentChanged = applyBodyReplacingUnits(mail);
+
+            if (charset.isPresent() && !contentChanged) {
+                mail.getMessage().setContent(mail.getMessage().getContent(), getContentType(mail));
             }
-        
-            filepar = getInitParameter(PARAMETER_NAME_BODY_PATTERNFILE);
-            if (filepar != null) {
-                PatternList o = getPatternsFromFileList(filepar);
-                bodyPatternsList.addAll(o.getPatterns());
-                bodySubstitutionsList.addAll(o.getSubstitutions());
-                bodyFlagsList.addAll(o.getFlags());
+
+            if (subjectChanged || contentChanged) {
+                mail.getMessage().saveChanges();
             }
-            
-            ReplaceConfig rConfig = new ReplaceConfig();
-            rConfig.subjectPatterns = subjectPatternsList.toArray(new Pattern[subjectPatternsList.size()]);
-            rConfig.subjectSubstitutions = subjectSubstitutionsList.toArray(new String[subjectSubstitutionsList.size()]);
-            rConfig.subjectFlags = subjectFlagsList.toArray(new Integer[subjectFlagsList.size()]);
-            rConfig.bodyPatterns = bodyPatternsList.toArray(new Pattern[bodyPatternsList.size()]);
-            rConfig.bodySubstitutions = bodySubstitutionsList.toArray(new String[bodySubstitutionsList.size()]);
-            rConfig.bodyFlags = bodyFlagsList.toArray(new Integer[bodyFlagsList.size()]);
-            
-            return rConfig;
-            
-        } catch (FileNotFoundException e) {
-            throw new MailetException("Failed initialization", e);
-            
-        } catch (MailetException e) {
-            throw new MailetException("Failed initialization", e);
+        } catch (MessagingException e) {
+            throw new MailetException("Error in replace", e);
             
         } catch (IOException e) {
-            throw new MailetException("Failed initialization", e);
-            
+            throw new MailetException("Error in replace", e);
         }
     }
 
-    public void service(Mail mail) throws MailetException {
-        ReplaceConfig rConfig = initPatterns();
-        
-        try {
-            boolean mod = false;
-            boolean contentChanged = false;
-            
-            if (rConfig.subjectPatterns != null && rConfig.subjectPatterns.length > 0) {
-                String subject = mail.getMessage().getSubject();
-                if (subject == null) subject = "";
-                subject = applyPatterns(rConfig.subjectPatterns, rConfig.subjectSubstitutions, rConfig.subjectFlags, subject, debug, this);
-                if (charset != null) mail.getMessage().setSubject(subject, charset);
-                else mail.getMessage().setSubject(subject);
-                mod = true;
+    private boolean applySubjectReplacingUnits(Mail mail) throws MessagingException {
+        if (!replaceConfig.getSubjectReplacingUnits().isEmpty()) {
+            String subject = applyPatterns(replaceConfig.getSubjectReplacingUnits(), 
+                    Strings.nullToEmpty(mail.getMessage().getSubject()), debug, this);
+            if (charset.isPresent()) {
+                mail.getMessage().setSubject(subject, charset.get().name());
             }
-            
-            if (rConfig.bodyPatterns != null && rConfig.bodyPatterns.length > 0) {
-                Object bodyObj = mail.getMessage().getContent();
-                if (bodyObj == null) bodyObj = "";
-                if (bodyObj instanceof String) {
-                    String body = (String) bodyObj;
-                    body = applyPatterns(rConfig.bodyPatterns, rConfig.bodySubstitutions, rConfig.bodyFlags, body, debug, this);
-                    String contentType = mail.getMessage().getContentType();
-                    if (charset != null) {
-                        ContentType ct = new ContentType(contentType);
-                        ct.setParameter("charset", charset);
-                        contentType = ct.toString();
-                    }
-                    mail.getMessage().setContent(body, contentType);
-                    mod = true;
-                    contentChanged = true;
-                }
+            else {
+                mail.getMessage().setSubject(subject);
             }
-            
-            if (charset != null && !contentChanged) {
-                ContentType ct = new ContentType(mail.getMessage().getContentType());
-                ct.setParameter("charset", charset);
-                String contentType = mail.getMessage().getContentType();
-                mail.getMessage().setContent(mail.getMessage().getContent(), contentType);
+            return true;
+        }
+        return false;
+    }
+
+    private boolean applyBodyReplacingUnits(Mail mail) throws IOException, MessagingException, ParseException {
+        if (!replaceConfig.getBodyReplacingUnits().isEmpty()) {
+            Object bodyObj = mail.getMessage().getContent();
+            if (bodyObj instanceof String) {
+                String body = applyPatterns(replaceConfig.getBodyReplacingUnits(), 
+                        Strings.nullToEmpty((String) bodyObj), debug, this);
+                setContent(mail, body);
+                return true;
             }
-            
-            if (mod) mail.getMessage().saveChanges();
-            
-        } catch (MessagingException e) {
-            throw new MailetException("Error in replace", e);
-            
-        } catch (IOException e) {
-            throw new MailetException("Error in replace", e);
         }
+        return false;
+    }
+
+    private void setContent(Mail mail, String body) throws MessagingException, ParseException {
+        mail.getMessage().setContent(body, getContentType(mail));
+    }
+
+    private String getContentType(Mail mail) throws MessagingException, ParseException {
+        String contentTypeAsString = mail.getMessage().getContentType();
+        if (charset.isPresent()) {
+            ContentType contentType = new ContentType(contentTypeAsString);
+            contentType.setParameter("charset", charset.get().name());
+            return contentType.toString();
+        }
+        return contentTypeAsString;
     }
 
 }

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplacingPattern.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplacingPattern.java b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplacingPattern.java
new file mode 100644
index 0000000..390d570
--- /dev/null
+++ b/mailet/standard/src/main/java/org/apache/james/transport/mailets/ReplacingPattern.java
@@ -0,0 +1,75 @@
+/****************************************************************
+ * 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.james.transport.mailets;
+
+import java.util.regex.Pattern;
+
+import com.google.common.base.MoreObjects;
+import com.google.common.base.Objects;
+
+public class ReplacingPattern {
+
+    private final Pattern matcher;
+    private final boolean repeat;
+    private final String substitution;
+
+    public ReplacingPattern(Pattern matcher, boolean repeat, String substitution) {
+        this.matcher = matcher;
+        this.repeat = repeat;
+        this.substitution = substitution;
+    }
+
+    public Pattern getMatcher() {
+        return matcher;
+    }
+
+    public boolean isRepeat() {
+        return repeat;
+    }
+
+    public String getSubstitution() {
+        return substitution;
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (o instanceof ReplacingPattern) {
+            ReplacingPattern other = (ReplacingPattern) o;
+            return Objects.equal(matcher.pattern(), other.matcher.pattern())
+                && Objects.equal(repeat, other.repeat)
+                && Objects.equal(substitution, other.substitution);
+        }
+        return false;
+    }
+
+    @Override
+    public int hashCode() {
+        return Objects.hashCode(matcher, repeat, substitution);
+    }
+
+    @Override
+    public String toString() {
+        return MoreObjects.toStringHelper(this)
+            .add("matcher", matcher)
+            .add("repeat", repeat)
+            .add("substitution", substitution)
+            .toString();
+    }
+}
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/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 8037f1b..d385567 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
@@ -107,11 +107,7 @@ public class StripAttachment extends GenericMailet {
 
     private boolean decodeFilename = false;
 
-    private Pattern[] replaceFilenamePatterns = null;
-
-    private String[] replaceFilenameSubstitutions = null;
-
-    private Integer[] replaceFilenameFlags = null;
+    private List<ReplacingPattern> filenameReplacingPatterns = null;
 
     private static boolean getBooleanParameter(String v, boolean def) {
         return def ? !(v != null && (v.equalsIgnoreCase("false") || v
@@ -175,14 +171,8 @@ public class StripAttachment extends GenericMailet {
                 getInitParameter(DECODE_FILENAME_PARAMETER_NAME),
                 decodeFilename);
         if (getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME) != null) {
-            PatternList pl = ReplaceContent
+            filenameReplacingPatterns = ReplaceContent
                     .getPatternsFromString(getInitParameter(REPLACE_FILENAME_PATTERN_PARAMETER_NAME));
-            List<Pattern> patterns = pl.getPatterns();
-            replaceFilenamePatterns = patterns.toArray(new Pattern[patterns.size()]);
-            List<String> substitutions = pl.getSubstitutions();
-            replaceFilenameSubstitutions = substitutions.toArray(new String[substitutions.size()]);
-            List<Integer> flags = pl.getFlags();
-            replaceFilenameFlags = flags.toArray(new Integer[flags.size()]);
         }
 
         String toLog = String.format("StripAttachment is initialised with regex pattern [%s / %s]",
@@ -296,10 +286,8 @@ public class StripAttachment extends GenericMailet {
             if (decodeFilename)
                 fileName = MimeUtility.decodeText(fileName);
 
-            if (replaceFilenamePatterns != null)
-                fileName = ReplaceContent.applyPatterns(
-                        replaceFilenamePatterns, replaceFilenameSubstitutions,
-                        replaceFilenameFlags, fileName, 0, this);
+            if (filenameReplacingPatterns != null)
+                fileName = ReplaceContent.applyPatterns(filenameReplacingPatterns, fileName, false, this);
 
             if (fileNameMatches(fileName)) {
                 if (directoryName != null) {

http://git-wip-us.apache.org/repos/asf/james-project/blob/af067c68/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
----------------------------------------------------------------------
diff --git a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
index 7c359a7..caacd51 100644
--- a/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
+++ b/mailet/standard/src/test/java/org/apache/james/transport/mailets/ReplaceContentTest.java
@@ -19,140 +19,222 @@
 
 package org.apache.james.transport.mailets;
 
+import static org.assertj.core.api.Assertions.assertThat;
+
 import java.io.ByteArrayInputStream;
-import java.io.IOException;
 import java.util.Properties;
+import java.util.regex.Pattern;
 
-import javax.mail.MessagingException;
 import javax.mail.Session;
 import javax.mail.internet.MimeMessage;
 
 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.FakeMailContext;
 import org.apache.mailet.base.test.FakeMailetConfig;
-import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Rule;
 import org.junit.Test;
+import org.junit.rules.ExpectedException;
+
+import com.google.common.base.Charsets;
 
 public class ReplaceContentTest {
 
-    @Test
-    public void testService() throws MessagingException, IOException {
-        Mailet mailet;
-        FakeMailetConfig mci;
-        MimeMessage message;
-        Mail mail;
+    @Rule
+    public ExpectedException expectedException = ExpectedException.none();
 
+    private ReplaceContent mailet;
+    private FakeMailetConfig mailetConfig;
+
+    @Before
+    public void setup() {
         mailet = new ReplaceContent();
-        mci = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
-        mci.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
-        mci.setProperty("bodyPattern", "/prova/PROVA/i/," + "/a/e//,"
+        mailetConfig = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
+    }
+
+    @Test
+    public void getMailetInfoShouldReturnValue() {
+        assertThat(mailet.getMailetInfo()).isEqualTo("ReplaceContent");
+    }
+
+    @Test
+    public void serviceShouldThrowWhenPatternIsLessThanTwoCharacters() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "a");
+        expectedException.expect(MailetException.class);
+
+        mailet.init(mailetConfig);
+    }
+
+    @Test
+    public void serviceShouldThrowWhenPatternDoesNotStartWithSlash() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "abc/");
+        expectedException.expect(MailetException.class);
+
+        mailet.init(mailetConfig);
+    }
+
+    @Test
+    public void serviceShouldThrowWhenPatternDoesNotEndWithSlash() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/abc");
+        expectedException.expect(MailetException.class);
+
+        mailet.init(mailetConfig);
+    }
+
+    @Test
+    public void serviceShouldUnescapeCarriageReturn() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/a/\\\\r/i/");
+
+        mailet.init(mailetConfig);
+        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\r"));
+    }
+
+    @Test
+    public void serviceShouldUnescapeLineBreak() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/a/\\\\n/i/");
+
+        mailet.init(mailetConfig);
+        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\n"));
+    }
+
+    @Test
+    public void serviceShouldUnescapeTabReturn() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/a/\\\\t/i/");
+
+        mailet.init(mailetConfig);
+        assertThat(mailet.replaceConfig.getSubjectReplacingUnits()).containsOnly(new ReplacingPattern(Pattern.compile("a"), false, "\\\t"));
+    }
+
+    @Test
+    public void serviceShouldReplaceSubjectWhenMatching() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
+        mailetConfig.setProperty("bodyPattern", "/prova/PROVA/i/," + "/a/e//,"
                 + "/o/o/i/,/\\u00E8/e'//," + "/prova([^\\/]*?)ble/X$1Y/im/,"
                 + "/X(.\\n)Y/P$1Q//," + "/\\/\\/,//");
-        mailet.init(mci);
+        mailet.init(mailetConfig);
 
-        message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
         message.setSubject("una prova");
         message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
                 + "Bla bla bla bla.\n");
 
-        mail = new FakeMail(message);
+        Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        Assert.assertEquals("une PRoVA", mail.getMessage().getSubject());
-        Assert.assertEquals("Sto fecendo une PRoVA di scritture, e' solo une P.\n"
-                + "Q ble ble ble.\n", mail.getMessage().getContent());
+        assertThat(mail.getMessage().getSubject()).isEqualTo("une PRoVA");
+    }
 
-        // ------------------
+    @Test
+    public void serviceShouldReplaceBodyWhenMatching() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
+        mailetConfig.setProperty("bodyPattern", "/prova/PROVA/i/," + "/a/e//,"
+                + "/o/o/i/,/\\u00E8/e'//," + "/prova([^\\/]*?)ble/X$1Y/im/,"
+                + "/X(.\\n)Y/P$1Q//," + "/\\/\\/,//");
+        mailet.init(mailetConfig);
 
-        mailet = new ReplaceContent();
-        mci = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
-        mci.setProperty("subjectPatternFile", "#/org/apache/james/mailet/standard/mailets/replaceSubject.patterns");
-        mailet.init(mci);
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        message.setSubject("una prova");
+        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
+                + "Bla bla bla bla.\n");
 
-        message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        Mail mail = new FakeMail(message);
+        mailet.service(mail);
+
+        assertThat(mail.getMessage().getContent()).isEqualTo("Sto fecendo une PRoVA di scritture, e' solo une P.\n"
+                + "Q ble ble ble.\n");
+    }
+
+    @Test
+    public void serviceShouldReplaceSubjectWhenConfigurationFromFile() throws Exception {
+        mailetConfig.setProperty("subjectPatternFile", "#/org/apache/james/mailet/standard/mailets/replaceSubject.patterns");
+        mailet.init(mailetConfig);
+
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
         message.setSubject("re: r:ri:una prova");
         message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
                 + "Bla bla bla bla.\n");
 
-        mail = new FakeMail(message);
+        Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        Assert.assertEquals("Re: Re: Re: una prova", mail.getMessage().getSubject());
-
-        // ------------------
+        assertThat(mail.getMessage().getSubject()).isEqualTo("Re: Re: Re: una prova");
+    }
 
-        mailet = new ReplaceContent();
-        mci = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
-        mci.setProperty("bodyPattern", "/--messaggio originale--/<quote>/i/,"
-                +
-                // "/<quote>([^\\0]*)(\\r\\n)([^>]+)/<quote>$1$2>$3/imr/,"+
-                "/<quote>(.*)(\\r\\n)([^>]+)/<quote>$1$2>$3/imrs/,"
+    @Test
+    public void serviceShouldRemoveOrAddTextInBody() throws Exception {
+        mailetConfig.setProperty("bodyPattern", "/--messaggio originale--/<quote>/i/,"
+                + "/<quote>(.*)(\\r\\n)([^>]+)/<quote>$1$2>$3/imrs/,"
                 + "/<quote>\\r\\n//im/");
-        mailet.init(mci);
+        mailet.init(mailetConfig);
 
-        message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
         message.setSubject("una prova");
         message.setText("Prova.\r\n" + "\r\n" + "--messaggio originale--\r\n"
                 + "parte del\r\n" + "messaggio\\ che\\0 deve0 essere\r\n"
                 + "quotato. Vediamo se\r\n" + "ce la fa.");
 
-        mail = new FakeMail(message);
+        Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        Assert.assertEquals("una prova", mail.getMessage().getSubject());
-        Assert.assertEquals("Prova.\r\n" + "\r\n" + ">parte del\r\n"
+        assertThat(mail.getMessage().getContent()).isEqualTo("Prova.\r\n" + "\r\n" + ">parte del\r\n"
                 + ">messaggio\\ che\\0 deve0 essere\r\n"
-                + ">quotato. Vediamo se\r\n" + ">ce la fa.", mail.getMessage()
-                .getContent());
+                + ">quotato. Vediamo se\r\n" + ">ce la fa.");
+    }
 
-        // ------------------
 
-        mailet = new ReplaceContent();
-        mci = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
-        mci.setProperty("bodyPattern", "/\\u2026/...//");
-        mailet.init(mci);
+    @Test
+    public void serviceShouldReplaceBodyWhenMatchingASCIICharacter() throws Exception {
+        mailetConfig.setProperty("bodyPattern", "/\\u2026/...//");
+        mailet.init(mailetConfig);
 
-        message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
         message.setSubject("una prova");
         message.setText("Prova \u2026 di replace \u2026");
 
-        mail = new FakeMail(message);
+        Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        Assert.assertEquals("una prova", mail.getMessage().getSubject());
-        Assert.assertEquals("Prova ... di replace ...", mail.getMessage().getContent());
+        assertThat(mail.getMessage().getContent()).isEqualTo("Prova ... di replace ...");
     }
 
     @Test
-    public void testFromFakeCp1252Stream() throws MessagingException,
-            IOException {
+    public void serviceShouldReplaceBodyWhenMatchingCharset() throws Exception {
         String messageSource = "Content-Type: text/plain; charset=\"iso-8859-1\"\r\n"
                 + "Content-Transfer-Encoding: quoted-printable\r\n"
                 + "\r\n"
                 + "=93prova=94 con l=92apice";
 
-        Mailet mailet;
-        FakeMailetConfig mci;
-        MimeMessage message;
-        Mail mail;
-
-        mailet = new ReplaceContent();
-        mci = new FakeMailetConfig("Test", FakeMailContext.defaultContext());
-        mci.setProperty("bodyPattern", "/[\\u2018\\u2019\\u201A]/'//,"
+        mailetConfig.setProperty("bodyPattern", "/[\\u2018\\u2019\\u201A]/'//,"
                 + "/[\\u201C\\u201D\\u201E]/\"//," + "/[\\x91\\x92\\x82]/'//,"
                 + "/[\\x93\\x94\\x84]/\"//," + "/\\x85/...//," + "/\\x8B/<//,"
                 + "/\\x9B/>//," + "/\\x96/-//," + "/\\x97/--//,");
-        mailet.init(mci);
+        mailet.init(mailetConfig);
 
-        message = new MimeMessage(Session.getDefaultInstance(new Properties()),
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()),
                 new ByteArrayInputStream(messageSource.getBytes()));
 
-        mail = new FakeMail(message);
+        Mail mail = new FakeMail(message);
         mailet.service(mail);
 
-        Assert.assertEquals("\"prova\" con l'apice", mail.getMessage().getContent());
+        assertThat(mail.getMessage().getContent()).isEqualTo("\"prova\" con l'apice");
     }
 
+    @Test
+    public void serviceShouldSetContenTypeWhenInitialized() throws Exception {
+        mailetConfig.setProperty("subjectPattern", "/prova/PROVA/i/,/a/e//,/o/o/i/");
+        mailetConfig.setProperty("charset", Charsets.UTF_8.name());
+        mailet.init(mailetConfig);
+
+        MimeMessage message = new MimeMessage(Session.getDefaultInstance(new Properties()));
+        message.setSubject("una prova");
+        message.setText("Sto facendo una prova di scrittura/ \u00E8 solo una prova.\n"
+                + "Bla bla bla bla.\n");
+
+        Mail mail = new FakeMail(message);
+        mailet.service(mail);
+
+        assertThat(mail.getMessage().getContentType()).isEqualTo("text/plain; charset=UTF-8");
+    }
 }


---------------------------------------------------------------------
To unsubscribe, e-mail: server-dev-unsubscribe@james.apache.org
For additional commands, e-mail: server-dev-help@james.apache.org