diff --git a/src/account/account-params.cpp b/src/account/account-params.cpp
index 51c21e753f3afb315229c904b51fe8c898fd6a07..6b602b2e1969ad1241fdc7f73e8eb1949d05b718 100644
--- a/src/account/account-params.cpp
+++ b/src/account/account-params.cpp
@@ -949,7 +949,7 @@ LinphonePrivacyMask AccountParams::getPrivacy() const {
 	return mPrivacy;
 }
 
-std::shared_ptr<const Address> AccountParams::getIdentityAddress() const {
+std::shared_ptr<Address> AccountParams::getIdentityAddress() const {
 	return mIdentityAddress;
 }
 
diff --git a/src/account/account-params.h b/src/account/account-params.h
index b34453d5aae61a08ed981e52ffe9a8f995e36d55..fb14d4bdd5ba2e16b2b9b59baa264b1f31a398a7 100644
--- a/src/account/account-params.h
+++ b/src/account/account-params.h
@@ -145,7 +145,7 @@ public:
 	const std::list<std::string> getRoutesString() const;
 	const bctbx_list_t *getRoutesCString() const;
 	LinphonePrivacyMask getPrivacy() const;
-	std::shared_ptr<const Address> getIdentityAddress() const;
+	std::shared_ptr<Address> getIdentityAddress() const;
 	LinphoneAVPFMode getAvpfMode() const;
 	std::shared_ptr<NatPolicy> getNatPolicy() const;
 	PushNotificationConfig *getPushNotificationConfig() const;
diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp
index 36b002711cd653a27477af3bce82a78800740032..dd7b2c500fe890cab10b87927f1d7edf22373e02 100644
--- a/src/chat/chat-message/chat-message.cpp
+++ b/src/chat/chat-message/chat-message.cpp
@@ -800,28 +800,49 @@ std::string ChatMessagePrivate::createFakeFileTransferFromUrl(const std::string
 }
 
 void ChatMessagePrivate::setChatRoom(const shared_ptr<AbstractChatRoom> &chatRoom) {
+	L_Q();
 	mChatRoom = chatRoom;
 	const ConferenceId &conferenceId = chatRoom->getConferenceId();
 	const auto &account = chatRoom->getAccount();
-	// If an account is attached to a chatroom, use its contact address otherwise use the local address of the
-	// conference ID. Note that the conference ID's local address may not have the "gr" parameter hence this may lead to
-	// issues such as IMDN not received
+	const bool isBasicChatRoom =
+	    (chatRoom->getCurrentParams()->getChatParams()->getBackend() == ChatParams::Backend::Basic);
+	// If an account is attached to a chatroom, use its contact or the identity address otherwise use the local address
+	// of the conference ID. For Flexisip based chatrooms, it is paramount to use a contact address as the From header.
+	// RFC3428 forbids adding a Contact header to MESSAGE requests, therefore the From header is the only way a
+	// conference server knows which device sent the request and can be forwarded to the other tchat members as well as
+	// other devices of the same participant.
 	std::shared_ptr<Address> localAddress = nullptr;
-	if (account && account->getContactAddress()) {
-		localAddress = account->getContactAddress()->clone()->toSharedPtr();
-	} else {
-		lInfo() << "It looks that chatroom " << chatRoom << " with ID " << conferenceId
-		        << " has no account associated to or the contact address is not available yet, setting conference ID's "
-		           "local address as message local address";
-		localAddress = conferenceId.getLocalAddress()->clone()->toSharedPtr();
+	if (account) {
+		if (isBasicChatRoom) {
+			localAddress = account->getAccountParams()->getIdentityAddress();
+			lInfo() << *chatRoom << " with ID " << conferenceId
+			        << " is a basic chatroom therefore set the local address of message [" << q
+			        << "] to the account identity address " << *localAddress;
+		} else {
+			localAddress = account->getContactAddress();
+			if (localAddress) {
+				lInfo() << *chatRoom << " with ID " << conferenceId
+				        << " is not a basic chatroom therefore set the local address of message [" << q
+				        << "] to the account contact address " << *localAddress;
+			}
+		}
+	}
+	if (!localAddress) {
+		lInfo() << *chatRoom << " with ID " << conferenceId
+		        << " has no account associated to or the contact or the identity address is not available yet, setting "
+		           "conference ID's local address as message local address";
+		localAddress = conferenceId.getLocalAddress();
 	}
 
-	auto peerAddress = conferenceId.getPeerAddress()->clone()->toSharedPtr();
-	const bool isBasicChatRoom =
-	    (chatRoom->getCurrentParams()->getChatParams()->getBackend() == ChatParams::Backend::Basic);
-	if (isBasicChatRoom && localAddress) {
-		localAddress = Address::create(localAddress->getUriWithoutGruu());
+	if (localAddress) {
+		if (isBasicChatRoom) {
+			localAddress = Address::create(localAddress->getUriWithoutGruu());
+		} else {
+			localAddress = localAddress->clone()->toSharedPtr();
+		}
 	}
+
+	auto peerAddress = conferenceId.getPeerAddress()->clone()->toSharedPtr();
 	if (direction == ChatMessage::Direction::Outgoing) {
 		fromAddress = localAddress;
 		toAddress = peerAddress;
diff --git a/src/chat/chat-room/abstract-chat-room.h b/src/chat/chat-room/abstract-chat-room.h
index 2e762b32b21decdbf36993d4bb0dd6b1672df36b..dda0d01ddf704bc1a247da1814a2f0a0fa6d3baa 100644
--- a/src/chat/chat-room/abstract-chat-room.h
+++ b/src/chat/chat-room/abstract-chat-room.h
@@ -287,7 +287,7 @@ std::ostream &operator<<(std::ostream &lhs, AbstractChatRoom::EphemeralMode e);
 
 inline std::ostream &operator<<(std::ostream &str, const AbstractChatRoom &chatRoom) {
 	const auto &conferenceAddress = chatRoom.getConferenceAddress();
-	str << "Conference [" << &chatRoom << "] ("
+	str << "ChatRoom [" << &chatRoom << "] ("
 	    << (conferenceAddress ? conferenceAddress->toString() : std::string("sip:")) << ")";
 	return str;
 }
diff --git a/src/chat/modifier/cpim-chat-message-modifier.cpp b/src/chat/modifier/cpim-chat-message-modifier.cpp
index d135445de005fd52eac8ca39d6230f1d1ce6304a..88d21220d7e7c2a5bb060078c3693a36e6098b7a 100644
--- a/src/chat/modifier/cpim-chat-message-modifier.cpp
+++ b/src/chat/modifier/cpim-chat-message-modifier.cpp
@@ -59,11 +59,29 @@ const string imdnDispositionNotificationHeader = "Disposition-Notification";
 ChatMessageModifier::Result CpimChatMessageModifier::encode(const shared_ptr<ChatMessage> &message,
                                                             BCTBX_UNUSED(int &errorCode)) {
 	Cpim::Message cpimMessage;
-
-	cpimMessage.addMessageHeader(
-	    Cpim::FromHeader(cpimAddressUri(message->getFromAddress()), cpimAddressDisplayName(message->getFromAddress())));
-	cpimMessage.addMessageHeader(
-	    Cpim::ToHeader(cpimAddressUri(message->getToAddress()), cpimAddressDisplayName(message->getToAddress())));
+	shared_ptr<AbstractChatRoom> chatRoom = message->getChatRoom();
+	const auto &account = chatRoom->getAccount();
+	if (!account) {
+		lWarning() << "Unable to encode CPIM because the account attached to the message is unknown";
+		return ChatMessageModifier::Result::Error;
+	}
+	const bool isBasicChatRoom =
+	    (chatRoom->getCurrentParams()->getChatParams()->getBackend() == ChatParams::Backend::Basic);
+	std::shared_ptr<Address> localDevice;
+	// For non-basic tchat, prefer using the account contact address in case the message from address is the account's
+	// identity address. It will help the server to correctly dispatch requests to the other participants and sender
+	// devices
+	if (!isBasicChatRoom) {
+		localDevice = account->getContactAddress();
+	}
+	if (!localDevice) {
+		localDevice = message->getFromAddress();
+	}
+	localDevice = localDevice->clone()->toSharedPtr();
+	localDevice->setDisplayName("");
+	cpimMessage.addMessageHeader(Cpim::FromHeader(cpimAddressUri(localDevice), cpimAddressDisplayName(localDevice)));
+	const auto &to = message->getToAddress();
+	cpimMessage.addMessageHeader(Cpim::ToHeader(cpimAddressUri(to), cpimAddressDisplayName(to)));
 	cpimMessage.addMessageHeader(Cpim::DateTimeHeader(message->getTime()));
 
 	bool linphoneNamespaceHeaderSet = false;
@@ -313,7 +331,8 @@ CpimChatMessageModifier::createMinimalCpimContentForLimeMessage(const shared_ptr
 	const auto &localDevice =
 	    accountContactAddress ? accountContactAddress : chatRoom->getConferenceId().getLocalAddress();
 	if (!localDevice) {
-		lWarning() << "Unable to create CPIM because account [" << account << "] has not registered yet and the chatroom local address is unknown";
+		lWarning() << "Unable to create CPIM because " << *account
+		           << " has not registered yet and the chatroom local address is unknown";
 		return Content::create();
 	}
 	Cpim::Message cpimMessage;
diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c
index 3f40af194500d328639baed96334d672dbd76d34..74bb37d691870f8d092987f8143e36afa423f87c 100644
--- a/tester/group_chat_tester.c
+++ b/tester/group_chat_tester.c
@@ -1021,7 +1021,7 @@ static void group_chat_room_creation_core_restart(void) {
 		uuid = bctbx_strdup(linphone_config_get_string(linphone_core_get_config(marie->lc), "misc", "uuid", NULL));
 	}
 
-	ms_message("Restart %s'c core", linphone_core_get_identity(marie->lc));
+	ms_message("Restart %s's core", linphone_core_get_identity(marie->lc));
 	initialMarieStats = marie->stat;
 	coresList = bctbx_list_remove(coresList, marie->lc);
 	linphone_core_manager_reinit(marie);
@@ -6187,6 +6187,126 @@ end:
 	linphone_core_manager_destroy(chloe);
 }
 
+static void basic_chat_room_with_cpim_base(bool_t use_gruu) {
+	LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc");
+	LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc");
+	bctbx_list_t *coresManagerList = NULL;
+	coresManagerList = bctbx_list_append(coresManagerList, marie);
+	coresManagerList = bctbx_list_append(coresManagerList, pauline);
+	if (!use_gruu) {
+		linphone_core_remove_supported_tag(marie->lc, "gruu");
+	}
+	bctbx_list_t *coresList = init_core_for_conference(coresManagerList);
+	start_core_for_conference(coresManagerList);
+
+	// Enable CPIM
+	LinphoneAccount *marie_account = linphone_core_get_default_account(marie->lc);
+	const LinphoneAccountParams *marie_account_params = linphone_account_get_params(marie_account);
+	LinphoneAccountParams *cloned_marie_account_params = linphone_account_params_clone(marie_account_params);
+	linphone_account_params_enable_cpim_in_basic_chat_room(cloned_marie_account_params, TRUE);
+	linphone_account_set_params(marie_account, cloned_marie_account_params);
+	linphone_account_params_unref(cloned_marie_account_params);
+
+	LinphoneAccount *pauline_account = linphone_core_get_default_account(pauline->lc);
+	const LinphoneAccountParams *pauline_account_params = linphone_account_get_params(pauline_account);
+	LinphoneAccountParams *cloned_pauline_account_params = linphone_account_params_clone(pauline_account_params);
+	linphone_account_params_enable_cpim_in_basic_chat_room(cloned_pauline_account_params, TRUE);
+	linphone_account_set_params(pauline_account, cloned_pauline_account_params);
+	linphone_account_params_unref(cloned_pauline_account_params);
+
+	LinphoneAddress *pauline_contact_address = linphone_account_get_contact_address(pauline_account);
+
+	bctbx_list_t *participantsAddresses = NULL;
+	participantsAddresses = bctbx_list_append(participantsAddresses, pauline_contact_address);
+	LinphoneConferenceParams *marie_params = linphone_core_create_conference_params(marie->lc);
+	linphone_conference_params_enable_chat(marie_params, TRUE);
+	linphone_conference_params_enable_group(marie_params, FALSE);
+	LinphoneChatParams *marie_chat_params = linphone_conference_params_get_chat_params(marie_params);
+	linphone_chat_params_set_backend(marie_chat_params, LinphoneChatRoomBackendBasic);
+	LinphoneChatRoom *marieCr =
+	    linphone_core_create_chat_room_7(marie->lc, marie_params, marie->identity, participantsAddresses);
+	bctbx_list_free(participantsAddresses);
+	participantsAddresses = NULL;
+	linphone_chat_room_params_unref(marie_params);
+	BC_ASSERT_PTR_NOT_NULL(marieCr);
+	BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, 1,
+	                             liblinphone_tester_sip_timeout));
+
+	// Marie sends a message in a basic chatroom
+	const char *marie_text = "This is a basic chat room";
+	if (marieCr) {
+		const LinphoneAddress *peer_address = linphone_chat_room_get_peer_address(marieCr);
+		BC_ASSERT_TRUE(linphone_address_has_uri_param(peer_address, "gr"));
+		LinphoneChatMessage *sent_msg = _send_message(marieCr, marie_text);
+		BC_ASSERT_TRUE(
+		    wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageSent, 1, liblinphone_tester_sip_timeout));
+		BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneChatRoomStateCreated, 1,
+		                             liblinphone_tester_sip_timeout));
+		BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageReceived, 1,
+		                             liblinphone_tester_sip_timeout));
+		BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageDelivered, 1,
+		                             liblinphone_tester_sip_timeout));
+		linphone_chat_message_unref(sent_msg);
+	}
+
+	LinphoneConferenceParams *pauline_params = linphone_core_create_conference_params(pauline->lc);
+	linphone_conference_params_enable_chat(pauline_params, TRUE);
+	linphone_conference_params_enable_group(pauline_params, FALSE);
+	LinphoneChatParams *pauline_chat_params = linphone_conference_params_get_chat_params(pauline_params);
+	linphone_chat_params_set_backend(pauline_chat_params, LinphoneChatRoomBackendBasic);
+	const LinphoneAddress *pauline_identity_address =
+	    linphone_account_params_get_identity_address(linphone_account_get_params(pauline_account));
+	LinphoneChatRoom *paulineCr =
+	    linphone_core_search_chat_room_2(pauline->lc, pauline_params, pauline_identity_address, NULL, NULL);
+	BC_ASSERT_PTR_NOT_NULL(paulineCr);
+	linphone_chat_room_params_unref(pauline_params);
+
+	const char *pauline_text = "Yes Madam";
+	if (paulineCr) {
+		LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(paulineCr);
+		if (BC_ASSERT_PTR_NOT_NULL(msg)) {
+			BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), marie_text);
+			linphone_chat_message_unref(msg);
+		}
+		const LinphoneAddress *local_address = linphone_chat_room_get_local_address(paulineCr);
+		BC_ASSERT_TRUE(linphone_address_has_uri_param(local_address, "gr"));
+		LinphoneChatMessage *sent_msg = _send_message(paulineCr, pauline_text);
+		BC_ASSERT_TRUE(
+		    wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageSent, 1, liblinphone_tester_sip_timeout));
+		BC_ASSERT_FALSE(wait_for_list(coresList, &marie->stat.number_of_LinphoneChatRoomStateCreated, 2, 2000));
+		BC_ASSERT_TRUE(wait_for_list(coresList, &marie->stat.number_of_LinphoneMessageReceived, 1,
+		                             liblinphone_tester_sip_timeout));
+		BC_ASSERT_TRUE(wait_for_list(coresList, &pauline->stat.number_of_LinphoneMessageDelivered, 1,
+		                             liblinphone_tester_sip_timeout));
+		linphone_chat_message_unref(sent_msg);
+	}
+
+	if (marieCr) {
+		LinphoneChatMessage *msg = linphone_chat_room_get_last_message_in_history(marieCr);
+		if (BC_ASSERT_PTR_NOT_NULL(msg)) {
+			BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text(msg), pauline_text);
+			linphone_chat_message_unref(msg);
+		}
+		linphone_core_manager_delete_chat_room(marie, marieCr, coresList);
+		linphone_chat_room_unref(marieCr);
+	}
+	if (paulineCr) linphone_core_manager_delete_chat_room(pauline, paulineCr, coresList);
+
+	bctbx_list_free(coresList);
+	bctbx_list_free(coresManagerList);
+
+	linphone_core_manager_destroy(marie);
+	linphone_core_manager_destroy(pauline);
+}
+
+static void basic_chat_room_with_cpim_gruu(void) {
+	basic_chat_room_with_cpim_base(TRUE);
+}
+
+static void basic_chat_room_with_cpim_without_gruu(void) {
+	basic_chat_room_with_cpim_base(FALSE);
+}
+
 static void find_one_to_one_chat_room(void) {
 	LinphoneCoreManager *marie = linphone_core_manager_create("marie_rc");
 	LinphoneCoreManager *pauline = linphone_core_manager_create("pauline_rc");
@@ -9495,6 +9615,8 @@ test_t group_chat2_tests[] = {
     TEST_ONE_TAG("IMDN sent from DB state", imdn_sent_from_db_state, "LeaksMemory"),
     TEST_NO_TAG("IMDN updated for group chat room with one participant offline",
                 imdn_updated_for_group_chat_room_with_one_participant_offline),
+    TEST_NO_TAG("Basic chat room with CPIM and GRUU", basic_chat_room_with_cpim_gruu),
+    TEST_NO_TAG("Basic chat room with CPIM and without GRUU", basic_chat_room_with_cpim_without_gruu),
     TEST_NO_TAG("Find one-to-one chat room", find_one_to_one_chat_room),
     TEST_NO_TAG("Exhumed one-to-one chat room 1", exhume_one_to_one_chat_room_1),
     TEST_NO_TAG("Exhumed one-to-one chat room 2", exhume_one_to_one_chat_room_2),