This is an automated email from the ASF dual-hosted git repository. rcordier pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/james-project.git
The following commit(s) were added to refs/heads/master by this push: new 4f77aab13a JAMES-4011 Use MIME4J to decode filename 4f77aab13a is described below commit 4f77aab13a6696f1417b4cb4728ed26b34a9de74 Author: Benoit TELLIER <btell...@linagora.com> AuthorDate: Tue Feb 27 08:50:45 2024 +0100 JAMES-4011 Use MIME4J to decode filename This is more lenient --- .../james/transport/mailets/StripAttachment.java | 20 ++++++++++-- .../transport/mailets/StripAttachmentTest.java | 37 ++++++++++++++++++++++ mailet/standard/src/test/resources/mime/space.eml | 24 ++++++++++++++ 3 files changed, 79 insertions(+), 2 deletions(-) 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 459e7fb0d4..115b5bd45e 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 @@ -50,6 +50,11 @@ import org.apache.commons.io.output.UnsynchronizedByteArrayOutputStream; import org.apache.james.javax.MultipartUtil; import org.apache.james.mime4j.codec.DecodeMonitor; import org.apache.james.mime4j.codec.DecoderUtil; +import org.apache.james.mime4j.dom.field.ContentDispositionField; +import org.apache.james.mime4j.field.ContentDispositionFieldLenientImpl; +import org.apache.james.mime4j.field.ContentTypeFieldLenientImpl; +import org.apache.james.mime4j.stream.Field; +import org.apache.james.mime4j.stream.RawField; import org.apache.mailet.Attribute; import org.apache.mailet.AttributeName; import org.apache.mailet.AttributeUtils; @@ -385,7 +390,18 @@ public class StripAttachment extends GenericMailet { @VisibleForTesting String getFilename(BodyPart bodyPart) { try { - String fileName = bodyPart.getFileName(); + String fileName = Optional.ofNullable(bodyPart.getHeader("Content-Disposition")) + .map(h -> h[0]) + .map(h -> new RawField("Content-Disposition", h)) + .map(h -> ContentDispositionFieldLenientImpl.PARSER.parse(h, DecodeMonitor.SILENT)) + .map(ContentDispositionField::getFilename) + .or(Throwing.supplier(() -> Optional.ofNullable(bodyPart.getHeader("Content-Type")) + .map(h -> h[0]) + .map(h -> new RawField("Content-Type", h)) + .map(h -> ContentTypeFieldLenientImpl.PARSER.parse(h, DecodeMonitor.SILENT)) + .map(Field::getName)).sneakyThrow()) + .orElse(null); + if (fileName != null) { return renameWithConfigurationPattern(decodeFilename(fileName)); } @@ -467,7 +483,7 @@ public class StripAttachment extends GenericMailet { } private File outputFile(Part part, Optional<String> fileName) throws MessagingException, IOException { - Optional<String> maybePartFileName = Optional.ofNullable(part.getFileName()); + Optional<String> maybePartFileName = fileName.or(Throwing.supplier(() -> Optional.ofNullable(part.getFileName())).sneakyThrow()); return createTempFile(fileName.orElse(maybePartFileName.orElse(null))); } 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 c2e4a3efd3..a374b5d1c9 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 @@ -44,6 +44,8 @@ import org.apache.james.core.builder.MimeMessageBuilder; import org.apache.james.junit.TemporaryFolderExtension; import org.apache.james.junit.TemporaryFolderExtension.TemporaryFolder; import org.apache.james.transport.mailets.StripAttachment.OutputFileName; +import org.apache.james.util.ClassLoaderUtils; +import org.apache.james.util.MimeMessageUtil; import org.apache.mailet.AttributeName; import org.apache.mailet.AttributeUtils; import org.apache.mailet.AttributeValue; @@ -340,6 +342,41 @@ class StripAttachmentTest { .hasValueSatisfying(assertValue.sneakyThrow()); } + @Test + void serviceShouldHandleFilenameWithSpace(TemporaryFolder temporaryFolder) throws Exception { + StripAttachment mailet = new StripAttachment(); + + String customAttribute = "my.custom.attribute"; + FakeMailetConfig mci = FakeMailetConfig.builder() + .mailetName("Test") + .setProperty("remove", "matched") + .setProperty("directory", temporaryFolder.getFolderPath()) + .setProperty("pattern", ".*\\.pdf") + .setProperty("attribute", customAttribute) + .build(); + mailet.init(mci); + + String expectedKey = "Vietnam Airline.pdf"; + MimeMessage message = MimeMessageUtil.mimeMessageFromStream(ClassLoaderUtils.getSystemResourceAsSharedStream("mime/space.eml")); + + Mail mail = FakeMail.builder() + .name("from-message-builder") + .mimeMessage(message) + .build(); + + mailet.service(mail); + + Optional<Map<String, AttributeValue<?>>> savedValue = AttributeUtils.getValueAndCastFromMail(mail, AttributeName.of(customAttribute), MAP_STRING_BYTES_CLASS); + ConsumerChainer<Map<String, AttributeValue<?>>> assertValue = Throwing.consumer(saved -> { + assertThat(saved) + .hasSize(1) + .containsKeys(expectedKey); + }); + assertThat(savedValue) + .isPresent() + .hasValueSatisfying(assertValue.sneakyThrow()); + } + @Test void serviceShouldDecodeHeaderFilenames() throws Exception, IOException { StripAttachment mailet = new StripAttachment(); diff --git a/mailet/standard/src/test/resources/mime/space.eml b/mailet/standard/src/test/resources/mime/space.eml new file mode 100644 index 0000000000..456b218a0b --- /dev/null +++ b/mailet/standard/src/test/resources/mime/space.eml @@ -0,0 +1,24 @@ +Content-Type: multipart/mixed; boundary="------------gwA6NAbT8Pk0FYCy0yoPh61m" +Message-ID: <1745dbd6-f23b-44d0-be4c-9b9472c50...@linagora.com> +Date: Tue, 27 Feb 2024 07:38:14 +0100 +MIME-Version: 1.0 +To: BT TEST <x...@linagora.com> +From: "x...@linagora.com" <x...@linagora.com> +Subject: Space + +This is a multi-part message in MIME format. +--------------gwA6NAbT8Pk0FYCy0yoPh61m +Content-Type: text/plain; charset=UTF-8; format=flowed +Content-Transfer-Encoding: 7bit + +space in attachment filename + +--------------gwA6NAbT8Pk0FYCy0yoPh61m +Content-Type: application/pdf +Content-Disposition: attachment; filename=Vietnam Airline.pdf +Content-Transfer-Encoding: base64 + +JVBERi0xLjUKJbXtrvsKMyAwIG9iago8PCAvTGVuZ3RoIDQgMCBSCiAgIC9GaWx0ZXIgL0Zs +YXRlRGVjb2RlCj4+CnN0cmVhbQp4nN1aS6/buhHe61foD1ghh28g0OIC3XTVAgfooujC9jm+ + +--------------gwA6NAbT8Pk0FYCy0yoPh61m-- --------------------------------------------------------------------- To unsubscribe, e-mail: notifications-unsubscr...@james.apache.org For additional commands, e-mail: notifications-h...@james.apache.org