This is an automated email from the ASF dual-hosted git repository. btellier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
commit 41bf356cd068607f35ce3e58790adcb3962bdffd Author: Benoit TELLIER <[email protected]> AuthorDate: Thu Nov 28 15:46:11 2024 +0100 [ENHANCEMENT] Extract MimeWalk Walking through a mime tree and matching parts is very common, we do not need to duplicate such logic. --- .../transport/matchers/AttachmentFileNameIs.java | 194 ++++++++++++--------- 1 file changed, 108 insertions(+), 86 deletions(-) diff --git a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java index f5d6f5ec86..d5703299fb 100755 --- a/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java +++ b/mailet/standard/src/main/java/org/apache/james/transport/matchers/AttachmentFileNameIs.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Locale; import java.util.StringTokenizer; +import java.util.function.Predicate; import java.util.zip.ZipEntry; import java.util.zip.ZipInputStream; @@ -99,6 +100,94 @@ public class AttachmentFileNameIs extends GenericMatcher { } } + public static class MimeWalk { + @FunctionalInterface + interface PartMatch { + boolean partMatch(Part part) throws MessagingException, IOException; + } + + private final MimeWalkConfiguration configuration; + private final PartMatch partMatch; + + public MimeWalk(MimeWalkConfiguration configuration, PartMatch partMatch) { + this.configuration = configuration; + this.partMatch = partMatch; + } + + private Collection<MailAddress> matchMail(Mail mail) throws MessagingException { + try { + MimeMessage message = mail.getMessage(); + + if (matchFound(message)) { + return mail.getRecipients(); + } else { + return null; + } + + } catch (Exception e) { + if (configuration.isDebug()) { + LOGGER.debug("Malformed message", e); + } + throw new MessagingException("Malformed message", e); + } + } + + /** + * Checks if <I>part</I> matches with at least one of the <CODE>masks</CODE>. + * + * @param part + */ + protected boolean matchFound(Part part) throws Exception { + + /* + * if there is an attachment and no inline text, + * the content type can be anything + */ + + if (part.getContentType() == null || + part.getContentType().startsWith("multipart/alternative")) { + return false; + } + + Object content; + + try { + content = part.getContent(); + } catch (UnsupportedEncodingException uee) { + // in this case it is not an attachment, so ignore it + return false; + } + + Exception anException = null; + + if (content instanceof Multipart) { + Multipart multipart = (Multipart) content; + for (int i = 0; i < multipart.getCount(); i++) { + try { + Part bodyPart = multipart.getBodyPart(i); + if (matchFound(bodyPart)) { + return true; // matching file found + } + } catch (MessagingException e) { + anException = e; + } // remember any messaging exception and process next bodypart + } + } else { + if (partMatch.partMatch(part)) { + return true; + } + } + + // if no matching attachment was found and at least one exception was catched rethrow it up + if (anException != null) { + throw anException; + } + + return false; + } + } + + /** * Transforms <I>fileName<I> in a trimmed lowercase string usable for matching agains the masks. * Also decode encoded words. @@ -125,18 +214,27 @@ public class AttachmentFileNameIs extends GenericMatcher { /** file name mask not including the wildcard asterisk */ public String matchString; + + public boolean match(String fileName) { + //XXX: file names in mail may contain directory - theoretically + if (this.suffixMatch) { + return fileName.endsWith(this.matchString); + } else { + return fileName.equals(this.matchString); + } + } } /** * Controls certain log messages. */ @VisibleForTesting - MimeWalkConfiguration mimeWalkConfiguration = MimeWalkConfiguration.DEFAULT; + MimeWalkConfiguration configuration = MimeWalkConfiguration.DEFAULT; @Override public void init() throws MessagingException { - mimeWalkConfiguration = MimeWalkConfiguration.parse(getCondition()); + configuration = MimeWalkConfiguration.parse(getCondition()); } /** @@ -145,76 +243,8 @@ public class AttachmentFileNameIs extends GenericMatcher { */ @Override public Collection<MailAddress> match(Mail mail) throws MessagingException { - - try { - MimeMessage message = mail.getMessage(); - - if (matchFound(message)) { - return mail.getRecipients(); // matching file found - } else { - return null; // no matching attachment found - } - - } catch (Exception e) { - if (mimeWalkConfiguration.isDebug) { - LOGGER.debug("Malformed message", e); - } - throw new MessagingException("Malformed message", e); - } - } - - /** - * Checks if <I>part</I> matches with at least one of the <CODE>masks</CODE>. - * - * @param part - */ - protected boolean matchFound(Part part) throws Exception { - - /* - * if there is an attachment and no inline text, - * the content type can be anything - */ - - if (part.getContentType() == null || - part.getContentType().startsWith("multipart/alternative")) { - return false; - } - - Object content; - - try { - content = part.getContent(); - } catch (UnsupportedEncodingException uee) { - // in this case it is not an attachment, so ignore it - return false; - } - - Exception anException = null; - - if (content instanceof Multipart) { - Multipart multipart = (Multipart) content; - for (int i = 0; i < multipart.getCount(); i++) { - try { - Part bodyPart = multipart.getBodyPart(i); - if (matchFound(bodyPart)) { - return true; // matching file found - } - } catch (MessagingException e) { - anException = e; - } // remember any messaging exception and process next bodypart - } - } else { - if (partMatch(part)) { - return true; - } - } - - // if no matching attachment was found and at least one exception was catched rethrow it up - if (anException != null) { - throw anException; - } - - return false; + return new MimeWalk(configuration, this::partMatch) + .matchMail(mail); } private boolean partMatch(Part part) throws MessagingException, IOException { @@ -223,12 +253,12 @@ public class AttachmentFileNameIs extends GenericMatcher { fileName = cleanFileName(fileName); // check the file name if (matchFound(fileName)) { - if (mimeWalkConfiguration.isDebug()) { + if (configuration.isDebug()) { LOGGER.debug("matched {}", fileName); } return true; } - if (mimeWalkConfiguration.unzipIsRequested() && fileName.endsWith(ZIP_SUFFIX) && matchFoundInZip(part)) { + if (configuration.unzipIsRequested() && fileName.endsWith(ZIP_SUFFIX) && matchFoundInZip(part)) { return true; } } @@ -241,22 +271,14 @@ public class AttachmentFileNameIs extends GenericMatcher { * @param fileName */ protected boolean matchFound(String fileName) { - for (Mask mask1 : mimeWalkConfiguration.masks) { - boolean fMatch; - - //XXX: file names in mail may contain directory - theoretically - if (mask1.suffixMatch) { - fMatch = fileName.endsWith(mask1.matchString); - } else { - fMatch = fileName.equals(mask1.matchString); - } - if (fMatch) { + for (Mask mask1 : configuration.masks) { + if (mask1.match(fileName)) { return true; // matching file found } } return false; } - + /** * Checks if <I>part</I> is a zip containing a file that matches with at least one of the <CODE>masks</CODE>. * @@ -271,7 +293,7 @@ public class AttachmentFileNameIs extends GenericMatcher { } String fileName = zipEntry.getName(); if (matchFound(fileName)) { - if (mimeWalkConfiguration.unzipIsRequested) { + if (configuration.unzipIsRequested) { LOGGER.debug("matched {}({})", part.getFileName(), fileName); } return true; --------------------------------------------------------------------- To unsubscribe, e-mail: [email protected] For additional commands, e-mail: [email protected]
