Skip to content

Commit 4f401c0

Browse files
committed
CAMEL-12630: better attachment handling in came...
...l-mail component
1 parent 9ccd726 commit 4f401c0

File tree

4 files changed

+147
-2
lines changed

4 files changed

+147
-2
lines changed

components/camel-mail/pom.xml

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,12 @@
119119
<artifactId>camel-quartz2</artifactId>
120120
<scope>test</scope>
121121
</dependency>
122+
<dependency>
123+
<groupId>org.assertj</groupId>
124+
<artifactId>assertj-core</artifactId>
125+
<version>${assertj-version}</version>
126+
<scope>test</scope>
127+
</dependency>
122128
</dependencies>
123129

124130
<build>
Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,59 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.component.mail;
18+
19+
import java.io.IOException;
20+
import java.io.InputStream;
21+
import java.io.OutputStream;
22+
23+
import javax.activation.DataSource;
24+
25+
import org.apache.camel.util.ObjectHelper;
26+
import org.apache.camel.util.StringHelper;
27+
28+
final class DelegatingDataSource implements DataSource {
29+
30+
private final DataSource delegate;
31+
32+
private final String name;
33+
34+
public DelegatingDataSource(final String name, final DataSource delegate) {
35+
this.name = StringHelper.notEmpty(name, "name");
36+
this.delegate = ObjectHelper.notNull(delegate, "DataSource");
37+
}
38+
39+
@Override
40+
public String getContentType() {
41+
return delegate.getContentType();
42+
}
43+
44+
@Override
45+
public InputStream getInputStream() throws IOException {
46+
return delegate.getInputStream();
47+
}
48+
49+
@Override
50+
public String getName() {
51+
return name;
52+
}
53+
54+
@Override
55+
public OutputStream getOutputStream() throws IOException {
56+
return delegate.getOutputStream();
57+
}
58+
59+
}

components/camel-mail/src/main/java/org/apache/camel/component/mail/MailBinding.java

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -52,6 +52,7 @@
5252
import org.apache.camel.impl.DefaultHeaderFilterStrategy;
5353
import org.apache.camel.spi.HeaderFilterStrategy;
5454
import org.apache.camel.util.CollectionHelper;
55+
import org.apache.camel.util.FileUtil;
5556
import org.apache.camel.util.IOHelper;
5657
import org.apache.camel.util.ObjectHelper;
5758
import org.slf4j.Logger;
@@ -314,7 +315,7 @@ protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, Attachm
314315
extractAttachmentsFromMultipart((Multipart) part.getContent(), map);
315316
} else {
316317
String disposition = part.getDisposition();
317-
String fileName = part.getFileName();
318+
String fileName = FileUtil.stripPath(part.getFileName());
318319

319320
if (LOG.isTraceEnabled()) {
320321
LOG.trace("Part #{}: Disposition: {}", i, disposition);
@@ -330,7 +331,11 @@ protected void extractAttachmentsFromMultipart(Multipart mp, Map<String, Attachm
330331
LOG.debug("Mail contains file attachment: {}", fileName);
331332
if (!map.containsKey(fileName)) {
332333
// Parts marked with a disposition of Part.ATTACHMENT are clearly attachments
333-
DefaultAttachment camelAttachment = new DefaultAttachment(part.getDataHandler());
334+
final DataHandler dataHandler = part.getDataHandler();
335+
final DataSource dataSource = dataHandler.getDataSource();
336+
337+
final DataHandler replacement = new DataHandler(new DelegatingDataSource(fileName, dataSource));
338+
DefaultAttachment camelAttachment = new DefaultAttachment(replacement);
334339
@SuppressWarnings("unchecked")
335340
Enumeration<Header> headers = part.getAllHeaders();
336341
while (headers.hasMoreElements()) {
Lines changed: 75 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,75 @@
1+
/**
2+
* Licensed to the Apache Software Foundation (ASF) under one or more
3+
* contributor license agreements. See the NOTICE file distributed with
4+
* this work for additional information regarding copyright ownership.
5+
* The ASF licenses this file to You under the Apache License, Version 2.0
6+
* (the "License"); you may not use this file except in compliance with
7+
* the License. You may obtain a copy of the License at
8+
*
9+
* http://www.apache.org/licenses/LICENSE-2.0
10+
*
11+
* Unless required by applicable law or agreed to in writing, software
12+
* distributed under the License is distributed on an "AS IS" BASIS,
13+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14+
* See the License for the specific language governing permissions and
15+
* limitations under the License.
16+
*/
17+
package org.apache.camel.component.mail;
18+
19+
import java.io.IOException;
20+
import java.util.Arrays;
21+
import java.util.HashMap;
22+
import java.util.Map;
23+
import java.util.Properties;
24+
25+
import javax.activation.DataHandler;
26+
import javax.mail.Message;
27+
import javax.mail.MessagingException;
28+
import javax.mail.Multipart;
29+
import javax.mail.Session;
30+
import javax.mail.internet.MimeBodyPart;
31+
import javax.mail.internet.MimeMessage;
32+
import javax.mail.internet.MimeMultipart;
33+
34+
import org.apache.camel.Attachment;
35+
import org.junit.Test;
36+
import org.junit.runner.RunWith;
37+
import org.junit.runners.Parameterized;
38+
import org.junit.runners.Parameterized.Parameter;
39+
import org.junit.runners.Parameterized.Parameters;
40+
41+
import static org.assertj.core.api.Assertions.assertThat;
42+
43+
@RunWith(Parameterized.class)
44+
public class MailBindingAttachmentFileTest {
45+
46+
@Parameter
47+
public String name;
48+
49+
private final MailBinding binding = new MailBinding();
50+
51+
@Test
52+
public void shouldSanitizeAttachmentFileNames() throws MessagingException, IOException {
53+
final Session session = Session.getInstance(new Properties());
54+
final Message message = new MimeMessage(session);
55+
56+
final Multipart multipart = new MimeMultipart();
57+
final MimeBodyPart part = new MimeBodyPart();
58+
part.attachFile(name);
59+
multipart.addBodyPart(part);
60+
message.setContent(multipart);
61+
62+
final Map<String, Attachment> attachments = new HashMap<>();
63+
binding.extractAttachmentsFromMail(message, attachments);
64+
65+
assertThat(attachments).containsKey("file.txt");
66+
final Attachment attachment = attachments.get("file.txt");
67+
final DataHandler dataHandler = attachment.getDataHandler();
68+
assertThat(dataHandler.getName()).isEqualTo("file.txt");
69+
}
70+
71+
@Parameters(name = "{0}")
72+
public static Iterable<String> fileNames() {
73+
return Arrays.asList("file.txt", "../file.txt", "..\\file.txt", "/absolute/file.txt", "c:\\absolute\\file.txt");
74+
}
75+
}

0 commit comments

Comments
 (0)