diff --git a/src/contactmodel.cpp b/src/contactmodel.cpp
index 257c9a1b7c090cb5cf3b5d35b8299a81ad8b7b01..5d2824507bfc45dd96665d526554c2d5b5df7010 100644
--- a/src/contactmodel.cpp
+++ b/src/contactmodel.cpp
@@ -210,10 +210,12 @@ ContactModel::addContact(contact::Info contactInfo)
     switch (profile.type) {
     case profile::Type::TEMPORARY:
         // NOTE: do not set profile::Type::RING, this has to be done when the daemon has emited contactAdded
-        #ifndef ENABLE_TEST // The old LRC doesn't like mocks
+#ifndef ENABLE_TEST // The old LRC doesn't like mocks
         if (auto* account = AccountModel::instance().getById(owner.id.c_str()))
             account->sendContactRequest(URI(profile.uri.c_str()));
-        #endif
+#else
+            ConfigurationManager::instance().addContact(owner.id.c_str(), profile.uri.c_str());
+#endif
         break;
     case profile::Type::PENDING:
         daemon::addContactFromPending(owner, profile.uri);
diff --git a/test/conversationmodeltester.cpp b/test/conversationmodeltester.cpp
index 0b83b98c8da19e4db36093b120fc2fc68eabaa9a..10ca9051afcc3e981041e571cf89cbcf8fee8809 100644
--- a/test/conversationmodeltester.cpp
+++ b/test/conversationmodeltester.cpp
@@ -1,6 +1,7 @@
 /*
  *  Copyright (C) 2017-2018 Savoir-faire Linux Inc.
  *  Author: Sébastien Blin <sebastien.blin@savoirfairelinux.com>
+ *  Author: Hugo Lefeuvre <hugo.lefeuvre@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
@@ -55,49 +56,145 @@ void
 ConversationModelTester::testAddValidConversation()
 {
     // Dummy should not be in contacts
-    auto contactId = accInfo_.contactModel->getContactProfileId("dummy");
-    CPPUNIT_ASSERT(contactId.empty());
-    // Search contact
-    accInfo_.conversationModel->setFilter("dummy");
-    WaitForSignalHelper(*accInfo_.contactModel,
-        SIGNAL(modelUpdated())).wait(1000);
-    // So, add dummy to contacts
-    auto newContactUri = accInfo_.conversationModel->owner.contactModel->getContact("").profileInfo.uri;
-    accInfo_.conversationModel->makePermanent(newContactUri);
-    auto contactAdded = WaitForSignalHelper(ConfigurationManager::instance(),
-        SIGNAL(contactAdded(const QString&, const QString&, bool))).wait(1000);
-    CPPUNIT_ASSERT_EQUAL(contactAdded, true);
+    CPPUNIT_ASSERT(!isAContact("dummy"));
+
+    auto newContactUri = addToContacts("dummy");
+
     // Dummy should be in contacts
-    contactId = accInfo_.contactModel->getContactProfileId("dummy");
-    CPPUNIT_ASSERT(!contactId.empty());
+    CPPUNIT_ASSERT(isAContact("dummy"));
+
     // So, a conversation should exists.
+    CPPUNIT_ASSERT(hasConversationWithContact("dummy"));
+}
+
+void
+ConversationModelTester::testPlaceCallWithBannedContact()
+{
+    // bannedContact should not be in contacts
+    CPPUNIT_ASSERT(!isAContact("badguy0"));
+
+    auto uri = addToContacts("badguy0");
+
+    // badguy0 should now be in contacts
+    CPPUNIT_ASSERT(isAContact("badguy0"));
+
+    // Ban badguy0
+    banContact(uri);
+    auto contactInfo = accInfo_.contactModel->getContact(uri);
+    CPPUNIT_ASSERT_EQUAL(contactInfo.isBanned, true);
+
+    // So, now that badguy0 is banned, calling him should be forbidden
     auto conversations = accInfo_.conversationModel->allFilteredConversations();
-    auto i = std::find_if(conversations.begin(), conversations.end(),
-    [](const lrc::api::conversation::Info& conversation) {
-        return std::find(conversation.participants.begin(),
-                         conversation.participants.end(),
-                         "dummy") != conversation.participants.end();
-    });
-    CPPUNIT_ASSERT(i != conversations.end());
+    bool conversationExists = false;
+    for (const auto& conversation: conversations) {
+        if (std::find(conversation.participants.begin(), conversation.participants.end(), contactInfo.profileInfo.uri) != conversation.participants.end()) {
+            conversationExists = true;
+            // Try to call banned contact
+            auto baseInteractionsSize = conversation.interactions.size();
+            accInfo_.conversationModel->placeCall(conversation.uid);
+            // Make sure call didn't succeed
+            CPPUNIT_ASSERT_EQUAL((int)baseInteractionsSize, (int)conversation.interactions.size());
+            break;
+        }
+    }
+
+    CPPUNIT_ASSERT(conversationExists);
+}
+
+void
+ConversationModelTester::testFilterBannedContact()
+{
+    // bannedContact should not be in contacts
+    CPPUNIT_ASSERT(!isAContact("bannedContact"));
+    CPPUNIT_ASSERT(!isAContact("bannedContacte"));
+    CPPUNIT_ASSERT(!isAContact("bannedContac"));
+
+    auto newContactUri = addToContacts("bannedContact");
+
+    // bannedContact now should be in contacts
+    CPPUNIT_ASSERT(isAContact("bannedContact"));
+
+    // Ban bannedContact
+    banContact(newContactUri);
+    auto contactInfo = accInfo_.contactModel->getContact(newContactUri);
+    CPPUNIT_ASSERT_EQUAL(contactInfo.isBanned, true);
+
+    // Make sure bannedContact doesn't appear is non-perfect-match filter searches
+    // We expect 1 (temporary item)
+    accInfo_.conversationModel->setFilter("bannedContac");
+    WaitForSignalHelper(*accInfo_.contactModel,
+        SIGNAL(modelUpdated())).wait(1000);
+    CPPUNIT_ASSERT_EQUAL(1, (int)accInfo_.conversationModel->allFilteredConversations().size());
+    auto isTemporary = accInfo_.conversationModel->filteredConversation(0).participants.front() == "";
+    CPPUNIT_ASSERT(isTemporary);
+    accInfo_.conversationModel->setFilter("bannedContacte");
+    WaitForSignalHelper(*accInfo_.contactModel,
+        SIGNAL(modelUpdated())).wait(1000);
+    CPPUNIT_ASSERT_EQUAL(1, (int)accInfo_.conversationModel->allFilteredConversations().size());
+    isTemporary = accInfo_.conversationModel->filteredConversation(0).participants.front() == "";
+    CPPUNIT_ASSERT(isTemporary);
+
+    // Make sure bannedContact appears in perfect-match filter searches
+    // We expect 1 (bannedContact)
+    accInfo_.conversationModel->setFilter("bannedContact");
+    WaitForSignalHelper(*accInfo_.contactModel,
+        SIGNAL(modelUpdated())).wait(1000);
+    CPPUNIT_ASSERT_EQUAL(1, (int)accInfo_.conversationModel->allFilteredConversations().size());
+    isTemporary = accInfo_.conversationModel->filteredConversation(0).participants.front() == "";
+    CPPUNIT_ASSERT(!isTemporary);
+}
+
+void
+ConversationModelTester::testSendMessageToBannedContact()
+{
+    // bannedContact should not be in contacts
+    CPPUNIT_ASSERT(!isAContact("badguy1"));
+
+    auto uri = addToContacts("badguy1");
+
+    // badguy1 should now be in contacts
+    CPPUNIT_ASSERT(isAContact("badguy1"));
+
+    // Ban badguy1
+    banContact(uri);
+    auto contactInfo = accInfo_.contactModel->getContact(uri);
+    CPPUNIT_ASSERT_EQUAL(contactInfo.isBanned, true);
+
+    // So, now that badguy is banned, sending a message should be forbidden
+    auto conversations = accInfo_.conversationModel->allFilteredConversations();
+    bool conversationExists = false;
+    for (const auto& conversation: conversations) {
+        if (std::find(conversation.participants.begin(), conversation.participants.end(), contactInfo.profileInfo.uri) != conversation.participants.end()) {
+            conversationExists = true;
+            // Try to send message to banned contact
+            auto baseInteractionsSize = conversation.interactions.size();
+            accInfo_.conversationModel->sendMessage(conversation.uid, "Hello banned !");
+            // Make sure message didn't arrive (but contact added is already here)
+            CPPUNIT_ASSERT_EQUAL((int)baseInteractionsSize, (int)conversation.interactions.size());
+            break;
+        }
+    }
+
+    CPPUNIT_ASSERT(conversationExists);
 }
 
 void
 ConversationModelTester::testAddInvalidConversation()
 {
     // notAContact should not be in contacts
-    auto contacts = accInfo_.contactModel->getAllContacts();
-    CPPUNIT_ASSERT(contacts.find("notAContact") == contacts.end());
+    CPPUNIT_ASSERT(!isAContact("notAContact"));
+
     // Search contact
     accInfo_.conversationModel->setFilter("notAContact");
     WaitForSignalHelper(*accInfo_.contactModel,
         SIGNAL(modelUpdated())).wait(1000);
-    // Temporary item should contains "Searching...notAContact"
+
+    // Temporary item should contain "Searching...notAContact"
     // makePermanent should not do anything
     accInfo_.conversationModel->makePermanent("");
     WaitForSignalHelper(ConfigurationManager::instance(),
         SIGNAL(contactAdded(const QString&, const QString&, bool))).wait(1000);
-    contacts = accInfo_.contactModel->getAllContacts();
-    CPPUNIT_ASSERT(contacts.find("notAContact") == contacts.end());
+    CPPUNIT_ASSERT(!isAContact("notAContact"));
 }
 
 void
@@ -112,18 +209,13 @@ ConversationModelTester::testRmConversation()
                          "contact0") != conversation.participants.end();
     });
     CPPUNIT_ASSERT(i != conversations.end());
+
     accInfo_.conversationModel->removeConversation((*i).uid);
     auto conversationRemoved = WaitForSignalHelper(*accInfo_.conversationModel,
         SIGNAL(conversationRemoved(const std::string& uid))).wait(1000);
     CPPUNIT_ASSERT(conversationRemoved);
-    conversations = accInfo_.conversationModel->allFilteredConversations();
-    i = std::find_if(conversations.begin(), conversations.end(),
-    [](const lrc::api::conversation::Info& conversation) {
-        return std::find(conversation.participants.begin(),
-                         conversation.participants.end(),
-                         "contact0") != conversation.participants.end();
-    });
-    CPPUNIT_ASSERT(i == conversations.end());
+
+    CPPUNIT_ASSERT(!hasConversationWithContact("contact0"));
 }
 
 void
@@ -135,6 +227,7 @@ ConversationModelTester::testFilterAndGetConversations()
         SIGNAL(modelUpdated())).wait(1000);
     auto conversations = accInfo_.conversationModel->allFilteredConversations();
     CPPUNIT_ASSERT_EQUAL((int)conversations.size(), 1);
+
     // Count when filter exact name
     auto contacts = accInfo_.contactModel->getAllContacts();
     CPPUNIT_ASSERT(contacts.size() != 0); // the daemon should return some contacts
@@ -146,6 +239,7 @@ ConversationModelTester::testFilterAndGetConversations()
     CPPUNIT_ASSERT_EQUAL((int)conversations.size(), 1); // We should see the contact
     auto firstConversation = accInfo_.conversationModel->filteredConversation(0);
     CPPUNIT_ASSERT_EQUAL(firstConversation.participants.front(), contactUri);
+
     // Count all contacts
     auto nbContact = 0;
     for (const auto& contact: contacts)
@@ -171,8 +265,8 @@ ConversationModelTester::testSendMessageAndClearHistory()
         for (const auto& conversation: conversations) {
         if (conversation.uid == firstConversation) {
             conversationExists = true;
-            // Should contains "Hello World!"
-            CPPUNIT_ASSERT_EQUAL((int)conversation.interactions.size(), 1);
+            // Should contains "Contact Added" + "Hello World!"
+            CPPUNIT_ASSERT_EQUAL((int)conversation.interactions.size(), 2);
             CPPUNIT_ASSERT_EQUAL((*conversation.interactions.rbegin()).second.body, std::string("Hello World!"));
             break;
         }
@@ -209,6 +303,7 @@ ConversationModelTester::testReceiveMessageAndSetRead()
     auto unreadMessage = WaitForSignalHelper(*accInfo_.conversationModel,
         SIGNAL(newUnreadMessage(const std::string&, uint64_t, const interaction::Info&))).wait(1000);
     CPPUNIT_ASSERT_EQUAL(unreadMessage, true);
+
     // This message should be unread
     conversations = accInfo_.conversationModel->allFilteredConversations();
     CPPUNIT_ASSERT(conversations.size() != 0);
@@ -216,6 +311,7 @@ ConversationModelTester::testReceiveMessageAndSetRead()
     auto lastInteraction = *firstConversation.interactions.rbegin();
     CPPUNIT_ASSERT(lastInteraction.second.status == lrc::api::interaction::Status::UNREAD);
     accInfo_.conversationModel->setInteractionRead(firstConversation.uid, lastInteraction.first);
+
     // Now, the interaction should be READ
     conversations = accInfo_.conversationModel->allFilteredConversations();
     CPPUNIT_ASSERT(conversations.size() != 0);
@@ -296,44 +392,91 @@ ConversationModelTester::testClearUnreadInteractions()
     auto conversations = accInfo_.conversationModel->allFilteredConversations();
     CPPUNIT_ASSERT(conversations.size() != 0);
     auto firstConversation = accInfo_.conversationModel->filteredConversation(0);
+    auto sender = firstConversation.participants.front().c_str();
+
     QMap<QString, QString> payloads;
-    // First message
+
+    // Send a first message
     payloads["text/plain"] = "This is not a message";
-    ConfigurationManager::instance().emitIncomingAccountMessage(accInfo_.id.c_str(),
-                                                                firstConversation.participants.front().c_str(), payloads);
+    ConfigurationManager::instance().emitIncomingAccountMessage(accInfo_.id.c_str(), sender, payloads);
     auto unreadMessage = WaitForSignalHelper(*accInfo_.conversationModel,
                                              SIGNAL(newUnreadMessage(const std::string&, uint64_t, const interaction::Info&))).wait(1000);
     CPPUNIT_ASSERT_EQUAL(unreadMessage, true);
-    // Second message
-    ConfigurationManager::instance().emitIncomingAccountMessage(accInfo_.id.c_str(),
-                                                                firstConversation.participants.front().c_str(), payloads);
+
+    // Send a second message
+    ConfigurationManager::instance().emitIncomingAccountMessage(accInfo_.id.c_str(), sender, payloads);
     unreadMessage = WaitForSignalHelper(*accInfo_.conversationModel,
                                              SIGNAL(newUnreadMessage(const std::string&, uint64_t, const interaction::Info&))).wait(1000);
     CPPUNIT_ASSERT_EQUAL(unreadMessage, true);
-    conversations = accInfo_.conversationModel->allFilteredConversations();
-    CPPUNIT_ASSERT(conversations.size() != 0);
+
+    // Make sure both messages are unread
     firstConversation = accInfo_.conversationModel->filteredConversation(0);
-    CPPUNIT_ASSERT(firstConversation.interactions.size() != 0);
-    for(auto&& interaction : firstConversation.interactions) {
-        CPPUNIT_ASSERT(interaction.second.status == lrc::api::interaction::Status::UNREAD);
-    }
+    auto interactions = firstConversation.interactions.rbegin();
+    CPPUNIT_ASSERT(interactions->second.status == lrc::api::interaction::Status::UNREAD);
+    CPPUNIT_ASSERT((++interactions)->second.status == lrc::api::interaction::Status::UNREAD);
+
     // Clear conversation of unread interactions
     accInfo_.conversationModel->clearUnreadInteractions(firstConversation.uid);
     auto conversationUpdated = WaitForSignalHelper(*accInfo_.conversationModel,
                                             SIGNAL(conversationUpdated(const std::string&))).wait(1000);
     CPPUNIT_ASSERT_EQUAL(conversationUpdated, true);
-    conversations = accInfo_.conversationModel->allFilteredConversations();
-    CPPUNIT_ASSERT(conversations.size() != 0);
+
+    // Now make sure both messages are read
     firstConversation = accInfo_.conversationModel->filteredConversation(0);
-    for(auto&& interaction : firstConversation.interactions) {
-        CPPUNIT_ASSERT(interaction.second.status == lrc::api::interaction::Status::READ);
-    }
+    interactions = firstConversation.interactions.rbegin();
+    CPPUNIT_ASSERT(interactions->second.status == lrc::api::interaction::Status::READ);
+    CPPUNIT_ASSERT((++interactions)->second.status == lrc::api::interaction::Status::READ);
 }
 
 void
 ConversationModelTester::tearDown()
 {
+}
+
+bool
+ConversationModelTester::hasConversationWithContact(std::string uri)
+{
+    auto conversations = accInfo_.conversationModel->allFilteredConversations();
+    auto i = std::find_if(conversations.begin(), conversations.end(),
+    [&uri](const lrc::api::conversation::Info& conversation) {
+        return std::find(conversation.participants.begin(),
+                         conversation.participants.end(),
+                         uri) != conversation.participants.end();
+    });
+    return i != conversations.end();
+}
+
+void
+ConversationModelTester::banContact(std::string uri)
+{
+    accInfo_.contactModel->removeContact(uri, true);
+    auto contactBanned = WaitForSignalHelper(ConfigurationManager::instance(),
+        SIGNAL(lrc::api::ConversationModel::filterChanged())).wait(2000);
+    CPPUNIT_ASSERT_EQUAL(contactBanned, true);
+}
+
+bool
+ConversationModelTester::isAContact(std::string uri)
+{
+    return !accInfo_.contactModel->getContactProfileId(uri).empty();
+}
+
+std::string
+ConversationModelTester::addToContacts(std::string username)
+{
+    // Search contact
+    accInfo_.conversationModel->setFilter(username);
+    WaitForSignalHelper(*accInfo_.contactModel,
+        SIGNAL(modelUpdated())).wait(1000);
+
+    // Add to contacts
+    auto uri = accInfo_.conversationModel->owner.contactModel->getContact("").profileInfo.uri;
+    accInfo_.conversationModel->makePermanent(uri);
+    auto contactAdded = WaitForSignalHelper(ConfigurationManager::instance(),
+        SIGNAL(contactAdded(const QString&, const QString&, bool))).wait(1000);
+    CPPUNIT_ASSERT_EQUAL(contactAdded, true);
 
+    return uri;
 }
 
 } // namespace test
diff --git a/test/conversationmodeltester.h b/test/conversationmodeltester.h
index 5fe9501a4b4a13c347016632052211df66cde56d..b88dc6c004ffa0a24271747693f2d25424383a41 100644
--- a/test/conversationmodeltester.h
+++ b/test/conversationmodeltester.h
@@ -51,6 +51,9 @@ class ConversationModelTester :  public CppUnit::TestFixture {
     CPPUNIT_TEST(testCreateConference);
     CPPUNIT_TEST(testPlaceAudioOnlyCall);
     CPPUNIT_TEST(testClearUnreadInteractions);
+    CPPUNIT_TEST(testSendMessageToBannedContact);
+    CPPUNIT_TEST(testFilterBannedContact);
+    CPPUNIT_TEST(testPlaceCallWithBannedContact);
     CPPUNIT_TEST_SUITE_END();
 
 public:
@@ -83,6 +86,14 @@ public:
      * Send "Hello World!" to the first conversation and clear the history
      */
     void testSendMessageAndClearHistory();
+    /**
+     * Make sure it is not possible to send a message to a banned contact
+     */
+    void testSendMessageToBannedContact();
+    /**
+     * Make sure banned contacts only appear in perfect-match filter searches.
+     */
+    void testFilterBannedContact();
     /**
      * Receives a message from a conversation and set this message READ
      */
@@ -91,6 +102,10 @@ public:
      * Call the first conversation
      */
     void testPlaceCall();
+    /**
+     * Make sure it is not possible to call a banned contact
+     */
+    void testPlaceCallWithBannedContact();
     /**
      * Start and audio-only call with the first conversation
      */
@@ -111,6 +126,25 @@ public:
 protected:
     std::unique_ptr<lrc::api::Lrc> lrc_;
     const lrc::api::account::Info& accInfo_;
+
+    // Helpers
+
+    /**
+     * Ban contact with passed uri
+     */
+    void banContact(std::string uri);
+    /**
+     * Return whether passed uri already maps to a contact or not
+     */
+    bool isAContact(std::string uri);
+    /**
+     * Add passed usename to contacts and return its uri
+     */
+    std::string addToContacts(std::string username);
+    /**
+     * Return whether a converation with passed contact uri exists or not
+     */
+    bool hasConversationWithContact(std::string uri);
 };
 
 } // namespace test
diff --git a/test/mocks/configurationmanager_mock.h b/test/mocks/configurationmanager_mock.h
index e7c883e1bd3dca1555eb6cfb15465112d8988223..180f9dfb9f255ce7e6b3f966b6f519f45baf1072 100644
--- a/test/mocks/configurationmanager_mock.h
+++ b/test/mocks/configurationmanager_mock.h
@@ -59,12 +59,18 @@ public:
       availableContacts_ << "contact0";
       availableContacts_ << "contact1";
       availableContacts_ << "contact2";
+      availableContacts_ << "badguy0";
+      availableContacts_ << "badguy1";
+      availableContacts_ << "bannedContact";
       availableContacts_ << "dummy";
       for (auto& account: getAccountList()) {
           auto contacts = VectorMapStringString();
           if (account.indexOf("ring") != -1) {
               for (auto& contactUri: availableContacts_) {
                   if (contactUri == "dummy") break;
+                  if (contactUri == "bannedContact") break;
+                  if (contactUri == "badguy0") break;
+                  if (contactUri == "badguy1") break;
                   auto contact = QMap<QString, QString>();
                   contact.insert("id", contactUri);
                   contact.insert("added", "true");
@@ -615,7 +621,12 @@ public Q_SLOTS: // METHODS
         auto contacts = accountToContactsMap[accountId];
         for (auto c = 0 ; c < contacts.size() ; ++c) {
             if (contacts.at(c)["id"] == uri) {
-                contacts.remove(c);
+                if (ban) {
+                    contacts[c].insert("removed", "true");
+                    contacts[c].insert("banned", "true");
+                } else {
+                    contacts.remove(c);
+                }
                 emit contactRemoved(accountId, uri, ban);
                 return;
             }