diff --git a/duniter4j-client/src/main/java/org/duniter/client/actions/validators/PubkeyValidator.java b/duniter4j-client/src/main/java/org/duniter/client/actions/validators/PubkeyValidator.java
index 17cee5811418b82b77dae4766c6db72911b0e4ae..8ad3c47944ae8ce1b61efafd566755d72e61ff30 100644
--- a/duniter4j-client/src/main/java/org/duniter/client/actions/validators/PubkeyValidator.java
+++ b/duniter4j-client/src/main/java/org/duniter/client/actions/validators/PubkeyValidator.java
@@ -1,5 +1,27 @@
 package org.duniter.client.actions.validators;
 
+/*
+ * #%L
+ * Duniter4j :: Client
+ * %%
+ * Copyright (C) 2014 - 2017 EIS
+ * %%
+ * This program is free software: you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation, either version 3 of the 
+ * License, or (at your option) any later version.
+ * 
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ * 
+ * You should have received a copy of the GNU General Public 
+ * License along with this program.  If not, see
+ * <http://www.gnu.org/licenses/gpl-3.0.html>.
+ * #L%
+ */
+
 import com.beust.jcommander.IParameterValidator;
 import com.beust.jcommander.ParameterException;
 import org.duniter.core.client.model.bma.Constants;
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java
index dfc6b61988c8a8a43cc36a7be56cc47dc60bd405..6837a79330cccfe0136b6b2596d13ae372614d26 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/Configuration.java
@@ -250,6 +250,14 @@ public class Configuration  {
         return applicationConfig.getOptionAsInt(ConfigurationOption.NETWORK_TIMEOUT.getKey());
     }
 
+    public int getNetworkMaxTotalConnections() {
+        return applicationConfig.getOptionAsInt(ConfigurationOption.NETWORK_MAX_CONNECTIONS.getKey());
+    }
+
+    public int getNetworkMaxConnectionsPerRoute() {
+        return applicationConfig.getOptionAsInt(ConfigurationOption.NETWORK_MAX_CONNECTIONS_PER_ROUTE.getKey());
+    }
+
     public int getNetworkCacheTimeInMillis() {
         return Integer.parseInt(ConfigurationOption.NETWORK_CACHE_TIME_IN_MILLIS.getDefaultValue());
     }
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java
index 606253e0c73a2e84b73a628b95c572532d869f3a..9c28f7ea4f86f5bab98b1b8c04ee104df043cbf1 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/config/ConfigurationOption.java
@@ -164,13 +164,28 @@ public enum ConfigurationOption implements ConfigOptionDef {
     NETWORK_TIMEOUT(
             "duniter4j.network.timeout",
             n("duniter4j.config.option.network.timeout.description"),
-            "20000", // = 2 s
+            "5000", // = 5 s
             Integer.class,
             false),
 
+    NETWORK_MAX_CONNECTIONS(
+            "duniter4j.network.maxConnections",
+            n("duniter4j.config.option.network.maxConnections.description"),
+            "100",
+            Integer.class,
+            false),
+
+    NETWORK_MAX_CONNECTIONS_PER_ROUTE(
+            "duniter4j.network.maxConnectionsPerHost",
+            n("duniter4j.config.option.network.maxConnectionsPerHost.description"),
+            "5",
+            Integer.class,
+            false),
+
+
     NETWORK_CACHE_TIME_IN_MILLIS (
-            "ucoin.network.cacheTimeInMillis",
-            "ucoin.config.option.network.cacheTimeInMillis.description",
+            "duniter4j.network.cacheTimeInMillis",
+            "duniter4j.config.option.network.cacheTimeInMillis.description",
             "10000",  // = 10 s
             Integer.class,
             false),
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
index 4522fecd42342e2510f63f92481268a47bf7fd01..652fd7d95b1390100cee5445b4607343181a57c4 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/HttpServiceImpl.java
@@ -27,14 +27,17 @@ import com.google.common.base.Joiner;
 import org.apache.http.HttpResponse;
 import org.apache.http.HttpStatus;
 import org.apache.http.client.HttpClient;
+import org.apache.http.client.config.CookieSpecs;
 import org.apache.http.client.config.RequestConfig;
 import org.apache.http.client.methods.CloseableHttpResponse;
 import org.apache.http.client.methods.HttpGet;
 import org.apache.http.client.methods.HttpUriRequest;
 import org.apache.http.client.utils.URIBuilder;
+import org.apache.http.config.SocketConfig;
 import org.apache.http.conn.ConnectTimeoutException;
 import org.apache.http.impl.client.CloseableHttpClient;
 import org.apache.http.impl.client.HttpClients;
+import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
 import org.apache.http.util.EntityUtils;
 import org.duniter.core.beans.InitializingBean;
 import org.duniter.core.client.config.Configuration;
@@ -70,6 +73,8 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
 
     public static final String URL_PEER_ALIVE = "/blockchain/parameters";
 
+    private PoolingHttpClientConnectionManager connectionManager;
+
     protected ObjectMapper objectMapper;
     protected Peer defaultPeer;
     private boolean debug;
@@ -99,16 +104,18 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
     protected void initCaches() {
         Configuration config = Configuration.instance();
         int cacheTimeInMillis = config.getNetworkCacheTimeInMillis();
-        int defaultTimeout = config.getNetworkTimeout();
+        final int defaultTimeout = config.getNetworkTimeout();
 
-        requestConfigCache = new SimpleCache<Integer, RequestConfig>(cacheTimeInMillis) {
+        requestConfigCache = new SimpleCache<Integer, RequestConfig>(cacheTimeInMillis*100) {
             @Override
             public RequestConfig load(Integer timeout) {
+                // Use config default timeout, if 0
+                if (timeout <= 0) timeout = defaultTimeout;
                 return createRequestConfig(timeout);
             }
         };
 
-        httpClientCache = new SimpleCache<Integer, HttpClient>(cacheTimeInMillis) {
+        httpClientCache = new SimpleCache<Integer, HttpClient>(cacheTimeInMillis*100) {
             @Override
             public HttpClient load(Integer timeout) {
                 return createHttpClient(timeout);
@@ -158,6 +165,8 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
             }
             wsEndPoints.clear();
         }
+
+        connectionManager.close();
     }
 
     public <T> T executeRequest(HttpUriRequest request, Class<? extends T> resultClass)  {
@@ -220,20 +229,40 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
         }
     }
 
+    protected PoolingHttpClientConnectionManager createConnectionManager(
+            int maxTotalConnections,
+            int maxConnectionsPerRoute,
+            int timeout) {
+        PoolingHttpClientConnectionManager connectionManager
+                = new PoolingHttpClientConnectionManager();
+        connectionManager.setMaxTotal(maxTotalConnections);
+        connectionManager.setDefaultMaxPerRoute(maxConnectionsPerRoute);
+        connectionManager.setDefaultSocketConfig(SocketConfig.custom()
+                .setSoTimeout(timeout).build());
+        return connectionManager;
+    }
+
     protected HttpClient createHttpClient(int timeout) {
-        CloseableHttpClient httpClient = HttpClients.custom().setDefaultRequestConfig(requestConfigCache.get(timeout))
-                // .setDefaultCredentialsProvider(getCredentialsProvider())
+        if (connectionManager == null) {
+            Configuration config = Configuration.instance();
+            connectionManager = createConnectionManager(
+                    config.getNetworkMaxTotalConnections(),
+                    config.getNetworkMaxConnectionsPerRoute(),
+                    config.getNetworkTimeout());
+        }
+
+        return HttpClients.custom()
+                .setConnectionManager(connectionManager)
+                .setDefaultRequestConfig(requestConfigCache.get(timeout))
                 .build();
-        return httpClient;
     }
 
     protected RequestConfig createRequestConfig(int timeout) {
-        // build request config for timeout
-        if (timeout <= 0) {
-            // Use config default timeout
-            timeout = Configuration.instance().getNetworkTimeout();
-        }
-        return RequestConfig.custom().setSocketTimeout(timeout).setConnectTimeout(timeout).build();
+        return RequestConfig.custom()
+                .setSocketTimeout(timeout).setConnectTimeout(timeout)
+                .setMaxRedirects(1)
+                .setCookieSpec(CookieSpecs.IGNORE_COOKIES)
+                .build();
     }
 
     protected <T> T executeRequest(HttpClient httpClient, HttpUriRequest request, Class<? extends T> resultClass)  {
@@ -481,4 +510,5 @@ public class HttpServiceImpl implements HttpService, Closeable, InitializingBean
     public <T> T readValue(InputStream json, Class<T> clazz) throws IOException {
         return objectMapper.readValue(json, clazz);
     }
+
 }
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkService.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkService.java
index f084cfd4aca7c690f92cef452b45b3d99b89a973..dae63b098ae52e1ff7a0330661732e8b161d7de3 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkService.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkService.java
@@ -71,6 +71,8 @@ public interface NetworkService extends Service {
 
     List<Peer> getPeers(Peer mainPeer, Filter filter, Sort sort);
 
+    List<Peer> getPeers(Peer mainPeer, Filter filter, Sort sort, ExecutorService pool);
+
     CompletableFuture<List<CompletableFuture<Peer>>> asyncGetPeers(Peer mainPeer, ExecutorService pool) throws ExecutionException, InterruptedException;
 
     List<Peer> fillPeerStatsConsensus(final List<Peer> peers);
diff --git a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkServiceImpl.java b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkServiceImpl.java
index 52e2fb97be703e86df53d328cb65fb4d98d92ea2..dd59a4436e5d25a805cf4b829f3285e41decf273 100644
--- a/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkServiceImpl.java
+++ b/duniter4j-core-client/src/main/java/org/duniter/core/client/service/local/NetworkServiceImpl.java
@@ -127,9 +127,14 @@ public class NetworkServiceImpl extends BaseRemoteServiceImpl implements Network
 
     @Override
     public List<Peer> getPeers(final Peer mainPeer, Filter filter, Sort sort) {
+        return getPeers(mainPeer, filter, sort, null);
+    }
+
+    @Override
+    public List<Peer> getPeers(final Peer mainPeer, Filter filter, Sort sort, ExecutorService executor) {
 
         try {
-            return asyncGetPeers(mainPeer, null)
+            return asyncGetPeers(mainPeer, executor)
                 .thenCompose(CompletableFutures::allOfToList)
                 .thenApply(this::fillPeerStatsConsensus)
                 .thenApply(peers -> peers.stream()
@@ -290,31 +295,16 @@ public class NetworkServiceImpl extends BaseRemoteServiceImpl implements Network
         final Comparator<Peer> peerComparator = peerComparator(sort);
         final ExecutorService pool = (executor != null) ? executor : ForkJoinPool.commonPool();
 
-        /*Runnable initCacheRunnable = () -> {
-            if (threadLock.isLocked()) return;
-            synchronized (threadLock) {
-                threadLock.lock();
-            }
-            try {
-                // TODO : load all peers from DAO, then fill list ?
-            }
-            catch(Exception e) {
-                log.error("Error while loading all peers: " + e.getMessage(), e);
-            }
-            finally {
-                synchronized (threadLock) {
-                    threadLock.unlock();
-                }
-            }
-        };*/
-
         Runnable getPeersRunnable = () -> {
-            if (threadLock.isLocked()) return;
+            if (threadLock.isLocked()) {
+                log.error("Rejected getPeersRunnable() call. Another refresh is already running...");
+                return;
+            }
             synchronized (threadLock) {
                 threadLock.lock();
             }
             try {
-                List<Peer> updatedPeers = getPeers(mainPeer, filter, sort);
+                List<Peer> updatedPeers = getPeers(mainPeer, filter, sort, pool);
 
                 knownPeers.clear();
                 updatedPeers.stream().forEach(peer -> {
@@ -340,7 +330,10 @@ public class NetworkServiceImpl extends BaseRemoteServiceImpl implements Network
         };
 
         Consumer<NetworkPeers.Peer> refreshPeerConsumer = (bmaPeer) -> {
-            if (threadLock.isLocked()) return;
+            if (threadLock.isLocked()) {
+                log.error("Rejected refreshPeerConsumer() call. Another refresh is already running...");
+                return;
+            }
             synchronized (threadLock) {
                 threadLock.lock();
             }
@@ -411,7 +404,7 @@ public class NetworkServiceImpl extends BaseRemoteServiceImpl implements Network
                 log.error("Could not parse peer received by WS: " + e.getMessage(), e);
             }
 
-            schedule(getPeersRunnable, pool, 5000);
+            schedule(getPeersRunnable, pool, 3000/*waiting block propagation*/);
         }, autoreconnect);
 
         // Manage new peer event
diff --git a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties
index 248b16f292e44931725b5969f49819a380a6fd16..3a45de92415dad6eba52d5622ec5dab908f613df 100644
--- a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties
+++ b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_en_GB.properties
@@ -12,6 +12,8 @@ duniter4j.config.option.data.directory.description=
 duniter4j.config.option.i18n.directory.description=
 duniter4j.config.option.i18n.locale.description=
 duniter4j.config.option.inceptionYear.description=
+duniter4j.config.option.network.maxConnections.description=
+duniter4j.config.option.network.maxConnectionsPerHost.description=
 duniter4j.config.option.network.timeout.description=
 duniter4j.config.option.node.currency.description=
 duniter4j.config.option.node.elasticsearch.host.description=
diff --git a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties
index 8e18b6c8e88f726af3ccfb6f55ea935420bb6949..1f9872aa69f948c9de1bd404131711c9686a306e 100644
--- a/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties
+++ b/duniter4j-core-client/src/main/resources/i18n/duniter4j-core-client_fr_FR.properties
@@ -12,6 +12,8 @@ duniter4j.config.option.data.directory.description=
 duniter4j.config.option.i18n.directory.description=
 duniter4j.config.option.i18n.locale.description=
 duniter4j.config.option.inceptionYear.description=
+duniter4j.config.option.network.maxConnections.description=
+duniter4j.config.option.network.maxConnectionsPerHost.description=
 duniter4j.config.option.network.timeout.description=
 duniter4j.config.option.node.currency.description=
 duniter4j.config.option.node.elasticsearch.host.description=
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 67ebaa21c4d02f143d3be87beb0124361596dbb9..8b7015600ea75e798ede9eb14746733ace2198cd 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
@@ -8,6 +8,7 @@ public class SmtpConfig {
     private String smtpUsername;
     private String smtpPassword;
     private String senderAddress;
+    private String senderName;
     private boolean useSsl;
     private boolean startTLS;
 
@@ -51,6 +52,14 @@ public class SmtpConfig {
         this.senderAddress = senderAddress;
     }
 
+    public String getSenderName() {
+        return senderName;
+    }
+
+    public void setSenderName(String senderName) {
+        this.senderName = senderName;
+    }
+
     public boolean isUseSsl() {
         return useSsl;
     }
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 6a19564a43c44a5a158f7be7050741d891d3da22..c53ad574ec0f0f818fc114ab8663183b326f32d3 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
@@ -26,6 +26,7 @@ import com.google.common.base.Joiner;
 import org.duniter.core.exception.TechnicalException;
 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 javax.activation.CommandMap;
@@ -33,6 +34,8 @@ import javax.activation.MailcapCommandMap;
 import javax.mail.*;
 import javax.mail.internet.*;
 import java.io.Closeable;
+import java.io.UnsupportedEncodingException;
+import java.net.InetAddress;
 import java.util.Arrays;
 import java.util.Properties;
 import java.util.stream.Collectors;
@@ -158,7 +161,8 @@ public class MailServiceImpl implements MailService, Closeable {
         // send email to recipients
         try {
             Message message = new MimeMessage(session);
-            message.setFrom(new InternetAddress(smtpConfig.getSenderAddress()));
+
+            message.setFrom(getSenderAddress(smtpConfig));
 
             Address[] recipientsAddresses = Arrays.asList(recipients).stream().map(recipient -> {
                 try {
@@ -190,6 +194,7 @@ public class MailServiceImpl implements MailService, Closeable {
         return getSmtpServerAsString(smtpConfig.getSmtpHost(), smtpConfig.getSmtpPort(), smtpConfig.getSmtpUsername());
     }
 
+
     private String getSmtpServerAsString(String smtpHost, int smtpPort, String smtpUsername) {
         StringBuilder buffer = new StringBuilder();
         if (StringUtils.isNotBlank(smtpUsername)) {
@@ -202,6 +207,19 @@ public class MailServiceImpl implements MailService, Closeable {
 
     }
 
+    private InternetAddress getSenderAddress(SmtpConfig smtpConfig) {
+        Preconditions.checkNotNull(smtpConfig);
+        try {
+            if (StringUtils.isNotBlank(smtpConfig.getSenderAddress())) {
+                return new InternetAddress(smtpConfig.getSenderAddress(), smtpConfig.getSenderName());
+            }
+            return new InternetAddress(smtpConfig.getSenderAddress());
+        }
+        catch(UnsupportedEncodingException | AddressException e) {
+            throw new TechnicalException(e);
+        }
+    }
+
     private void connect(String smtpHost, int smtpPort,
                          String smtpUsername,
                          String smtpPassword,
@@ -248,7 +266,10 @@ public class MailServiceImpl implements MailService, Closeable {
         props.put("mail.smtp.host", config.getSmtpHost());
         props.put("mail.smtp.port", config.getSmtpPort());
         if (StringUtils.isNotBlank(config.getSenderAddress())) {
-            props.put("mail.from", config.getSenderAddress());
+            props.put("mail.from.alias", config.getSenderAddress());
+            if (StringUtils.isNotBlank(config.getSenderName())) {
+                props.put("mail.from.alias", config.getSenderName());
+            }
         }
         if (config.isUseSsl()) {
             props.put("mail.smtp.socketFactory.port", config.getSmtpPort());
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
new file mode 100644
index 0000000000000000000000000000000000000000..13dfb4a6793c32c06003973630e083746bc4655f
--- /dev/null
+++ b/duniter4j-core-shared/src/test/java/org/duniter/core/service/MailServiceTest.java
@@ -0,0 +1,36 @@
+package org.duniter.core.service;
+
+import org.duniter.core.model.SmtpConfig;
+import org.duniter.core.test.TestFixtures;
+import org.junit.Before;
+import org.junit.Ignore;
+import org.junit.Test;
+
+import java.io.UnsupportedEncodingException;
+
+/**
+ * Created by blavenie on 20/04/17.
+ */
+public class MailServiceTest {
+
+    private MailService  service;
+
+    @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);
+    }
+
+    @Test
+    @Ignore
+    public void sendTextEmail() {
+        service.sendTextEmail("Test " + System.currentTimeMillis(),
+                "a test content",
+                "root@localhost");
+    }
+}
diff --git a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
index 4b37a882f4074c5bd772693a248ab927c18d1c35..ecddee4df3d7e601939d2c99cc4968fc0553de1a 100644
--- a/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
+++ b/duniter4j-es-assembly/src/main/assembly/config/elasticsearch.yml
@@ -128,6 +128,7 @@ duniter.blockchain.sync.enable: true
 duniter.host: gtest.duniter.org
 duniter.port: 10900
 #duniter.useSsl: true
+#duniter4j.network.timeout
 #
 # ---------------------------------- Duniter4j security -------------------------
 #
diff --git a/duniter4j-es-assembly/src/test/es-home/config/logging.yml b/duniter4j-es-assembly/src/test/es-home/config/logging.yml
index ad829d2029d741802ca251053c7068e5d7158a6a..ad8c49871136a509ce3074d05aa3d45b730b98b6 100644
--- a/duniter4j-es-assembly/src/test/es-home/config/logging.yml
+++ b/duniter4j-es-assembly/src/test/es-home/config/logging.yml
@@ -14,7 +14,7 @@ logger:
   com.amazonaws.jmx.SdkMBeanRegistrySupport: ERROR
   com.amazonaws.metrics.AwsSdkMetrics: ERROR
 
-  org.apache.http: INFO
+  org.apache.http: WARN
   org.apache.http.client: ERROR
 
   org.duniter: INFO
diff --git a/duniter4j-es-assembly/src/test/misc/test_es_query.sh b/duniter4j-es-assembly/src/test/misc/test_es_query.sh
new file mode 100755
index 0000000000000000000000000000000000000000..ea670c7611558f8fc53ab4a49fd9ffa4482fd83a
--- /dev/null
+++ b/duniter4j-es-assembly/src/test/misc/test_es_query.sh
@@ -0,0 +1,23 @@
+#!/bin/sh
+
+curl -XPOST 'http://localhost:9200/g1/block/_search?pretty' -d '
+   {
+     "size": 10000,
+     "query": {
+         "filtered": {
+           "filter": {
+             "bool": {
+               "must": [
+                 {
+                   "exists": {
+                     "field": "dividend"
+                   }
+                 }
+               ]
+             }
+           }
+         }
+       },
+       "_source": ["dividend", "monetaryMass", "membersCount"],
+       sort
+   }'
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java
index 2a6140c64e21b9fe7ee03263b3b85e8ccc465429..2157b179e7390494e231d4f7817327cc717615d3 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/PluginSettings.java
@@ -106,6 +106,8 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> {
         applicationConfig.setDefaultOption(ConfigurationOption.NODE_HOST.getKey(), getNodeBmaHost());
         applicationConfig.setDefaultOption(ConfigurationOption.NODE_PORT.getKey(), String.valueOf(getNodeBmaPort()));
         applicationConfig.setDefaultOption(ConfigurationOption.NETWORK_TIMEOUT.getKey(), String.valueOf(getNetworkTimeout()));
+        applicationConfig.setDefaultOption(ConfigurationOption.NETWORK_MAX_CONNECTIONS.getKey(), String.valueOf(getNetworkMaxConnections()));
+        applicationConfig.setDefaultOption(ConfigurationOption.NETWORK_MAX_CONNECTIONS_PER_ROUTE.getKey(), String.valueOf(getNetworkMaxConnectionsPerRoute()));
 
         try {
             applicationConfig.parse(new String[]{});
@@ -199,7 +201,15 @@ public class PluginSettings extends AbstractLifecycleComponent<PluginSettings> {
     }
 
     public int getNetworkTimeout()  {
-        return settings.getAsInt("duniter.network.timeout", 100000 /*10s*/);
+        return settings.getAsInt("duniter.network.timeout", 5000 /*5s*/);
+    }
+
+    public int getNetworkMaxConnections()  {
+        return settings.getAsInt("duniter.network.maxConnections", 100);
+    }
+
+    public int getNetworkMaxConnectionsPerRoute()  {
+        return settings.getAsInt("duniter.network.maxConnectionsPerRoute", 5);
     }
 
     public boolean isDevMode() {
diff --git a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/PeerService.java b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/PeerService.java
index 3a15b37b4a1c3e88a39c382be725490e3c17b415..83c531448b2bbf85d89483fab3698de66489a11e 100644
--- a/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/PeerService.java
+++ b/duniter4j-es-core/src/main/java/org/duniter/elasticsearch/service/PeerService.java
@@ -176,7 +176,9 @@ public class PeerService extends AbstractService {
 
         networkService.addPeersChangeListener(mainPeer, peers -> {
             if (CollectionUtils.isNotEmpty(peers)) {
-                logger.info(String.format("[%s] Updating peers endpoints (%s endpoints found)", currencyName, peers.size()));
+                if (logger.isDebugEnabled()) {
+                    logger.debug(String.format("[%s] Updating peers endpoints (%s endpoints found)", currencyName, peers.size()));
+                }
                 peers.stream().forEach(peer -> savePeer(peer));
             }
         }, filterDef, sortDef, true /*autoreconnect*/, threadPool.scheduler());
@@ -212,7 +214,9 @@ public class PeerService extends AbstractService {
 
         // Update existing peer
         else {
-            logger.trace(String.format("Update peer [%s]", peer));
+            if (logger.isTraceEnabled()) {
+                logger.trace(String.format("Update peer [%s]", peer));
+            }
             peerDao.update(peer);
         }
         return peer;
diff --git a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
index 266c713c768568b3b1638701d4dd29ecbd62bec5..727c652648cff630882ecce5ca2b5761deeaf386 100644
--- a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
+++ b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/service/SubscriptionService.java
@@ -57,6 +57,8 @@ import org.stringtemplate.v4.ST;
 import org.stringtemplate.v4.STGroup;
 import org.stringtemplate.v4.STGroupDir;
 
+import java.text.DateFormat;
+import java.text.SimpleDateFormat;
 import java.util.*;
 import java.util.concurrent.TimeUnit;
 import java.util.stream.Collectors;
@@ -131,18 +133,28 @@ public class SubscriptionService extends AbstractService {
             return this;
         }
 
-        // Daily execution
-        threadPool.scheduler().scheduleAtFixedRate(
-                () -> executeEmailSubscriptions(EmailSubscription.Frequency.daily),
-                DateUtils.delayBeforeHour(pluginSettings.getEmailSubscriptionsExecuteHour()),
-                1, TimeUnit.DAYS);
-
-        // Weekly execution
-        threadPool.scheduler().scheduleAtFixedRate(
-                () -> executeEmailSubscriptions(EmailSubscription.Frequency.weekly),
-                DateUtils.delayBeforeDayAndHour(pluginSettings.getEmailSubscriptionsExecuteDayOfWeek(), pluginSettings.getEmailSubscriptionsExecuteHour()),
-                7, TimeUnit.DAYS);
+        // Email subscriptions
+        {
+            if (logger.isInfoEnabled()) {
+                Calendar cal = new GregorianCalendar();
+                cal.setTimeInMillis(0);
+                cal.set(Calendar.DAY_OF_WEEK, pluginSettings.getEmailSubscriptionsExecuteDayOfWeek());
+                String dayOfWeek = new SimpleDateFormat("EEE").format(cal.getTime());
+                logger.warn(I18n.t("duniter4j.es.subscription.email.start", pluginSettings.getEmailSubscriptionsExecuteHour(), dayOfWeek));
+            }
 
+            // Daily execution
+            threadPool.scheduler().scheduleAtFixedRate(
+                    () -> executeEmailSubscriptions(EmailSubscription.Frequency.daily),
+                    DateUtils.delayBeforeHour(pluginSettings.getEmailSubscriptionsExecuteHour()),
+                    DateUtils.DAY_DURATION_IN_MILLIS, TimeUnit.MILLISECONDS);
+
+            // Weekly execution
+            threadPool.scheduler().scheduleAtFixedRate(
+                    () -> executeEmailSubscriptions(EmailSubscription.Frequency.weekly),
+                    DateUtils.delayBeforeDayAndHour(pluginSettings.getEmailSubscriptionsExecuteDayOfWeek(), pluginSettings.getEmailSubscriptionsExecuteHour()),
+                    7 * DateUtils.DAY_DURATION_IN_MILLIS, TimeUnit.MILLISECONDS);
+        }
         return this;
     }
 
diff --git a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/util/DateUtils.java b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/util/DateUtils.java
index 85162fe8c5b29b7685dff23e587b596e977e994a..a67fecb2d4feee9137289340fa0a6766092a9d92 100644
--- a/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/util/DateUtils.java
+++ b/duniter4j-es-subscription/src/main/java/org/duniter/elasticsearch/subscription/util/DateUtils.java
@@ -9,10 +9,13 @@ import java.util.GregorianCalendar;
  */
 public class DateUtils {
 
+    public static final long DAY_DURATION_IN_MILLIS = 24 * 60 * 60 * 1000;
+
+
     public static Date nextHour(int hour) {
         Calendar cal = new GregorianCalendar();
         cal.setTimeInMillis(System.currentTimeMillis());
-        if (cal.get(Calendar.HOUR_OF_DAY) > hour) {
+        if (cal.get(Calendar.HOUR_OF_DAY) >= hour) {
             // Too late for today: add 1 day (will wait tomorrow)
             cal.add(Calendar.DAY_OF_YEAR, 1);
         }
@@ -26,7 +29,7 @@ public class DateUtils {
     public static Date nextDayAndHour(int dayOfTheWeek, int hour) {
         Calendar cal = new GregorianCalendar();
         cal.setTimeInMillis(System.currentTimeMillis());
-        if (cal.get(Calendar.DAY_OF_WEEK) > dayOfTheWeek || (cal.get(Calendar.DAY_OF_WEEK) == dayOfTheWeek && cal.get(Calendar.HOUR_OF_DAY) > hour)) {
+        if (cal.get(Calendar.DAY_OF_WEEK) > dayOfTheWeek || (cal.get(Calendar.DAY_OF_WEEK) == dayOfTheWeek && cal.get(Calendar.HOUR_OF_DAY) >= hour)) {
             // Too late for this week: will wait for next week
             cal.add(Calendar.WEEK_OF_YEAR, 1);
         }
@@ -45,5 +48,7 @@ public class DateUtils {
     public static long delayBeforeDayAndHour(int dayOfTheWeek, int hour) {
         return nextDayAndHour(dayOfTheWeek, hour).getTime() - System.currentTimeMillis();
     }
+
+
 }
 
diff --git a/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_en_GB.properties b/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_en_GB.properties
index a02b913127a317b5b42ac38e41f331d5ea77043d..3277f18a7ba82c3dca3b0711603f4c4197cd0492 100644
--- a/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_en_GB.properties
+++ b/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_en_GB.properties
@@ -9,6 +9,7 @@ duniter4j.es.subscription.email.html.unreadCount=You received <b>%s new notifica
 duniter4j.es.subscription.email.notificationsDivider=Notifications list\:
 duniter4j.es.subscription.email.openCesium=Open Cesium+
 duniter4j.es.subscription.email.pubkey=Public key\: %2$s (%1$s)
+duniter4j.es.subscription.email.start=Email subscriptions\: daily mailing [at %1$s\:00] and weekly [on %2$s at %1$s\:00]
 duniter4j.es.subscription.email.subject=You received %s new notifications
 duniter4j.es.subscription.email.unreadCount=You received %s new notifications.
 duniter4j.es.subscription.error.mailDisabling=Unable to process email subscriptions\: Email sending is disabled in the configuration
diff --git a/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_fr_FR.properties b/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_fr_FR.properties
index c64cf822ca5fd6cf73d58b8abb85de91e35e30ca..28faba1c1aefaca12ba5fcd2c051d9d857535925 100644
--- a/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_fr_FR.properties
+++ b/duniter4j-es-subscription/src/main/resources/i18n/duniter4j-es-subscription_fr_FR.properties
@@ -9,6 +9,7 @@ duniter4j.es.subscription.email.html.unreadCount=Vous avez <b>%s notifications</
 duniter4j.es.subscription.email.notificationsDivider=Liste des notifications \:
 duniter4j.es.subscription.email.openCesium=Ouvrir Cesium+
 duniter4j.es.subscription.email.pubkey=Clé publique \: %2$s (%1$s)
+duniter4j.es.subscription.email.start=Abonnement email\: envoi quotidien [à %1$s\:00] et hebdomadaire [le %2$s à %1$s\:00]
 duniter4j.es.subscription.email.subject=%s nouvelles notifications non lues
 duniter4j.es.subscription.email.unreadCount=Vous avez %s notifications non lues.
 duniter4j.es.subscription.error.mailDisabling=Impossible de traiter les abonnements email\: la fonction d'envoi d'email est désactivée dans la configuration