This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-email.git
commit 185fb25e1182443201d2d0b05f4b530f7672ec9e Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Sat Dec 16 14:34:59 2023 -0500 Add MultiPartEmail.attach(Path, OpenOption...). --- src/changes/changes.xml | 1 + .../org/apache/commons/mail/MultiPartEmail.java | 28 +++++ .../commons/mail/activation/PathDataSource.java | 2 +- .../apache/commons/mail/util/MimeMessageUtils.java | 2 +- .../org/apache/commons/mail/EmailLiveTest.java | 18 +++- .../apache/commons/mail/MultiPartEmailTest.java | 114 +++++++++++++++------ .../commons/mail/util/MimeMessageParserTest.java | 12 +-- 7 files changed, 139 insertions(+), 38 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index ca7515f..7860475 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -53,6 +53,7 @@ <action type="add" due-to="Gary Gregory" dev="ggregory">Add PathDataSource.</action> <action type="add" due-to="Gary Gregory" dev="ggregory">Add DataSourcePathResolver.</action> <action type="add" due-to="Gary Gregory" dev="ggregory">Add MimeMessageUtils.createMimeMessage(Session, Path, OpenOption...).</action> + <action type="add" due-to="Gary Gregory" dev="ggregory">Add MultiPartEmail.attach(Path, OpenOption...).</action> <!-- UPDATE --> <action type="update" due-to="Dependabot" dev="sebb">Bump org.slf4j:slf4j-jdk14 from 1.7.7 to 2.0.9 #165.</action> <action type="update" due-to="Dependabot" dev="sebb">Bump mockito-core from 4.11.0 to 5.8.0 #187.</action> diff --git a/src/main/java/org/apache/commons/mail/MultiPartEmail.java b/src/main/java/org/apache/commons/mail/MultiPartEmail.java index 97ad9a4..540b6c0 100644 --- a/src/main/java/org/apache/commons/mail/MultiPartEmail.java +++ b/src/main/java/org/apache/commons/mail/MultiPartEmail.java @@ -21,10 +21,14 @@ import java.io.IOException; import java.io.InputStream; import java.io.UnsupportedEncodingException; import java.net.URL; +import java.nio.file.Files; +import java.nio.file.OpenOption; +import java.nio.file.Path; import javax.activation.DataHandler; import javax.activation.DataSource; import javax.activation.FileDataSource; +import javax.activation.FileTypeMap; import javax.activation.URLDataSource; import javax.mail.BodyPart; import javax.mail.MessagingException; @@ -33,6 +37,8 @@ import javax.mail.internet.MimeMultipart; import javax.mail.internet.MimePart; import javax.mail.internet.MimeUtility; +import org.apache.commons.mail.activation.PathDataSource; + /** * A multipart email. * <p> @@ -220,6 +226,28 @@ public class MultiPartEmail extends Email { } } + /** + * Attaches a path. + * + * @param file A file attachment. + * @param options options for opening file streams. + * @return A MultiPartEmail. + * @throws EmailException see javax.mail.internet.MimeBodyPart for definitions + * @since 1.6.0 + */ + public MultiPartEmail attach(final Path file, final OpenOption... options) throws EmailException { + final Path fileName = file.toAbsolutePath(); + try { + if (!Files.exists(file)) { + throw new IOException("\"" + fileName + "\" does not exist"); + } + return attach(new PathDataSource(file, FileTypeMap.getDefaultFileTypeMap(), options), file.getFileName().toString(), null, + EmailAttachment.ATTACHMENT); + } catch (final IOException e) { + throw new EmailException("Cannot attach file \"" + fileName + "\"", e); + } + } + /** * Attaches a file located by its URL. The disposition of the file is set to mixed. * diff --git a/src/main/java/org/apache/commons/mail/activation/PathDataSource.java b/src/main/java/org/apache/commons/mail/activation/PathDataSource.java index 467ca7b..90a74b9 100644 --- a/src/main/java/org/apache/commons/mail/activation/PathDataSource.java +++ b/src/main/java/org/apache/commons/mail/activation/PathDataSource.java @@ -65,7 +65,7 @@ public class PathDataSource implements DataSource { * * @param path the path, non-null. * @param typeMap the type map, non-null. - * @param options Options for opening streams. + * @param options options for opening file streams. */ public PathDataSource(final Path path, final FileTypeMap typeMap, final OpenOption... options) { this.path = Objects.requireNonNull(path, "path"); diff --git a/src/main/java/org/apache/commons/mail/util/MimeMessageUtils.java b/src/main/java/org/apache/commons/mail/util/MimeMessageUtils.java index 6a00ca2..cb57049 100644 --- a/src/main/java/org/apache/commons/mail/util/MimeMessageUtils.java +++ b/src/main/java/org/apache/commons/mail/util/MimeMessageUtils.java @@ -91,7 +91,7 @@ public final class MimeMessageUtils { * @throws MessagingException creating the MimeMessage failed. * @throws IOException creating the MimeMessage failed. */ - public static MimeMessage createMimeMessage(final Session session, final Path source, OpenOption... options) throws MessagingException, IOException { + public static MimeMessage createMimeMessage(final Session session, final Path source, final OpenOption... options) throws MessagingException, IOException { try (InputStream inputStream = Files.newInputStream(source, options)) { return createMimeMessage(session, inputStream); } diff --git a/src/test/java/org/apache/commons/mail/EmailLiveTest.java b/src/test/java/org/apache/commons/mail/EmailLiveTest.java index 86c958b..6e77187 100644 --- a/src/test/java/org/apache/commons/mail/EmailLiveTest.java +++ b/src/test/java/org/apache/commons/mail/EmailLiveTest.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.InputStream; import java.net.URL; import java.nio.charset.StandardCharsets; +import java.nio.file.Paths; import java.util.ArrayList; import java.util.List; @@ -269,7 +270,7 @@ public class EmailLiveTest extends AbstractEmailTest { * @throws Exception the test failed */ @Test - public void testMultiPartEmail() throws Exception { + public void testMultiPartEmailFile() throws Exception { final MultiPartEmail email = (MultiPartEmail) create(MultiPartEmail.class); email.setSubject("TestMultiPartMail"); email.setMsg("This is a test mail ... :-)"); @@ -278,6 +279,21 @@ public class EmailLiveTest extends AbstractEmailTest { EmailUtils.writeMimeMessage(new File("./target/test-emails/multipart.eml"), send(email).getMimeMessage()); } + /** + * A sanity check that a simple email also works in reality. + * + * @throws Exception the test failed + */ + @Test + public void testMultiPartEmailPath() throws Exception { + final MultiPartEmail email = (MultiPartEmail) create(MultiPartEmail.class); + email.setSubject("TestMultiPartMail"); + email.setMsg("This is a test mail ... :-)"); + email.attach(Paths.get("./src/test/resources/attachments/logo.pdf")); + + EmailUtils.writeMimeMessage(new File("./target/test-emails/multipart.eml"), send(email).getMimeMessage()); + } + /** * Testing if we are able to send a partial email with an invalid address. * diff --git a/src/test/java/org/apache/commons/mail/MultiPartEmailTest.java b/src/test/java/org/apache/commons/mail/MultiPartEmailTest.java index b229601..9d87815 100644 --- a/src/test/java/org/apache/commons/mail/MultiPartEmailTest.java +++ b/src/test/java/org/apache/commons/mail/MultiPartEmailTest.java @@ -24,6 +24,7 @@ import java.io.File; import java.io.IOException; import java.net.MalformedURLException; import java.net.URL; +import java.nio.file.Path; import java.util.HashMap; import java.util.Map; @@ -36,16 +37,22 @@ import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; public class MultiPartEmailTest extends AbstractEmailTest { + /** */ private MockMultiPartEmailConcrete email; + /** File to used to test file attachments (Must be valid) */ private File testFile; + /** File to used to test file attachments (Must be valid) */ + private Path testPath; + @BeforeEach public void setUpMultiPartEmailTest() throws Exception { // reusable objects to be used across multiple tests email = new MockMultiPartEmailConcrete(); testFile = File.createTempFile("testfile", ".txt"); + testPath = testFile.toPath(); } @Test @@ -80,8 +87,45 @@ public class MultiPartEmailTest extends AbstractEmailTest { } + /** + * @throws MalformedURLException when a bad attachment URL is used + * @throws EmailException when a bad address or attachment is used + */ @Test - public void testAttach() throws Exception { + public void testAttach2() throws MalformedURLException, EmailException { + // Test Success - URL + email.attach(new URL(strTestURL), "Test Attachment", "Test Attachment Desc"); + + // bad name + email.attach(new URL(strTestURL), null, "Test Attachment Desc"); + } + + @Test + public void testAttach3() throws Exception { + // Test Success - URL + email.attach(new URLDataSource(new URL(strTestURL)), "Test Attachment", "Test Attachment Desc"); + // Test Exceptions + // null datasource + try { + final URLDataSource urlDs = null; + email.attach(urlDs, "Test Attachment", "Test Attachment Desc"); + fail("Should have thrown an exception"); + } catch (final EmailException e) { + assertTrue(true); + } + + // invalid datasource + try { + final URLDataSource urlDs = new URLDataSource(createInvalidURL()); + email.attach(urlDs, "Test Attachment", "Test Attachment Desc"); + fail("Should have thrown an exception"); + } catch (final EmailException e) { + assertTrue(true); + } + } + + @Test + public void testAttachFile() throws Exception { EmailAttachment attachment; // Test Success - EmailAttachment attachment = new EmailAttachment(); @@ -129,53 +173,65 @@ public class MultiPartEmailTest extends AbstractEmailTest { } } - /** - * @throws MalformedURLException when a bad attachment URL is used - * @throws EmailException when a bad address or attachment is used - */ @Test - public void testAttach2() throws MalformedURLException, EmailException { - // Test Success - URL - email.attach(new URL(strTestURL), "Test Attachment", "Test Attachment Desc"); + public void testAttachFileLocking() throws Exception { + // EMAIL-120: attaching a FileDataSource may result in a locked file + // resource on windows systems - // bad name - email.attach(new URL(strTestURL), null, "Test Attachment Desc"); + final File tmpFile = File.createTempFile("attachment", ".eml"); + + email.attach(new FileDataSource(tmpFile), "Test Attachment", "Test Attachment Desc"); + + assertTrue(tmpFile.delete()); } @Test - public void testAttach3() throws Exception { + public void testAttachPath() throws Exception { + EmailAttachment attachment; + // Test Success - EmailAttachment + attachment = new EmailAttachment(); + attachment.setName("Test Attachment"); + attachment.setDescription("Test Attachment Desc"); + attachment.setPath(testPath.toAbsolutePath().toString()); + email.attach(attachment); + assertTrue(email.isBoolHasAttachments()); // Test Success - URL - email.attach(new URLDataSource(new URL(strTestURL)), "Test Attachment", "Test Attachment Desc"); + attachment = new EmailAttachment(); + attachment.setName("Test Attachment"); + attachment.setDescription("Test Attachment Desc"); + attachment.setURL(new URL(strTestURL)); + email.attach(attachment); + // Test Success - File + email.attach(testPath); + assertTrue(email.isBoolHasAttachments()); // Test Exceptions - // null datasource + // null attachment try { - final URLDataSource urlDs = null; - email.attach(urlDs, "Test Attachment", "Test Attachment Desc"); + email.attach((EmailAttachment) null); fail("Should have thrown an exception"); } catch (final EmailException e) { assertTrue(true); } - // invalid datasource + // bad url + attachment = new EmailAttachment(); try { - final URLDataSource urlDs = new URLDataSource(createInvalidURL()); - email.attach(urlDs, "Test Attachment", "Test Attachment Desc"); + attachment.setURL(createInvalidURL()); + email.attach(attachment); fail("Should have thrown an exception"); } catch (final EmailException e) { assertTrue(true); } - } - - @Test - public void testAttachFileLocking() throws Exception { - // EMAIL-120: attaching a FileDataSource may result in a locked file - // resource on windows systems - - final File tmpFile = File.createTempFile("attachment", ".eml"); - - email.attach(new FileDataSource(tmpFile), "Test Attachment", "Test Attachment Desc"); - assertTrue(tmpFile.delete()); + // bad file + attachment = new EmailAttachment(); + try { + attachment.setPath(""); + email.attach(attachment); + fail("Should have thrown an exception"); + } catch (final EmailException e) { + assertTrue(true); + } } /** TODO implement test for GetContainer */ diff --git a/src/test/java/org/apache/commons/mail/util/MimeMessageParserTest.java b/src/test/java/org/apache/commons/mail/util/MimeMessageParserTest.java index a7c2d88..b454672 100644 --- a/src/test/java/org/apache/commons/mail/util/MimeMessageParserTest.java +++ b/src/test/java/org/apache/commons/mail/util/MimeMessageParserTest.java @@ -68,7 +68,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = mimeMessageParser.findAttachmentByName("Kunde 100029 Auftrag 3600.pdf"); + final DataSource dataSource = mimeMessageParser.findAttachmentByName("Kunde 100029 Auftrag 3600.pdf"); assertNotNull(dataSource); assertEquals("application/pdf", dataSource.getContentType()); } @@ -102,7 +102,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = mimeMessageParser.findAttachmentByName("test.txt"); + final DataSource dataSource = mimeMessageParser.findAttachmentByName("test.txt"); assertNotNull(dataSource); assertEquals("text/plain", dataSource.getContentType()); } @@ -136,7 +136,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = mimeMessageParser.findAttachmentByName("test.txt"); + final DataSource dataSource = mimeMessageParser.findAttachmentByName("test.txt"); assertNotNull(dataSource); assertEquals("text/plain", dataSource.getContentType()); } @@ -261,7 +261,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = mimeMessageParser.getAttachmentList().get(0); + final DataSource dataSource = mimeMessageParser.getAttachmentList().get(0); assertNotNull(dataSource); assertEquals("text/plain", dataSource.getContentType()); assertEquals("Test Attachment - a>ä, o>ö, u>ü, au>äu", dataSource.getName()); @@ -329,7 +329,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = mimeMessageParser.findAttachmentByName("test.html"); + final DataSource dataSource = mimeMessageParser.findAttachmentByName("test.html"); assertNotNull(dataSource); assertEquals("text/html", dataSource.getContentType()); } @@ -392,7 +392,7 @@ public class MimeMessageParserTest { final List<?> attachmentList = mimeMessageParser.getAttachmentList(); assertEquals(1, attachmentList.size()); - DataSource dataSource = (DataSource) attachmentList.get(0); + final DataSource dataSource = (DataSource) attachmentList.get(0); assertNotNull(dataSource); assertNull(dataSource.getName()); assertEquals("message/disposition-notification", dataSource.getContentType());