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");
+        }
+    }
 }