diff --git a/duniter4j-core-shared/src/main/java/org/duniter/core/model/SmtpConfig.java b/duniter4j-core-shared/src/main/java/org/duniter/core/model/SmtpConfig.java index 0019dbebd8b56776457fef6e1b30da5f28492581..30e5b9fcb644f58ce3be9cbc234da134a00b9d95 100644 --- a/duniter4j-core-shared/src/main/java/org/duniter/core/model/SmtpConfig.java +++ b/duniter4j-core-shared/src/main/java/org/duniter/core/model/SmtpConfig.java @@ -22,6 +22,12 @@ package org.duniter.core.model; * #L% */ +import lombok.*; + +@Data +@Builder +@NoArgsConstructor +@AllArgsConstructor public class SmtpConfig { @@ -31,70 +37,11 @@ public class SmtpConfig { private String smtpPassword; private String senderAddress; private String senderName; - private boolean useSsl; - private boolean startTLS; - - public String getSmtpHost() { - return smtpHost; - } - - public void setSmtpHost(String smtpHost) { - this.smtpHost = smtpHost; - } - - public int getSmtpPort() { - return smtpPort; - } - - public void setSmtpPort(int smtpPort) { - this.smtpPort = smtpPort; - } - - public String getSmtpUsername() { - return smtpUsername; - } - - public void setSmtpUsername(String smtpUsername) { - this.smtpUsername = smtpUsername; - } - - public String getSmtpPassword() { - return smtpPassword; - } - - public void setSmtpPassword(String smtpPassword) { - this.smtpPassword = smtpPassword; - } - - public String getSenderAddress() { - return senderAddress; - } - - public void setSenderAddress(String senderAddress) { - this.senderAddress = senderAddress; - } - - public String getSenderName() { - return senderName; - } - - public void setSenderName(String senderName) { - this.senderName = senderName; - } - - public boolean isUseSsl() { - return useSsl; - } - public void setUseSsl(boolean useSsl) { - this.useSsl = useSsl; - } + @Builder.Default + private boolean useSsl = false; - public boolean isStartTLS() { - return startTLS; - } + @Builder.Default + private boolean startTLS = false; - public void setStartTLS(boolean startTLS) { - this.startTLS = startTLS; - } } diff --git a/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailService.java b/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailService.java index 1a11960e61b1852241675983bdef0cf7cd88b555..5b4c9eab6b9ac467ee021c61d416b0d468eabd37 100644 --- a/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailService.java +++ b/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailService.java @@ -28,6 +28,8 @@ import org.duniter.core.model.SmtpConfig; import javax.mail.internet.ContentType; import javax.mail.internet.ParseException; +import java.net.URL; +import java.util.List; /** * Created by blavenie on 28/11/16. @@ -47,8 +49,14 @@ public interface MailService extends Bean { void sendHtmlEmailWithText( String subject, - String utf8textContent, - String utf8HtmlContent, + String messageText, + String messageHtml, String... recipients); + void sendHtmlEmailWithText( + String subject, + String messageText, + String messageHtml, + List<URL> attachments, + String... recipients); } diff --git a/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailServiceImpl.java b/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailServiceImpl.java index 5c1771767c45a47ca123134fec8ed76ba594183a..42b6e906ad3a03a8ae09afde3f181b9472f24d90 100644 --- a/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailServiceImpl.java +++ b/duniter4j-core-shared/src/main/java/org/duniter/core/service/MailServiceImpl.java @@ -28,6 +28,7 @@ import org.duniter.core.model.SmtpConfig; import org.duniter.core.util.CollectionUtils; import org.duniter.core.util.Preconditions; import org.duniter.core.util.StringUtils; +import org.duniter.core.util.mail.MailContentBuilder; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -37,7 +38,9 @@ import javax.mail.*; import javax.mail.internet.*; import java.io.Closeable; import java.io.UnsupportedEncodingException; +import java.net.URL; import java.util.Arrays; +import java.util.List; import java.util.Properties; import java.util.stream.Collectors; @@ -96,32 +99,25 @@ public class MailServiceImpl implements MailService, Closeable { @Override public void sendHtmlEmailWithText(String subject, - String textContent, - String htmlContent, + String messageText, + String messageHtml, String... recipients) { - try{ - - Multipart content = new MimeMultipart("alternative"); + sendHtmlEmailWithText(subject, messageText, messageHtml, null, recipients); + } - // Add text part - { - MimeBodyPart mbp = new MimeBodyPart(); - ContentType contentType = new ContentType("text/plain"); - contentType.setParameter("charset", "UTF-8"); - mbp.setContent(textContent, contentType.toString()); - content.addBodyPart(mbp); - } + @Override + public void sendHtmlEmailWithText(String subject, String messageText, String messageHtml, + List<URL> attachments, + String... recipients) { + try { - // Add html part - { - MimeBodyPart mbp = new MimeBodyPart(); - ContentType contentType = new ContentType("text/html"); - contentType.setParameter("charset", "UTF-8"); - mbp.setContent(htmlContent, contentType.toString()); - content.addBodyPart(mbp); - } + MailContentBuilder mailContentBuilder = new MailContentBuilder(); + final Multipart mixed = mailContentBuilder.build(messageText, + messageHtml, + mailContentBuilder.findUrls(messageHtml), + attachments); - sendEmail(subject, content.getContentType(), content, recipients); + sendEmail(subject, mixed.getContentType(), mixed, recipients); } catch(MessagingException e) { // Should never occur @@ -166,21 +162,26 @@ public class MailServiceImpl implements MailService, Closeable { message.setFrom(getSenderAddress(smtpConfig)); - Address[] recipientsAddresses = Arrays.asList(recipients).stream().map(recipient -> { - try { - return new InternetAddress(recipient); - } - catch (AddressException e) { - throw new TechnicalException(String.format("Error while sending email. Bad recipient address [%s]", recipient), e); - } - }).collect(Collectors.toList()).toArray(new InternetAddress[recipients.length]); + Address[] recipientsAddresses = Arrays.stream(recipients) + .map(this::toInternetAddress) + .toArray(InternetAddress[]::new); - message.setRecipients(Message.RecipientType.TO, recipientsAddresses); + if (recipientsAddresses.length == 1) { + message.setRecipients(Message.RecipientType.TO, recipientsAddresses); + } + else { + message.setRecipients(Message.RecipientType.BCC, recipientsAddresses); + } message.setSubject(subject); - message.setContent(content, contentType); + if (content instanceof Multipart) { + message.setContent((Multipart)content); + } + else { + message.setContent(content, contentType); + } message.setSentDate(new java.util.Date()); - message.saveChanges(); + //message.saveChanges(); transport.sendMessage(message, message.getAllRecipients()); } catch (MessagingException e) { @@ -303,8 +304,6 @@ public class MailServiceImpl implements MailService, Closeable { } else { transport.connect(); } - } catch (NoSuchProviderException e) { - throw new TechnicalException(e); } catch (MessagingException e) { throw new TechnicalException(e); } @@ -325,11 +324,34 @@ public class MailServiceImpl implements MailService, Closeable { protected void configureJavaMailMimeTypes() { MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); - mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); + /*mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); //mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); mc.addMailcap("multipart/alternative;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed"); - mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822"); + mc.addMailcap("message/rfc822;; x-java-content- handler=com.sun.mail.handlers.message_rfc822");*/ + + mc.addMailcap("text/plain;; x-java-content-handler=com.sun.mail.handlers.text_plain"); + mc.addMailcap("text/html;; x-java-content-handler=com.sun.mail.handlers.text_html"); + mc.addMailcap("text/xml;; x-java-content-handler=com.sun.mail.handlers.text_xml"); + mc.addMailcap("multipart/*;; x-java-content-handler=com.sun.mail.handlers.multipart_mixed; x-java-fallback-entry=true"); + mc.addMailcap("message/rfc822;; x-java-content-handler=com.sun.mail.handlers.message_rfc822"); + } + + protected Multipart newChild(Multipart parent, String alternative) throws MessagingException { + MimeMultipart child = new MimeMultipart(alternative); + final MimeBodyPart mbp = new MimeBodyPart(); + parent.addBodyPart(mbp); + mbp.setContent(child); + return child; + } + + protected InternetAddress toInternetAddress(String address) { + try { + return new InternetAddress(address); + } + catch (AddressException e) { + throw new TechnicalException(String.format("Invalid email address: %s", address), e); + } } } \ No newline at end of file diff --git a/duniter4j-core-shared/src/test/java/org/duniter/core/service/MailServiceTest.java b/duniter4j-core-shared/src/test/java/org/duniter/core/service/MailServiceTest.java index 2953815bda7efdbf009e05a0c387b7e59c382f9b..25248a8bd50cc0690f49647cc812206229e66ac8 100644 --- a/duniter4j-core-shared/src/test/java/org/duniter/core/service/MailServiceTest.java +++ b/duniter4j-core-shared/src/test/java/org/duniter/core/service/MailServiceTest.java @@ -22,13 +22,25 @@ package org.duniter.core.service; * #L% */ +import com.google.common.collect.ImmutableList; +import com.google.common.collect.Lists; +import com.google.common.io.Files; +import org.apache.commons.io.FileUtils; import org.duniter.core.model.SmtpConfig; import org.duniter.core.test.TestFixtures; +import org.junit.Assert; import org.junit.Before; import org.junit.Ignore; import org.junit.Test; +import java.io.File; +import java.io.IOException; import java.io.UnsupportedEncodingException; +import java.net.MalformedURLException; +import java.net.URL; +import java.nio.charset.Charset; +import java.nio.charset.StandardCharsets; +import java.util.List; /** * Created by blavenie on 20/04/17. @@ -40,12 +52,13 @@ public class MailServiceTest { @Before public void setUp() throws UnsupportedEncodingException { service = new MailServiceImpl(); - SmtpConfig config = new SmtpConfig(); - config.setSenderName("test"); - config.setSenderAddress("no-reply@duniter.fr"); - config.setSmtpHost("localhost"); - config.setSmtpPort(25); - service.setSmtpConfig(config); + + service.setSmtpConfig(SmtpConfig.builder() + .senderName("test") + .senderAddress("no-reply@duniter.fr") + .smtpHost("localhost") + .smtpPort(25) + .build()); } @Test @@ -55,4 +68,36 @@ public class MailServiceTest { "a test content", "root@localhost"); } + + @Test + //@Ignore + public void sendHtmlEmailWithText() throws MalformedURLException { + + service.sendHtmlEmailWithText("Test " + System.currentTimeMillis() + " with HTML", + "a test text content", + "<b>a test HTML</b> content.", + "benoit.lavenier@e-is.pro"); + + service.sendHtmlEmailWithText("Test " + System.currentTimeMillis() + " with HTML and Image", + "a test text content", + "<b>a test HTML</b> content.<br/><img src=\"https://demo.cesium.app/img/logo_128px.png\">", + "benoit.lavenier@e-is.pro"); + + // Send file attachments + try { + File temp = new File("/tmp/mail-attachment.csv"); + FileUtils.write(temp, "col1;col2\nval1;val2", StandardCharsets.UTF_8); + + service.sendHtmlEmailWithText("Test " + System.currentTimeMillis() + " with HTML and Image + attachment", + "a test text content", + "<b>a test HTML</b> content.<br/><img src=\"https://demo.cesium.app/img/logo_128px.png\">", + Lists.newArrayList( + new URL("https://demo.cesium.app/img/logo_128px.png"), + new URL("file://" + temp.getAbsolutePath()) + ), + "benoit.lavenier@e-is.pro"); + } catch (IOException e) { + Assert.fail("error"); + } + } }