diff --git a/src/archiver.cpp b/src/archiver.cpp
index 20a24975a504e6d2fc80a4b9c9e02346bd060a96..a916c6381cb25545d13552cda2b2be6d00b7ebe8 100644
--- a/src/archiver.cpp
+++ b/src/archiver.cpp
@@ -144,6 +144,14 @@ compressGzip(const std::string& str, const std::string& path)
     gzclose(fi);
 }
 
+void
+compressGzip(const std::vector<uint8_t>& dat, const std::string& path)
+{
+    auto fi = openGzip(path, "wb");
+    gzwrite(fi, dat.data(), dat.size());
+    gzclose(fi);
+}
+
 std::vector<uint8_t>
 decompressGzip(const std::string& path)
 {
@@ -169,7 +177,7 @@ decompress(const std::vector<uint8_t>& str)
     z_stream zs; // z_stream is zlib's control structure
     memset(&zs, 0, sizeof(zs));
 
-    if (inflateInit(&zs) != Z_OK)
+    if (inflateInit2(&zs, 32+MAX_WBITS) != Z_OK)
         throw std::runtime_error("inflateInit failed while decompressing.");
 
     zs.next_in = (Bytef*) str.data();
diff --git a/src/archiver.h b/src/archiver.h
index 5e84d25b4831ffff5f419141c94b6fdcca079c0a..5fa78a2d054f2101b2d0e15f9ea6d128fabaeb26 100644
--- a/src/archiver.h
+++ b/src/archiver.h
@@ -57,6 +57,7 @@ std::vector<uint8_t> decompress(const std::vector<uint8_t>& dat);
  * Compress string to a Gzip file
  */
 void compressGzip(const std::string& str, const std::string& path);
+void compressGzip(const std::vector<uint8_t>& dat, const std::string& path);
 
 /**
  * Decompress Gzip file to bytes
diff --git a/src/fileutils.cpp b/src/fileutils.cpp
index 7ea786a2e581573c7b61a9b6f81b478e4087bf63..aebe0d9d7d6e748157dac551a4bd85c6498358a4 100644
--- a/src/fileutils.cpp
+++ b/src/fileutils.cpp
@@ -535,24 +535,53 @@ readArchive(const std::string& path, const std::string& pwd)
 {
     JAMI_DBG("Reading archive from %s", path.c_str());
 
-    std::vector<uint8_t> data;
-    if (pwd.empty()) {
-        data = archiver::decompressGzip(path);
-    } else {
-        // Read file
+    auto isUnencryptedGzip = [](const std::vector<uint8_t>& data) {
+        // NOTE: some webserver modify gzip files and this can end with a gunzip in a gunzip
+        // file. So, to make the readArchive more robust, we can support this case by detecting
+        // gzip header via 1f8b 08
+        // We don't need to support more than 2 level, else somebody may be able to send
+        // gunzip in loops and abuse.
+        return data.size() > 3 && data[0] == 0x1f && data[1] == 0x8b && data[2] == 0x08;
+    };
+
+    auto decompress = [](std::vector<uint8_t>& data) {
         try {
-            data = loadFile(path);
+            data = archiver::decompress(data);
         } catch (const std::exception& e) {
-            JAMI_ERR("Error loading archive: %s", e.what());
+            JAMI_ERR("Error decrypting archive: %s", e.what());
             throw e;
         }
+    };
+
+    std::vector<uint8_t> data;
+    // Read file
+    try {
+        data = loadFile(path);
+    } catch (const std::exception& e) {
+        JAMI_ERR("Error loading archive: %s", e.what());
+        throw e;
+    }
+
+
+    if (isUnencryptedGzip(data)) {
+        if (!pwd.empty())
+            JAMI_WARN() << "A gunzip in a gunzip is detected. A webserver may have a bad config";
+
+        decompress(data);
+    }
+
+    if (!pwd.empty()) {
         // Decrypt
         try {
-            data = archiver::decompress(dht::crypto::aesDecrypt(data, pwd));
+            data = dht::crypto::aesDecrypt(data, pwd);
         } catch (const std::exception& e) {
             JAMI_ERR("Error decrypting archive: %s", e.what());
             throw e;
         }
+        decompress(data);
+    } else if (isUnencryptedGzip(data)) {
+        JAMI_WARN() << "A gunzip in a gunzip is detected. A webserver may have a bad config";
+        decompress(data);
     }
     return data;
 }
diff --git a/test/unitTest/Makefile.am b/test/unitTest/Makefile.am
index 95940fdc040aa06a72781ae8e75f9566b83e95c8..d7e0a9fb7ae5ffc545e8437faa0f1be4d9adf2d8 100644
--- a/test/unitTest/Makefile.am
+++ b/test/unitTest/Makefile.am
@@ -14,6 +14,12 @@ check_PROGRAMS =
 check_PROGRAMS += ut_account_factory
 ut_account_factory_SOURCES = account_factory/testAccount_factory.cpp common.cpp
 
+#
+# account_archive
+#
+check_PROGRAMS += ut_account_archive
+ut_account_archive_SOURCES = account_archive/account_archive.cpp common.cpp
+
 #
 # certstore
 #
diff --git a/test/unitTest/account_archive/account_archive.cpp b/test/unitTest/account_archive/account_archive.cpp
new file mode 100644
index 0000000000000000000000000000000000000000..845761e14918edeca88f5d0470e617ed94dde74a
--- /dev/null
+++ b/test/unitTest/account_archive/account_archive.cpp
@@ -0,0 +1,180 @@
+/*
+ *  Copyright (C) 2021 Savoir-faire Linux Inc.
+ *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *
+ *  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 <https://www.gnu.org/licenses/>.
+ */
+
+#include <cppunit/TestAssert.h>
+#include <cppunit/TestFixture.h>
+#include <cppunit/extensions/HelperMacros.h>
+
+#include <condition_variable>
+#include <string>
+#include <fstream>
+#include <streambuf>
+
+#include "manager.h"
+#include "jamidht/conversationrepository.h"
+#include "jamidht/connectionmanager.h"
+#include "jamidht/gitserver.h"
+#include "jamidht/jamiaccount.h"
+#include "../../test_runner.h"
+#include "archiver.h"
+#include "base64.h"
+#include "dring.h"
+#include "fileutils.h"
+#include "account_const.h"
+#include "common.h"
+
+#include <git2.h>
+#include <filesystem>
+
+using namespace std::string_literals;
+using namespace DRing::Account;
+
+namespace jami {
+namespace test {
+
+class AccountArchiveTest : public CppUnit::TestFixture
+{
+public:
+    AccountArchiveTest()
+    {
+        // Init daemon
+        DRing::init(DRing::InitFlag(DRing::DRING_FLAG_DEBUG | DRing::DRING_FLAG_CONSOLE_LOG));
+        if (not Manager::instance().initialized)
+            CPPUNIT_ASSERT(DRing::start("dring-sample.yml"));
+    }
+    ~AccountArchiveTest() { DRing::fini(); }
+    static std::string name() { return "AccountArchive"; }
+    void setUp();
+    void tearDown();
+
+    std::string aliceId;
+    std::string bobId;
+
+private:
+    void testExportImportNoPassword();
+    void testExportImportNoPasswordDoubleGunzip();
+    void testExportImportPassword();
+    void testExportImportPasswordDoubleGunzip();
+
+    CPPUNIT_TEST_SUITE(AccountArchiveTest);
+    CPPUNIT_TEST(testExportImportNoPassword);
+    CPPUNIT_TEST(testExportImportNoPasswordDoubleGunzip);
+    CPPUNIT_TEST(testExportImportPassword);
+    CPPUNIT_TEST(testExportImportPasswordDoubleGunzip);
+    CPPUNIT_TEST_SUITE_END();
+};
+
+CPPUNIT_TEST_SUITE_NAMED_REGISTRATION(AccountArchiveTest,
+                                      AccountArchiveTest::name());
+
+void
+AccountArchiveTest::setUp()
+{
+    auto actors = load_actors_and_wait_for_announcement("actors/alice-bob-password.yml");
+    aliceId = actors["alice"];
+    bobId = actors["bob"];
+}
+
+void
+AccountArchiveTest::tearDown()
+{
+    wait_for_removal_of({aliceId, bobId});
+}
+
+void
+AccountArchiveTest::testExportImportNoPassword()
+{
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+
+    CPPUNIT_ASSERT(aliceAccount->exportArchive("test.gz"));
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::ARCHIVE_PATH] = "test.gz";
+
+    auto accountId = jami::Manager::instance().addAccount(details);
+    wait_for_announcement_of(accountId);
+    auto alice2Account = Manager::instance().getAccount<JamiAccount>(accountId);
+    CPPUNIT_ASSERT(alice2Account->getUsername() == aliceAccount->getUsername());
+    std::remove("test.gz");
+    wait_for_removal_of(accountId);
+}
+
+void
+AccountArchiveTest::testExportImportNoPasswordDoubleGunzip()
+{
+    auto aliceAccount = Manager::instance().getAccount<JamiAccount>(aliceId);
+
+    CPPUNIT_ASSERT(aliceAccount->exportArchive("test.gz"));
+    auto dat = fileutils::loadFile("test.gz");
+    archiver::compressGzip(dat, "test.gz");
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::ARCHIVE_PATH] = "test.gz";
+
+    auto accountId = jami::Manager::instance().addAccount(details);
+    wait_for_announcement_of(accountId);
+    auto alice2Account = Manager::instance().getAccount<JamiAccount>(accountId);
+    CPPUNIT_ASSERT(alice2Account->getUsername() == aliceAccount->getUsername());
+    std::remove("test.gz");
+    wait_for_removal_of(accountId);
+}
+
+void
+AccountArchiveTest::testExportImportPassword()
+{
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+
+    CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "test"));
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::ARCHIVE_PATH] = "test.gz";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "test";
+
+    auto accountId = jami::Manager::instance().addAccount(details);
+    wait_for_announcement_of(accountId);
+    auto bob2Account = Manager::instance().getAccount<JamiAccount>(accountId);
+    CPPUNIT_ASSERT(bob2Account->getUsername() == bobAccount->getUsername());
+    std::remove("test.gz");
+    wait_for_removal_of(accountId);
+}
+
+void
+AccountArchiveTest::testExportImportPasswordDoubleGunzip()
+{
+    auto bobAccount = Manager::instance().getAccount<JamiAccount>(bobId);
+
+    CPPUNIT_ASSERT(bobAccount->exportArchive("test.gz", "test"));
+    auto dat = fileutils::loadFile("test.gz");
+    archiver::compressGzip(dat, "test.gz");
+
+    std::map<std::string, std::string> details = DRing::getAccountTemplate("RING");
+    details[ConfProperties::ARCHIVE_PATH] = "test.gz";
+    details[ConfProperties::ARCHIVE_PASSWORD] = "test";
+
+    auto accountId = jami::Manager::instance().addAccount(details);
+    wait_for_announcement_of(accountId);
+    auto bob2Account = Manager::instance().getAccount<JamiAccount>(accountId);
+    CPPUNIT_ASSERT(bob2Account->getUsername() == bobAccount->getUsername());
+    std::remove("test.gz");
+    wait_for_removal_of(accountId);
+}
+
+} // namespace test
+} // namespace jami
+
+RING_TEST_RUNNER(jami::test::AccountArchiveTest::name())