diff --git a/src/chat/chat-room/client-group-chat-room.cpp b/src/chat/chat-room/client-group-chat-room.cpp
index 12e54d1ce0422c4a48fe7a6ffe3cb75d3f8e4a1f..86a0e390a6baa4c8c59918bcbe3d8886a9b94cd6 100644
--- a/src/chat/chat-room/client-group-chat-room.cpp
+++ b/src/chat/chat-room/client-group-chat-room.cpp
@@ -314,7 +314,11 @@ RemoteConference(core, me->getAddress(), nullptr) {
 		getMe()->getPrivate()->addDevice(device->getAddress(), device->getName());
 
 	dConference->eventHandler->setConferenceId(conferenceId);
-	dConference->eventHandler->setLastNotify(lastNotifyId);
+	
+	bool_t forceFullState = linphone_config_get_bool(linphone_core_get_config(getCore()->getCCore()), "misc", "conference_event_package_force_full_state",FALSE );
+	dConference->eventHandler->setLastNotify(forceFullState?0:lastNotifyId);
+	lInfo() << "Last notify set to [" << dConference->eventHandler->getLastNotify() << "] for conference [" << dConference << "]";
+
 	if (!hasBeenLeft)
 		getCore()->getPrivate()->remoteListEventHandler->addHandler(dConference->eventHandler.get());
 }
@@ -725,7 +729,10 @@ void ClientGroupChatRoom::onFirstNotifyReceived (const IdentityAddress &addr) {
 		time(nullptr),
 		d->conferenceId
 	);
-	d->addEvent(event);
+	
+	bool_t forceFullState = linphone_config_get_bool(linphone_core_get_config(getCore()->getCCore()), "misc", "conference_event_package_force_full_state",FALSE );
+	if (!forceFullState) //to avoid this event to be repeated for each full state
+		d->addEvent(event);
 
 	LinphoneChatRoom *cr = d->getCChatRoom();
 	_linphone_chat_room_notify_conference_joined(cr, L_GET_C_BACK_PTR(event));
@@ -907,7 +914,14 @@ void ClientGroupChatRoom::onParticipantDeviceRemoved (const shared_ptr<Conferenc
 
 void ClientGroupChatRoom::onParticipantsCleared () {
 	L_D_T(RemoteConference, dConference);
+	//clear from db as well
+	for (const auto &participant : dConference->participants) {
+		getCore()->getPrivate()->mainDb->deleteChatRoomParticipant(getSharedFromThis(), participant->getAddress());
+		for (const auto &device : participant->getPrivate()->getDevices())
+			getCore()->getPrivate()->mainDb->deleteChatRoomParticipantDevice(getSharedFromThis(), device);
+	}
 	dConference->participants.clear();
+	
 }
 
 LINPHONE_END_NAMESPACE
diff --git a/src/chat/encryption/lime-x3dh-encryption-engine.cpp b/src/chat/encryption/lime-x3dh-encryption-engine.cpp
index 0682eb56c085304a7800adcc2ab410f7d9cf5af5..e40b5b702955933671d2a4337d248a2724001dad 100644
--- a/src/chat/encryption/lime-x3dh-encryption-engine.cpp
+++ b/src/chat/encryption/lime-x3dh-encryption-engine.cpp
@@ -371,10 +371,12 @@ ChatMessageModifier::Result LimeX3dhEncryptionEngine::processIncomingMessage (
 
 	// Discard incoming messages from unsafe peer devices
 	lime::PeerDeviceStatus peerDeviceStatus = limeManager->get_peerDeviceStatus(senderDeviceId);
-	if (peerDeviceStatus == lime::PeerDeviceStatus::unsafe) {
-		lWarning() << "LIME X3DH discard incoming message from unsafe sender device " << senderDeviceId;
-		errorCode = 488; // Not Acceptable
-		return ChatMessageModifier::Result::Error;
+	if (linphone_config_get_int(linphone_core_get_config(chatRoom->getCore()->getCCore()), "lime", "allow_message_in_unsafe_chatroom", 0) == 0) {
+		if (peerDeviceStatus == lime::PeerDeviceStatus::unsafe) {
+			lWarning() << "LIME X3DH discard incoming message from unsafe sender device " << senderDeviceId;
+			errorCode = 488; // Not Acceptable
+			return ChatMessageModifier::Result::Error;
+		}
 	}
 
 	// ---------------------------------------------- HEADERS
diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp
index e7a1708a743de4be5cf02365ae5888509aeacd5a..a2edf982b65aa4339e3c144af040bf06b7aedcfb 100644
--- a/src/db/main-db.cpp
+++ b/src/db/main-db.cpp
@@ -337,22 +337,22 @@ long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &cha
 	long long chatRoomId = selectChatRoomId(peerSipAddressId, localSipAddressId);
 	if (chatRoomId >= 0) {
 		// The chat room is already stored in DB, but still update the notify id that might have changed
+		lInfo() << "Update chat room in database: " << conferenceId << ".";
 		*dbSession.getBackendSession() << "UPDATE chat_room SET last_notify_id = :lastNotifyId WHERE id = :chatRoomId",
 			soci::use(notifyId), soci::use(chatRoomId);
-		return chatRoomId;
-	}
-
-	lInfo() << "Insert new chat room in database: " << conferenceId << ".";
-
-	const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
-	const tm &lastUpdateTime = Utils::getTimeTAsTm(chatRoom->getLastUpdateTime());
-
-	// Remove capabilities like `Proxy`.
-	const int &capabilities = chatRoom->getCapabilities() & ~ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Proxy);
-
-	const string &subject = chatRoom->getSubject();
-	const int &flags = chatRoom->hasBeenLeft();
-	*dbSession.getBackendSession() << "INSERT INTO chat_room ("
+	} else {
+		
+		lInfo() << "Insert new chat room in database: " << conferenceId << ".";
+		
+		const tm &creationTime = Utils::getTimeTAsTm(chatRoom->getCreationTime());
+		const tm &lastUpdateTime = Utils::getTimeTAsTm(chatRoom->getLastUpdateTime());
+		
+		// Remove capabilities like `Proxy`.
+		const int &capabilities = chatRoom->getCapabilities() & ~ChatRoom::CapabilitiesMask(ChatRoom::Capabilities::Proxy);
+		
+		const string &subject = chatRoom->getSubject();
+		const int &flags = chatRoom->hasBeenLeft();
+		*dbSession.getBackendSession() << "INSERT INTO chat_room ("
 		"  peer_sip_address_id, local_sip_address_id, creation_time,"
 		"  last_update_time, capabilities, subject, flags, last_notify_id"
 		") VALUES ("
@@ -361,9 +361,9 @@ long long MainDbPrivate::insertChatRoom (const shared_ptr<AbstractChatRoom> &cha
 		")",
 		soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(creationTime),
 		soci::use(lastUpdateTime), soci::use(capabilities), soci::use(subject), soci::use(flags), soci::use(notifyId);
-
-	chatRoomId = dbSession.getLastInsertId();
-
+		
+		chatRoomId = dbSession.getLastInsertId();
+	}
 	// Do not add 'me' when creating a server-group-chat-room.
 	if (conferenceId.getLocalAddress() != conferenceId.getPeerAddress()) {
 		shared_ptr<Participant> me = chatRoom->getMe();
@@ -2851,6 +2851,27 @@ void MainDb::updateChatRoomParticipantDevice (
 	};
 }
 
+void MainDb::deleteChatRoomParticipant (
+	const std::shared_ptr<AbstractChatRoom> &chatRoom,
+	const IdentityAddress &participant
+){
+	L_D();
+	const long long &dbChatRoomId = d->selectChatRoomId(chatRoom->getConferenceId());
+	const long long &participantSipAddressId = d->selectSipAddressId(participant.asString());
+	d->deleteChatRoomParticipant(dbChatRoomId, participantSipAddressId);
+}
+
+void MainDb::deleteChatRoomParticipantDevice (
+	const shared_ptr<AbstractChatRoom> &chatRoom,
+	const shared_ptr<ParticipantDevice> &device
+) {
+	L_D();
+	const long long &dbChatRoomId = d->selectChatRoomId(chatRoom->getConferenceId());
+	const long long &participantSipAddressId = d->selectSipAddressId(device->getParticipant()->getAddress().asString());
+	const long long &participantId = d->selectChatRoomParticipantId(dbChatRoomId, participantSipAddressId);
+	d->deleteChatRoomParticipantDevice(participantId, participantSipAddressId);
+}
+	
 // -----------------------------------------------------------------------------
 
 bool MainDb::import (Backend, const string &parameters) {
diff --git a/src/db/main-db.h b/src/db/main-db.h
index 5e92de7fae56b0d97fd4241e1803d1d74e06ced0..7ce57d797d22f46b918e39cd025040b87193f0fe 100644
--- a/src/db/main-db.h
+++ b/src/db/main-db.h
@@ -189,6 +189,16 @@ public:
 		const std::shared_ptr<ParticipantDevice> &device
 	);
 
+	void deleteChatRoomParticipant (
+		const std::shared_ptr<AbstractChatRoom> &chatRoom,
+		const IdentityAddress &participant
+	);
+	
+	void deleteChatRoomParticipantDevice (
+		const std::shared_ptr<AbstractChatRoom> &chatRoom,
+		const std::shared_ptr<ParticipantDevice> &device
+	);
+
 	// ---------------------------------------------------------------------------
 	// Other.
 	// ---------------------------------------------------------------------------
diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c
index ebe18a0a259257a6bed89aec5fca84c74e66ad9e..2e3135746001af423dbff234597d6e0b13a92ca1 100644
--- a/tester/group_chat_tester.c
+++ b/tester/group_chat_tester.c
@@ -70,6 +70,13 @@ static void chat_room_participant_device_added (LinphoneChatRoom *cr, const Linp
 	manager->stat.number_of_participant_devices_added++;
 }
 
+static void chat_room_participant_device_removed (LinphoneChatRoom *cr, const LinphoneEventLog *event_log) {
+	LinphoneCore *core = linphone_chat_room_get_core(cr);
+	LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core);
+	manager->stat.number_of_participant_devices_removed++;
+}
+
+
 static void chat_room_state_changed (LinphoneChatRoom *cr, LinphoneChatRoomState newState) {
 	LinphoneCore *core = linphone_chat_room_get_core(cr);
 	LinphoneCoreManager *manager = (LinphoneCoreManager *)linphone_core_get_user_data(core);
@@ -153,6 +160,7 @@ void core_chat_room_state_changed (LinphoneCore *core, LinphoneChatRoom *cr, Lin
 		linphone_chat_room_cbs_set_security_event(cbs, chat_room_security_event);
 		linphone_chat_room_cbs_set_subject_changed(cbs, chat_room_subject_changed);
 		linphone_chat_room_cbs_set_participant_device_added(cbs, chat_room_participant_device_added);
+		linphone_chat_room_cbs_set_participant_device_removed(cbs, chat_room_participant_device_removed);
 		linphone_chat_room_cbs_set_undecryptable_message_received(cbs, undecryptable_message_received);
 		linphone_chat_room_cbs_set_conference_joined(cbs, chat_room_conference_joined);
 		linphone_chat_room_add_callbacks(cr, cbs);
@@ -4815,6 +4823,8 @@ static void group_chat_lime_x3dh_reject_sas_before_message (void) {
 	BC_ASSERT_EQUAL(linphone_core_get_zrtp_status(marie->lc, linphone_address_as_string_uri_only(paulineAddr)), LinphoneZrtpPeerStatusValid, int , "%d");
 	BC_ASSERT_EQUAL(linphone_core_get_zrtp_status(pauline->lc, linphone_address_as_string_uri_only(marieAddr)), LinphoneZrtpPeerStatusValid, int , "%d");
 
+	
+	
 	// Delete chatrooms
 	linphone_core_manager_delete_chat_room(marie, marieCr, coresList);
 	linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList);
@@ -6987,8 +6997,6 @@ static void participant_removed_then_added (void) {
 	stats initialPauline1Stats = pauline1->stat;
 	stats initialLaureStats = laure->stat;
 	
-	
-	
 	// Marie creates a new group chat room
 	const char *initialSubject = "Colleagues";
 	LinphoneChatRoom *marie1Cr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, FALSE);
@@ -7053,6 +7061,133 @@ static void participant_removed_then_added (void) {
 	linphone_core_manager_destroy(laure);
 }
 
+static void group_chat_room_join_one_to_one_chat_room_with_a_new_device_not_notified(void) {
+	LinphoneCoreManager *marie1 = linphone_core_manager_create("marie_rc");
+	LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc");
+	bctbx_list_t *coresManagerList = NULL;
+	coresManagerList = bctbx_list_append(coresManagerList, marie1);
+	coresManagerList = bctbx_list_append(coresManagerList, pauline);
+	bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
+	start_core_for_conference(coresManagerList);
+	bctbx_list_t *participantsAddresses = bctbx_list_append(NULL, linphone_address_new(linphone_core_get_identity(pauline->lc)));
+	stats initialMarie1Stats = marie1->stat;
+	stats initialPaulineStats = pauline->stat;
+	
+	// Marie1 creates a new one-to-one chat room with Pauline
+	const char *initialSubject = "Pauline";
+	LinphoneChatRoom *marie1Cr = create_chat_room_client_side(coresList, marie1, &initialMarie1Stats, participantsAddresses, initialSubject, FALSE);
+	BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marie1Cr) & LinphoneChatRoomCapabilitiesOneToOne);
+	
+	LinphoneAddress *confAddr = linphone_address_clone(linphone_chat_room_get_conference_address(marie1Cr));
+	
+	// Check that the chat room is correctly created on Pauline's side and that the participants are added
+	LinphoneChatRoom *paulineCr = check_creation_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE);
+	BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(paulineCr) & LinphoneChatRoomCapabilitiesOneToOne);
+	
+	initialPaulineStats.number_of_participant_devices_added = pauline->stat.number_of_participant_devices_added;
+	LinphoneCoreManager *marie2 = linphone_core_manager_create("marie_rc");
+	stats initialMarie2Stats = marie2->stat;
+	
+	bctbx_list_t *newCoresManagerList = bctbx_list_append(NULL, marie2);
+	bctbx_list_t *newCoresList = init_core_for_conference(newCoresManagerList);
+	start_core_for_conference(newCoresManagerList);
+	coresManagerList = bctbx_list_concat(coresManagerList, newCoresManagerList);
+	coresList = bctbx_list_concat(coresList, newCoresList);
+	
+	// Marie2 gets the one-to-one chat room with Pauline
+	LinphoneChatRoom *marie2Cr = check_creation_chat_room_client_side(coresList, marie2, &initialMarie2Stats, confAddr, initialSubject, 1, FALSE);
+	BC_ASSERT_TRUE(linphone_chat_room_get_capabilities(marie2Cr) & LinphoneChatRoomCapabilitiesOneToOne);
+	
+	BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_devices_added, initialPaulineStats.number_of_participant_devices_added + 1, 3000));
+
+	// Save pauline db
+	const char *uri = lp_config_get_string(linphone_core_get_config(pauline->lc), "storage", "uri", "");
+	char *uriCopy = bc_tester_file("linphone_tester.db");
+	BC_ASSERT_FALSE(liblinphone_tester_copy_file(uri, uriCopy));
+	int initialPaulineEvent = linphone_chat_room_get_history_events_size(paulineCr);
+	// Simulate an uninstall of the application on Marie's side with unregistration (It should remove the device)
+	coresManagerList = bctbx_list_remove(coresManagerList, marie1);
+	coresList = bctbx_list_remove(coresList, marie1->lc);
+	initialPaulineStats = pauline->stat;
+	linphone_core_manager_destroy(marie1);
+	//force flexisip to publish on marie topic
+	linphone_core_refresh_registers(marie2->lc);
+	BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_participant_devices_removed, initialPaulineStats.number_of_participant_devices_removed + 1, 3000));
+
+	// Reset db at pauline side
+	pauline->database_path = uriCopy;
+	coresList = bctbx_list_remove(coresList, pauline->lc);
+	memset(&initialPaulineStats, 0, sizeof(initialPaulineStats));
+	
+	
+	linphone_core_manager_reinit(pauline);
+	//force full state
+	linphone_config_set_bool(linphone_core_get_config(pauline->lc), "misc", "conference_event_package_force_full_state",TRUE);
+	bctbx_list_t *tmpCoresManagerList = bctbx_list_append(NULL, pauline);
+	bctbx_list_t *tmpCoresList = init_core_for_conference(tmpCoresManagerList);
+	bctbx_list_free(tmpCoresManagerList);
+	coresList = bctbx_list_concat(coresList, tmpCoresList);
+	linphone_core_manager_start(pauline, TRUE);
+
+	//wait for first notify to be received by pauline
+	wait_for_list(coresList, NULL, 0, 1000);
+	
+	// Marie2 gets the one-to-one chat room with Pauline
+	paulineCr = check_has_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE);
+	LinphoneAddress *marieAddress = linphone_address_new(linphone_core_get_identity(marie2->lc));
+	LinphoneParticipant *marieParticipant =  linphone_chat_room_find_participant(paulineCr, marieAddress);
+	BC_ASSERT_EQUAL(bctbx_list_size(linphone_participant_get_devices (marieParticipant)), 1, int, "%i");
+	
+	//recheck after restart
+	coresList = bctbx_list_remove(coresList, pauline->lc);
+	linphone_core_manager_reinit(pauline);
+	linphone_config_set_bool(linphone_core_get_config(pauline->lc), "misc", "conference_event_package_force_full_state",FALSE);
+	tmpCoresManagerList = bctbx_list_append(NULL, pauline);
+	tmpCoresList = init_core_for_conference(tmpCoresManagerList);
+	bctbx_list_free(tmpCoresManagerList);
+	coresList = bctbx_list_concat(coresList, tmpCoresList);
+	linphone_core_manager_start(pauline, TRUE);
+	
+	
+	//wait for first notify to be received by pauline
+	wait_for_list(coresList, NULL, 0, 1000);
+	
+	// Marie2 gets the one-to-one chat room with Pauline
+	paulineCr = check_has_chat_room_client_side(coresList, pauline, &initialPaulineStats, confAddr, initialSubject, 1, FALSE);
+	marieParticipant =  linphone_chat_room_find_participant(paulineCr, marieAddress);
+	BC_ASSERT_EQUAL(bctbx_list_size(linphone_participant_get_devices (marieParticipant)), 1, int, "%i");
+	BC_ASSERT_EQUAL(linphone_chat_room_get_history_events_size(paulineCr), initialPaulineEvent, int, "%i");
+	
+	//check if we can still communicate
+	// Marie1 sends a message
+	const char *textMessage = "Hello";
+	LinphoneChatMessage *message = _send_message(marie2Cr, textMessage);
+	BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneMessageDelivered, initialMarie1Stats.number_of_LinphoneMessageDelivered + 1, 3000));
+	BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, initialPaulineStats.number_of_LinphoneMessageReceived + 1, 3000));
+	BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(pauline->stat.last_received_chat_message), textMessage);
+	linphone_chat_message_unref(message);
+	
+	// Pauline answers to the previous message
+	textMessage = "Hey. How are you?";
+	message = _send_message(paulineCr, textMessage);
+	BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, initialPaulineStats.number_of_LinphoneMessageDelivered + 1, 3000));
+	BC_ASSERT_TRUE(wait_for_list(coresList, &marie2->stat.number_of_LinphoneMessageReceived, initialMarie1Stats.number_of_LinphoneMessageReceived + 1, 3000));
+	BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(marie2->stat.last_received_chat_message), textMessage);
+	linphone_chat_message_unref(message);
+	
+	// Clean db from chat room
+	
+	linphone_core_manager_delete_chat_room(marie2, marie2Cr, coresList);
+	linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList);
+	
+	linphone_address_unref(confAddr);
+	bctbx_list_free(coresList);
+	bctbx_list_free(coresManagerList);
+	linphone_core_manager_destroy(marie2);
+	linphone_core_manager_destroy(pauline);
+}
+
+
 test_t group_chat_tests[] = {
 	TEST_NO_TAG("Group chat room creation server", group_chat_room_creation_server),
 	TEST_ONE_TAG("Add participant", group_chat_room_add_participant, "LeaksMemory"),
@@ -7134,7 +7269,8 @@ test_t group_chat_tests[] = {
 	TEST_TWO_TAGS("Search friend result chat room participants", search_friend_chat_room_participants, "MagicSearch", "LeaksMemory"),
 	TEST_ONE_TAG("Group chat room notify participant devices name", group_chat_room_participant_devices_name, "LeaksMemory" /* Core restarts */),
 	TEST_NO_TAG("Add device in one to one chat room where other participant left", add_device_one_to_one_chat_room_other_left),
-	TEST_ONE_TAG("Participant removed then added", participant_removed_then_added, "LeaksMemory" /*due to core restart*/)
+	TEST_ONE_TAG("Participant removed then added", participant_removed_then_added, "LeaksMemory" /*due to core restart*/),
+	TEST_ONE_TAG("Check  if participant device are removed", group_chat_room_join_one_to_one_chat_room_with_a_new_device_not_notified, "LeaksMemory" /*due to core restart*/)
 };
 
 test_suite_t group_chat_test_suite = {
diff --git a/tester/liblinphone_tester.h b/tester/liblinphone_tester.h
index 28087704af8226c4ffe1c2db46ec191fdb50638e..3de5775bccb809ccffaffe7b0195c5444c011a24 100644
--- a/tester/liblinphone_tester.h
+++ b/tester/liblinphone_tester.h
@@ -307,6 +307,7 @@ typedef struct _stats {
 	int number_of_participants_removed;
 	int number_of_subject_changed;
 	int number_of_participant_devices_added;
+	int number_of_participant_devices_removed;
 
 	int number_of_SecurityLevelDowngraded;
 	int number_of_ParticipantMaxDeviceCountExceeded;