Skip to content
Snippets Groups Projects
Commit 71cba435 authored by Benoit Lavenier's avatar Benoit Lavenier
Browse files

[fix] Mail: add attachments, and embedded urls

parent c77f26f2
No related branches found
No related tags found
No related merge requests found
...@@ -22,6 +22,12 @@ package org.duniter.core.model; ...@@ -22,6 +22,12 @@ package org.duniter.core.model;
* #L% * #L%
*/ */
import lombok.*;
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class SmtpConfig { public class SmtpConfig {
...@@ -31,70 +37,11 @@ public class SmtpConfig { ...@@ -31,70 +37,11 @@ public class SmtpConfig {
private String smtpPassword; private String smtpPassword;
private String senderAddress; private String senderAddress;
private String senderName; 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) { @Builder.Default
this.useSsl = useSsl; private boolean useSsl = false;
}
public boolean isStartTLS() { @Builder.Default
return startTLS; private boolean startTLS = false;
}
public void setStartTLS(boolean startTLS) {
this.startTLS = startTLS;
}
} }
...@@ -28,6 +28,8 @@ import org.duniter.core.model.SmtpConfig; ...@@ -28,6 +28,8 @@ import org.duniter.core.model.SmtpConfig;
import javax.mail.internet.ContentType; import javax.mail.internet.ContentType;
import javax.mail.internet.ParseException; import javax.mail.internet.ParseException;
import java.net.URL;
import java.util.List;
/** /**
* Created by blavenie on 28/11/16. * Created by blavenie on 28/11/16.
...@@ -47,8 +49,14 @@ public interface MailService extends Bean { ...@@ -47,8 +49,14 @@ public interface MailService extends Bean {
void sendHtmlEmailWithText( void sendHtmlEmailWithText(
String subject, String subject,
String utf8textContent, String messageText,
String utf8HtmlContent, String messageHtml,
String... recipients); String... recipients);
void sendHtmlEmailWithText(
String subject,
String messageText,
String messageHtml,
List<URL> attachments,
String... recipients);
} }
...@@ -28,6 +28,7 @@ import org.duniter.core.model.SmtpConfig; ...@@ -28,6 +28,7 @@ import org.duniter.core.model.SmtpConfig;
import org.duniter.core.util.CollectionUtils; import org.duniter.core.util.CollectionUtils;
import org.duniter.core.util.Preconditions; import org.duniter.core.util.Preconditions;
import org.duniter.core.util.StringUtils; import org.duniter.core.util.StringUtils;
import org.duniter.core.util.mail.MailContentBuilder;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
...@@ -37,7 +38,9 @@ import javax.mail.*; ...@@ -37,7 +38,9 @@ import javax.mail.*;
import javax.mail.internet.*; import javax.mail.internet.*;
import java.io.Closeable; import java.io.Closeable;
import java.io.UnsupportedEncodingException; import java.io.UnsupportedEncodingException;
import java.net.URL;
import java.util.Arrays; import java.util.Arrays;
import java.util.List;
import java.util.Properties; import java.util.Properties;
import java.util.stream.Collectors; import java.util.stream.Collectors;
...@@ -96,32 +99,25 @@ public class MailServiceImpl implements MailService, Closeable { ...@@ -96,32 +99,25 @@ public class MailServiceImpl implements MailService, Closeable {
@Override @Override
public void sendHtmlEmailWithText(String subject, public void sendHtmlEmailWithText(String subject,
String textContent, String messageText,
String htmlContent, String messageHtml,
String... recipients) { String... recipients) {
try{ sendHtmlEmailWithText(subject, messageText, messageHtml, null, recipients);
}
Multipart content = new MimeMultipart("alternative");
// Add text part @Override
{ public void sendHtmlEmailWithText(String subject, String messageText, String messageHtml,
MimeBodyPart mbp = new MimeBodyPart(); List<URL> attachments,
ContentType contentType = new ContentType("text/plain"); String... recipients) {
contentType.setParameter("charset", "UTF-8"); try {
mbp.setContent(textContent, contentType.toString());
content.addBodyPart(mbp);
}
// Add html part MailContentBuilder mailContentBuilder = new MailContentBuilder();
{ final Multipart mixed = mailContentBuilder.build(messageText,
MimeBodyPart mbp = new MimeBodyPart(); messageHtml,
ContentType contentType = new ContentType("text/html"); mailContentBuilder.findUrls(messageHtml),
contentType.setParameter("charset", "UTF-8"); attachments);
mbp.setContent(htmlContent, contentType.toString());
content.addBodyPart(mbp);
}
sendEmail(subject, content.getContentType(), content, recipients); sendEmail(subject, mixed.getContentType(), mixed, recipients);
} }
catch(MessagingException e) { catch(MessagingException e) {
// Should never occur // Should never occur
...@@ -166,21 +162,26 @@ public class MailServiceImpl implements MailService, Closeable { ...@@ -166,21 +162,26 @@ public class MailServiceImpl implements MailService, Closeable {
message.setFrom(getSenderAddress(smtpConfig)); message.setFrom(getSenderAddress(smtpConfig));
Address[] recipientsAddresses = Arrays.asList(recipients).stream().map(recipient -> { Address[] recipientsAddresses = Arrays.stream(recipients)
try { .map(this::toInternetAddress)
return new InternetAddress(recipient); .toArray(InternetAddress[]::new);
}
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]);
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.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.setSentDate(new java.util.Date());
message.saveChanges(); //message.saveChanges();
transport.sendMessage(message, message.getAllRecipients()); transport.sendMessage(message, message.getAllRecipients());
} catch (MessagingException e) { } catch (MessagingException e) {
...@@ -303,8 +304,6 @@ public class MailServiceImpl implements MailService, Closeable { ...@@ -303,8 +304,6 @@ public class MailServiceImpl implements MailService, Closeable {
} else { } else {
transport.connect(); transport.connect();
} }
} catch (NoSuchProviderException e) {
throw new TechnicalException(e);
} catch (MessagingException e) { } catch (MessagingException e) {
throw new TechnicalException(e); throw new TechnicalException(e);
} }
...@@ -325,11 +324,34 @@ public class MailServiceImpl implements MailService, Closeable { ...@@ -325,11 +324,34 @@ public class MailServiceImpl implements MailService, Closeable {
protected void configureJavaMailMimeTypes() { protected void configureJavaMailMimeTypes() {
MailcapCommandMap mc = (MailcapCommandMap) CommandMap.getDefaultCommandMap(); 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/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("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/*;; 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("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
...@@ -22,13 +22,25 @@ package org.duniter.core.service; ...@@ -22,13 +22,25 @@ package org.duniter.core.service;
* #L% * #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.model.SmtpConfig;
import org.duniter.core.test.TestFixtures; import org.duniter.core.test.TestFixtures;
import org.junit.Assert;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Test; import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.io.UnsupportedEncodingException; 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. * Created by blavenie on 20/04/17.
...@@ -40,12 +52,13 @@ public class MailServiceTest { ...@@ -40,12 +52,13 @@ public class MailServiceTest {
@Before @Before
public void setUp() throws UnsupportedEncodingException { public void setUp() throws UnsupportedEncodingException {
service = new MailServiceImpl(); service = new MailServiceImpl();
SmtpConfig config = new SmtpConfig();
config.setSenderName("test"); service.setSmtpConfig(SmtpConfig.builder()
config.setSenderAddress("no-reply@duniter.fr"); .senderName("test")
config.setSmtpHost("localhost"); .senderAddress("no-reply@duniter.fr")
config.setSmtpPort(25); .smtpHost("localhost")
service.setSmtpConfig(config); .smtpPort(25)
.build());
} }
@Test @Test
...@@ -55,4 +68,36 @@ public class MailServiceTest { ...@@ -55,4 +68,36 @@ public class MailServiceTest {
"a test content", "a test content",
"root@localhost"); "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");
}
}
} }
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment