diff --git a/coreapi/tester_utils.cpp b/coreapi/tester_utils.cpp
index defaec7abed4390c1bb9f426dd186441dbba6e48..6ad6c04b4d223e621a9b09763f61c38629adf0bc 100644
--- a/coreapi/tester_utils.cpp
+++ b/coreapi/tester_utils.cpp
@@ -345,3 +345,10 @@ int linphone_core_get_number_of_duplicated_messages(const LinphoneCore *core) {
 void linphone_core_set_account_deletion_timeout(LinphoneCore *core, unsigned int seconds) {
 	L_GET_CPP_PTR_FROM_C_OBJECT(core)->setAccountDeletionTimeout(seconds);
 }
+
+LinphoneChatRoom *
+linphone_core_create_basic_chat_room(LinphoneCore *core, const char *localSipUri, const char *remoteSipUri) {
+	return L_GET_CPP_PTR_FROM_C_OBJECT(core)
+	    ->getOrCreateBasicChatRoomFromUri(L_C_TO_STRING(localSipUri), L_C_TO_STRING(remoteSipUri))
+	    ->toC();
+}
\ No newline at end of file
diff --git a/coreapi/tester_utils.h b/coreapi/tester_utils.h
index 0d51f65c270aa93e079670635fe1e38d430bd25a..941431ac47732614088a46ff02ea35e0329e745f 100644
--- a/coreapi/tester_utils.h
+++ b/coreapi/tester_utils.h
@@ -450,6 +450,9 @@ LINPHONE_PUBLIC void linphone_core_enable_gruu_in_conference_address(LinphoneCor
  **/
 LINPHONE_PUBLIC bool_t linphone_core_gruu_in_conference_address_enabled(const LinphoneCore *core);
 
+LINPHONE_PUBLIC LinphoneChatRoom *
+linphone_core_create_basic_chat_room(LinphoneCore *core, const char *localSipUri, const char *remoteSipUri);
+
 #ifdef __cplusplus
 }
 #endif
diff --git a/include/linphone/api/c-chat-room.h b/include/linphone/api/c-chat-room.h
index 48e83898aea5c8abc474e3ff90aeddf44b461120..8fa6848705766a279a311eccd27cce9208903494 100644
--- a/include/linphone/api/c-chat-room.h
+++ b/include/linphone/api/c-chat-room.h
@@ -141,6 +141,13 @@ LINPHONE_PUBLIC const LinphoneAddress *linphone_chat_room_get_local_address(Linp
  */
 LINPHONE_PUBLIC const char *linphone_chat_room_get_identifier(const LinphoneChatRoom *chat_room);
 
+/**
+ * Returns the local account to which this chat room is related.
+ * @param chat_room The #LinphoneChatRoom object. @notnil
+ * @return the related #LinphoneAccount object if any, NULL otherwise. @maybenil
+ */
+LINPHONE_PUBLIC LinphoneAccount *linphone_chat_room_get_account(LinphoneChatRoom *chat_room);
+
 /**
  * Used to receive a chat message when using async mechanism with IM enchat_roomyption engine
  * @param chat_room #LinphoneChatRoom object @notnil
diff --git a/src/c-wrapper/api/c-chat-room.cpp b/src/c-wrapper/api/c-chat-room.cpp
index 9b079762abe384f07aef585be2188794fe096ecf..ef7c248ac27c158010389b3286cc5894c8b2b0a3 100644
--- a/src/c-wrapper/api/c-chat-room.cpp
+++ b/src/c-wrapper/api/c-chat-room.cpp
@@ -113,6 +113,11 @@ const char *linphone_chat_room_get_identifier(const LinphoneChatRoom *chat_room)
 	return NULL;
 }
 
+LinphoneAccount *linphone_chat_room_get_account(LinphoneChatRoom *chat_room) {
+	shared_ptr<Account> account = AbstractChatRoom::toCpp(chat_room)->getAccount();
+	return (account) ? account->toC() : nullptr;
+}
+
 LinphoneChatMessage *linphone_chat_room_create_empty_message(LinphoneChatRoom *chat_room) {
 	ChatRoomLogContextualizer logContextualizer(chat_room);
 	shared_ptr<ChatMessage> cppPtr = AbstractChatRoom::toCpp(chat_room)->createChatMessage();
diff --git a/src/chat/chat-room/basic-chat-room.cpp b/src/chat/chat-room/basic-chat-room.cpp
index 819abe5449f20b5ba29e924481cdfad7016f7975..3008ca34979eb54b33bb1c4684fa0bf01a8f0ec5 100644
--- a/src/chat/chat-room/basic-chat-room.cpp
+++ b/src/chat/chat-room/basic-chat-room.cpp
@@ -116,6 +116,10 @@ const ConferenceId &BasicChatRoom::getConferenceId() const {
 	return mConferenceId;
 }
 
+void BasicChatRoom::setConferenceId(const ConferenceId &conferenceId) {
+	mConferenceId = conferenceId;
+}
+
 std::optional<std::reference_wrapper<const std::string>> BasicChatRoom::getIdentifier() const {
 	if (mState == ConferenceInterface::State::Instantiated) {
 		return std::nullopt;
diff --git a/src/chat/chat-room/basic-chat-room.h b/src/chat/chat-room/basic-chat-room.h
index b94259b7d3bc2eecb14bd8361495c10ccd21825e..bc4cb20cf74d4c0e7bbd0fee9b44ae5f463b5f15 100644
--- a/src/chat/chat-room/basic-chat-room.h
+++ b/src/chat/chat-room/basic-chat-room.h
@@ -44,6 +44,7 @@ public:
 	bool isReadOnly() const override;
 
 	const ConferenceId &getConferenceId() const override;
+	void setConferenceId(const ConferenceId &conferenceId);
 	std::optional<std::reference_wrapper<const std::string>> getIdentifier() const override;
 
 	void invalidateAccount() override;
diff --git a/src/conference/conference.h b/src/conference/conference.h
index 705a2b7f0bdc58a8a5b8d591cdb6f23dbb6e50b0..e8a72aa5501bcc0b85c7fc21554cbb782419d148 100644
--- a/src/conference/conference.h
+++ b/src/conference/conference.h
@@ -355,6 +355,8 @@ public:
 
 	void resetLastNotify();
 
+	void setConferenceId(const ConferenceId &conferenceId);
+
 protected:
 	explicit Conference(const std::shared_ptr<Core> &core,
 	                    std::shared_ptr<CallSessionListener> callSessionListener,
@@ -433,8 +435,6 @@ protected:
 	void incrementLastNotify();
 	void setLastNotify(unsigned int lastNotify);
 
-	void setConferenceId(const ConferenceId &conferenceId);
-
 	void setChatRoom(const std::shared_ptr<AbstractChatRoom> &chatRoom);
 
 	std::unique_ptr<LogContextualizer> getLogContextualizer() override;
diff --git a/src/conference/session/call-session.cpp b/src/conference/session/call-session.cpp
index 82eef613610c4724a9de84c73876d327a44575c3..d08b8cb6cfeb032be4771f9f2720a94d670aefa4 100644
--- a/src/conference/session/call-session.cpp
+++ b/src/conference/session/call-session.cpp
@@ -1486,24 +1486,22 @@ void CallSession::assignAccount(const std::shared_ptr<Account> &account) {
 				cAccount = linphone_core_lookup_account_by_conference_factory_strict(core, toAddr);
 			}
 			if (!cAccount) {
-				cAccount = linphone_core_lookup_account_by_identity_strict(core, toAddr);
-				if (!cAccount) {
-					string toUser = d->log->getToAddress()->getUsername();
-					if (!toUser.empty()) {
-						cAccount = linphone_core_lookup_known_account_2(core, fromAddr, FALSE);
-						if (cAccount &&
-						    Account::toCpp(cAccount)->getAccountParams()->getIdentityAddress()->getUsername() ==
-						        toUser) {
-							// We have a match for the from domain and the to username.
-							// We may face an IPBPX that sets the To domain to our IP address, which is
-							// a terribly stupid idea.
-							lWarning() << "Detecting to header probably ill-choosen. Applying workaround to have this "
-							              "call assigned to a known account.";
-							// We must "hack" the call-log so it is correctly reported for this Account.
-							d->log->setToAddress(Account::toCpp(cAccount)->getAccountParams()->getIdentityAddress());
-						}
+				auto account = getCore()->findAccountByIdentityAddress(d->log->getToAddress());
+				if (!account) {
+					account = getCore()->guessLocalAccountFromMalformedMessage(d->log->getToAddress(),
+					                                                           d->log->getFromAddress());
+					if (account) {
+						// We have a match for the from domain and the to username.
+						// We may face an IPBPX that sets the To domain to our IP address, which is
+						// a terribly stupid idea.
+						lWarning() << "Applying workaround to have this call assigned to a known account.";
+						// We must "hack" the call-log so it is correctly reported for this Account.
+						d->log->setToAddress(account->getAccountParams()->getIdentityAddress());
 					}
 				}
+				if (account) {
+					cAccount = account->toC();
+				}
 			}
 		} else {
 			cAccount = linphone_core_lookup_account_by_identity(core, fromAddr);
diff --git a/src/core/core-chat-room.cpp b/src/core/core-chat-room.cpp
index f81cbf1108128def367969c781956d4b69a746c0..7035df4daaac20456660801fcbd43d10fdc07b34 100644
--- a/src/core/core-chat-room.cpp
+++ b/src/core/core-chat-room.cpp
@@ -929,6 +929,30 @@ LinphoneReason Core::onSipMessageReceived(SalOp *op, const SalMessage *sal_msg)
 	ConferenceId conferenceId(std::move(peerAddress), std::move(localAddress), createConferenceIdParams());
 	shared_ptr<AbstractChatRoom> chatRoom = findChatRoom(conferenceId, false);
 	if (chatRoom) {
+		bool isBasic = (chatRoom->getCurrentParams()->getChatParams()->getBackend() == ChatParams::Backend::Basic);
+		if (isBasic) {
+			auto localAccount =
+			    guessLocalAccountFromMalformedMessage(conferenceId.getLocalAddress(), conferenceId.getPeerAddress());
+			if (localAccount) {
+				// We have a match for the from domain and the to username.
+				// We may face an IPBPX that sets the To domain to our IP address, which is
+				// a terribly stupid idea.
+				lWarning() << "Applying workaround to have this existing chat room assigned to a known account.";
+				auto oldConfId = chatRoom->getConferenceId();
+				conferenceId.setLocalAddress(localAccount->getAccountParams()->getIdentityAddress(), true);
+
+				d->mainDb->updateChatRoomConferenceId(oldConfId, conferenceId);
+
+				auto basicChatRoom = dynamic_pointer_cast<BasicChatRoom>(chatRoom);
+				basicChatRoom->setConferenceId(conferenceId);
+
+				d->mChatRoomsById.erase(oldConfId);
+				d->mChatRoomsById[conferenceId] = chatRoom;
+
+				updateChatRoomList();
+			}
+		}
+
 		reason = handleChatMessagesAggregation(chatRoom, op, sal_msg);
 	} else if (!linphone_core_conference_server_enabled(cCore)) {
 		const char *session_mode = sal_custom_header_find(op->getRecvCustomHeaders(), "Session-mode");
@@ -937,6 +961,16 @@ LinphoneReason Core::onSipMessageReceived(SalOp *op, const SalMessage *sal_msg)
 			lError() << "Message is received in the context of a client chatroom for which we have no context.";
 			reason = LinphoneReasonNotAcceptable;
 		} else {
+			auto localAccount =
+			    guessLocalAccountFromMalformedMessage(conferenceId.getLocalAddress(), conferenceId.getPeerAddress());
+			if (localAccount) {
+				// We have a match for the from domain and the to username.
+				// We may face an IPBPX that sets the To domain to our IP address, which is
+				// a terribly stupid idea.
+				lWarning() << "Applying workaround to have this chat room assigned to a known account.";
+				conferenceId.setLocalAddress(localAccount->getAccountParams()->getIdentityAddress(), true);
+			}
+
 			chatRoom = getOrCreateBasicChatRoom(conferenceId);
 			if (chatRoom) {
 				reason = handleChatMessagesAggregation(chatRoom, op, sal_msg);
@@ -1030,4 +1064,30 @@ void Core::decrementRemainingDownloadFileCount() {
 	}
 }
 
+std::shared_ptr<Account> Core::guessLocalAccountFromMalformedMessage(const std::shared_ptr<Address> &localAddress,
+                                                                     const std::shared_ptr<Address> &peerAddress) {
+	if (!localAddress) return nullptr;
+
+	auto account = findAccountByIdentityAddress(localAddress);
+	if (!account) {
+		string toUser = localAddress->getUsername();
+		if (!toUser.empty() && peerAddress) {
+			auto localAddressWithPeerDomain = make_shared<Address>(*localAddress);
+			localAddressWithPeerDomain->setDomain(peerAddress->getDomain());
+			account = lookupKnownAccount(localAddressWithPeerDomain, false);
+			if (account) {
+				// We have a match for the from domain and the to username.
+				// We may face an IPBPX that sets the To domain to our IP address, which is
+				// a terribly stupid idea.
+				lWarning() << "Detecting TO header probably ill-choosen.";
+				return account;
+			} else {
+				lWarning() << "Failed to find an account matching TO header";
+			}
+		}
+	}
+
+	return nullptr;
+}
+
 LINPHONE_END_NAMESPACE
diff --git a/src/core/core.cpp b/src/core/core.cpp
index cc7ac2dac21f0071e4be9a47951de28f3f34fb97..ebc6665e2c365cfe9f2618bc8ecb13e0599edc0a 100644
--- a/src/core/core.cpp
+++ b/src/core/core.cpp
@@ -2867,7 +2867,7 @@ std::shared_ptr<Account> Core::findAccountByIdentityAddress(const std::shared_pt
 	for (const auto &account : accounts) {
 		const auto &params = account->getAccountParams();
 		const auto &address = params->getIdentityAddress();
-		if (identity->weakEqual(*address)) {
+		if (address && identity->weakEqual(address)) {
 			found = account;
 			break;
 		}
diff --git a/src/core/core.h b/src/core/core.h
index 4792c874402105b582bd3abab3a3e8068aa7f930..406d879bc848ef5d774a14bbdf3572e8d9d5bbd9 100644
--- a/src/core/core.h
+++ b/src/core/core.h
@@ -474,6 +474,9 @@ private:
 	const ConferenceId prepareConfereceIdForSearch(const ConferenceId &conferenceId) const;
 	void clearProxyConfigList() const;
 
+	std::shared_ptr<Account> guessLocalAccountFromMalformedMessage(const std::shared_ptr<Address> &localAddress,
+	                                                               const std::shared_ptr<Address> &peerAddress);
+
 	std::list<std::string> plugins;
 #if defined(_WIN32) && !defined(_WIN32_WCE)
 	std::list<HINSTANCE> loadedPlugins;
diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp
index f978e0d5c59a0100e037858d851c3373db210138..0aeef0574a9c55b5538ed500ff76e34059991283 100644
--- a/src/db/main-db.cpp
+++ b/src/db/main-db.cpp
@@ -6541,12 +6541,14 @@ void MainDb::updateChatRoomConferenceId(const ConferenceId oldConferenceId, cons
 		L_D();
 
 		const long long &peerSipAddressId = d->insertSipAddress(newConferenceId.getPeerAddress());
+		const long long &localSipAddressId = d->insertSipAddress(newConferenceId.getLocalAddress());
 		const long long &dbChatRoomId = d->selectChatRoomId(oldConferenceId);
 
 		*d->dbSession.getBackendSession() << "UPDATE chat_room"
-		                                     " SET peer_sip_address_id = :peerSipAddressId"
+		                                     " SET peer_sip_address_id = :peerSipAddressId,"
+		                                     " local_sip_address_id = :localSipAddressId"
 		                                     " WHERE id = :chatRoomId",
-		    soci::use(peerSipAddressId), soci::use(dbChatRoomId);
+		    soci::use(peerSipAddressId), soci::use(localSipAddressId), soci::use(dbChatRoomId);
 
 		tr.commit();
 
diff --git a/tester/message_tester.c b/tester/message_tester.c
index 72cf5dbd832309d78fcce5e270a74fcec2866056..84212a2ca697114ea4840d24a4743bfe7cf8dab2 100644
--- a/tester/message_tester.c
+++ b/tester/message_tester.c
@@ -4445,6 +4445,102 @@ static void baudot_text_message_voice_switch_voice_carryover_europe(void) {
 
 #endif /* HAVE_BAUDOT */
 
+static void crappy_to_header(bool_t existing_chat_room) {
+	const char *template = "MESSAGE sip:%s@192.168.0.24:9597 SIP/2.0\r\n"
+	                       "Via: SIP/2.0/TCP 10.0.0.1;rport;branch=z9hG4bKSg92gr72NvDUp\r\n"
+	                       "Route: <sip:%s@192.168.0.24:9597>;transport=tcp\r\n"
+	                       "Max-Forwards: 70\r\n"
+	                       "From: <sip:marcel@sip.example.org>;tag=yPe~pl-Rg\r\n"
+	                       "To: <sip:%s@192.168.0.24:9597>;transport=tcp\r\n"
+	                       "Call-ID: e1431428-4229-4744-9479-e432618ba7f9\r\n"
+	                       "CSeq: 95887387 MESSAGE\r\n"
+	                       "User-Agent: FreeSWITCH\r\n"
+	                       "Allow: INVITE, ACK, BYE, CANCEL, OPTIONS, MESSAGE, INFO, UPDATE, REGISTER, REFER, NOTIFY, "
+	                       "PUBLISH, SUBSCRIBE\r\n"
+	                       "Supported: path, replaces\r\n"
+	                       "Content-Type: text/plain\r\n"
+	                       "Content-Length: 2\r\n"
+	                       "\r\n"
+	                       "Hi\r\n";
+
+	LinphoneCoreManager *laure = linphone_core_manager_new("laure_rc_udp");
+	const char *laure_username = linphone_address_get_username(laure->identity);
+
+	if (existing_chat_room) {
+		char *localSipUri = bctbx_strdup_printf("sip:%s@192.168.0.24", laure_username);
+		LinphoneChatRoom *existing_cr =
+		    linphone_core_create_basic_chat_room(laure->lc, localSipUri, "sip:marcel@sip.example.org");
+		BC_ASSERT_PTR_NOT_NULL(existing_cr);
+		if (existing_cr) {
+			const LinphoneAddress *local_address = linphone_chat_room_get_local_address(existing_cr);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_username(local_address), laure_username);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(local_address), "192.168.0.24");
+
+			const LinphoneAddress *peer_address = linphone_chat_room_get_peer_address(existing_cr);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_username(peer_address), "marcel");
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(peer_address), "sip.example.org");
+		}
+		bctbx_free(localSipUri);
+	}
+
+	char *message = bctbx_strdup_printf(template, laure_username, laure_username, laure_username);
+	LinphoneTransports *tp = linphone_core_get_transports_used(laure->lc);
+	BC_ASSERT_TRUE(liblinphone_tester_send_data(message, strlen(message), "127.0.0.1",
+	                                            linphone_transports_get_udp_port(tp), SOCK_DGRAM) > 0);
+	linphone_transports_unref(tp);
+	bctbx_free(message);
+
+	BC_ASSERT_TRUE(wait_for(laure->lc, NULL, &laure->stat.number_of_LinphoneMessageReceived, 1));
+	LinphoneChatMessage *received_message = laure->stat.last_received_chat_message;
+	BC_ASSERT_PTR_NOT_NULL(received_message);
+	if (received_message != NULL) {
+		LinphoneChatRoom *chat_room = linphone_chat_message_get_chat_room(received_message);
+		BC_ASSERT_PTR_NOT_NULL(chat_room);
+		if (chat_room) {
+			const LinphoneAddress *local_address = linphone_chat_room_get_local_address(chat_room);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_username(local_address), laure_username);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(local_address), "sip.example.org");
+
+			const LinphoneAddress *peer_address = linphone_chat_room_get_peer_address(chat_room);
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_username(peer_address), "marcel");
+			BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(peer_address), "sip.example.org");
+
+			LinphoneAccount *account = linphone_chat_room_get_account(chat_room);
+			BC_ASSERT_PTR_NOT_NULL(account);
+			if (account) {
+				const LinphoneAddress *identity_address =
+				    linphone_account_params_get_identity_address(linphone_account_get_params(account));
+				BC_ASSERT_STRING_EQUAL(linphone_address_get_username(identity_address), laure_username);
+				BC_ASSERT_STRING_EQUAL(linphone_address_get_domain(identity_address), "sip.example.org");
+
+				const bctbx_list_t *chat_rooms = linphone_account_get_chat_rooms(account);
+				BC_ASSERT_PTR_NOT_NULL(chat_rooms);
+				if (chat_rooms) {
+					BC_ASSERT_EQUAL((int)bctbx_list_size(chat_rooms), 1, int, "%d");
+					LinphoneChatRoom *first_chat_room = (LinphoneChatRoom *)bctbx_list_get_data(chat_rooms);
+					LinphoneChatMessage *last_message = linphone_chat_room_get_last_message_in_history(first_chat_room);
+					BC_ASSERT_PTR_NOT_NULL(last_message);
+					if (last_message) {
+						BC_ASSERT_STRING_EQUAL(linphone_chat_message_get_text_content(last_message),
+						                       linphone_chat_message_get_text_content(received_message));
+						linphone_chat_message_unref(last_message);
+					}
+				}
+			}
+		}
+	}
+
+	linphone_core_manager_destroy(laure);
+}
+
+void text_message_crappy_to_header_existing_chat_room(void) {
+	crappy_to_header(TRUE);
+}
+
+void text_message_crappy_to_header(void) {
+	crappy_to_header(FALSE);
+}
+
 test_t message_tests[] = {
     TEST_NO_TAG("File transfer content", file_transfer_content),
     TEST_NO_TAG("Message with 2 attachments", message_with_two_attachments),
@@ -4479,6 +4575,9 @@ test_t message_tests[] = {
                 text_message_in_call_chat_room_from_denied_text_offer_when_room_exists),
     TEST_NO_TAG("Text message duplication", text_message_duplication),
     TEST_NO_TAG("Text message auto resent after failure", text_message_auto_resent_after_failure),
+    TEST_NO_TAG("Text message with crappy TO header", text_message_crappy_to_header),
+    TEST_NO_TAG("Text message with crappy TO header from existing chat room",
+                text_message_crappy_to_header_existing_chat_room),
     TEST_NO_TAG("Transfer message", transfer_message),
     TEST_NO_TAG("Transfer message 2", transfer_message_2),
     TEST_NO_TAG("Transfer message 3", transfer_message_3),