diff --git a/include/linphone/api/c-content.h b/include/linphone/api/c-content.h
index f75e0b3279a74910036ba0aaf99db310cfe5a40b..63b6c4818c0ee7b31b2953eb97c8d31426e7ca17 100644
--- a/include/linphone/api/c-content.h
+++ b/include/linphone/api/c-content.h
@@ -330,16 +330,25 @@ LINPHONE_PUBLIC bool_t linphone_content_is_file_transfer(const LinphoneContent *
 
 /**
  * Tells whether or not this content contains an encrypted file
+ * @param content #LinphoneContent object. @notnil
  * @return True is this content contains a file and this file is encrypted, false otherwise.
  */
 LINPHONE_PUBLIC bool_t linphone_content_is_file_encrypted(const LinphoneContent *content);
 
 /**
  * Returns the creation timestamp if this content is a FileContent (received or sent by chat).
+ * @param content #LinphoneContent object. @notnil
  * @return The timestamp at which this content was created if available, -1 otherwise.
  */
 LINPHONE_PUBLIC time_t linphone_content_get_creation_timestamp(const LinphoneContent *content);
 
+/**
+ * Returns the chat message id for which this content is related to, if any.
+ * @param content #LinphoneContent object. @notnil
+ * @return The chat message ID if this content is related to a chat message, NULL otherwise. @maybenil
+ */
+LINPHONE_PUBLIC const char *linphone_content_get_related_chat_message_id(const LinphoneContent *content);
+
 /************ */
 /* DEPRECATED */
 /* ********** */
diff --git a/src/c-wrapper/api/c-content.cpp b/src/c-wrapper/api/c-content.cpp
index c156fee8cbf11ede35634ff0aeb307efbb0eb7bd..602f62f69e474f918457976bb710f53dbfaf6072 100644
--- a/src/c-wrapper/api/c-content.cpp
+++ b/src/c-wrapper/api/c-content.cpp
@@ -380,6 +380,11 @@ time_t linphone_content_get_creation_timestamp(const LinphoneContent *content) {
 	return -1;
 }
 
+const char *linphone_content_get_related_chat_message_id(const LinphoneContent *content) {
+	const auto c = Content::toCpp(content);
+	return L_STRING_TO_C(c->getRelatedChatMessageId());
+}
+
 // =============================================================================
 // Private functions.
 // =============================================================================
diff --git a/src/chat/chat-message/chat-message.cpp b/src/chat/chat-message/chat-message.cpp
index 00160523f6b547ab5b44c45e620505d4f74c801a..7152e1a4d09e1971f6f215e4aa686b3a0dd659c5 100644
--- a/src/chat/chat-message/chat-message.cpp
+++ b/src/chat/chat-message/chat-message.cpp
@@ -1198,6 +1198,8 @@ void ChatMessagePrivate::handleAutoDownload() {
 	}
 
 	for (auto &c : contents) {
+		c->setRelatedChatMessageId(imdnId);
+
 		ContentType contentType = c->getContentType();
 		if (contentType.strongEqual(ContentType::Icalendar)) {
 			LinphoneConferenceInfo *cConfInfo =
@@ -1250,7 +1252,9 @@ void ChatMessagePrivate::restoreFileTransferContentAsFileContent() {
 		if (content && content->isFileTransfer()) {
 			auto fileTransferContent = static_pointer_cast<FileTransferContent>(content);
 			auto fileContent = fileTransferContent->getFileContent();
+
 			if (fileContent) {
+				fileContent->setRelatedChatMessageId(imdnId);
 				it = contents.erase(it);
 				it = contents.insert(it, fileContent);
 			} else {
@@ -1712,6 +1716,10 @@ const string &ChatMessage::getImdnMessageId() const {
 
 void ChatMessagePrivate::setImdnMessageId(const string &id) {
 	imdnId = id;
+
+	for (auto &content : contents) {
+		content->setRelatedChatMessageId(id);
+	}
 }
 
 const string &ChatMessagePrivate::getCallId() const {
diff --git a/src/chat/modifier/file-transfer-chat-message-modifier.cpp b/src/chat/modifier/file-transfer-chat-message-modifier.cpp
index 258f53185787171ffc8000a40c3a4ba6efa0da8f..fb735584c5b7c00e465747616cedca002deb7a6f 100644
--- a/src/chat/modifier/file-transfer-chat-message-modifier.cpp
+++ b/src/chat/modifier/file-transfer-chat-message-modifier.cpp
@@ -620,6 +620,7 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode(const shared
 		fileTransferContent->setBody(internalContent.getBody());
 		string xml_body = fileTransferContent->getBodyAsUtf8String();
 		parseFileTransferXmlIntoContent(xml_body.c_str(), fileTransferContent);
+		fileTransferContent->setRelatedChatMessageId(message->getImdnMessageId());
 		message->addContent(fileTransferContent);
 		return ChatMessageModifier::Result::Done;
 	}
@@ -629,6 +630,7 @@ ChatMessageModifier::Result FileTransferChatMessageModifier::decode(const shared
 			auto fileTransferContent = static_pointer_cast<FileTransferContent>(content);
 			string xml_body = fileTransferContent->getBodyAsUtf8String();
 			parseFileTransferXmlIntoContent(xml_body.c_str(), fileTransferContent);
+			fileTransferContent->setRelatedChatMessageId(message->getImdnMessageId());
 		}
 	}
 	return ChatMessageModifier::Result::Done;
@@ -881,6 +883,7 @@ void FileTransferChatMessageModifier::processResponseHeadersFromGetFile(const be
 		} else {
 			lWarning() << "No file transfer information for message [" << message << "]: creating...";
 			auto content = createFileTransferInformationFromHeaders(response);
+			content->setRelatedChatMessageId(message->getImdnMessageId());
 			message->addContent(content);
 		}
 
@@ -993,6 +996,7 @@ static void createFileContentFromFileTransferContent(std::shared_ptr<FileTransfe
 	fileContent->setFilePath(fileTransferContent->getFilePath());
 	fileContent->setContentType(fileTransferContent->getFileContentType());
 	fileContent->setFileDuration(fileTransferContent->getFileDuration());
+	fileContent->setRelatedChatMessageId(fileTransferContent->getRelatedChatMessageId());
 
 	// Link the FileContent to the FileTransferContent
 	fileTransferContent->setFileContent(fileContent);
diff --git a/src/chat/modifier/multipart-chat-message-modifier.cpp b/src/chat/modifier/multipart-chat-message-modifier.cpp
index 2536c34cd3287da0649ab8a87bd584bb4b109b3f..863a327750a7e3dc27a9c8a06704352d6b34b08e 100644
--- a/src/chat/modifier/multipart-chat-message-modifier.cpp
+++ b/src/chat/modifier/multipart-chat-message-modifier.cpp
@@ -64,6 +64,7 @@ ChatMessageModifier::Result MultipartChatMessageModifier::decode(const shared_pt
 			} else {
 				content = Content::create(c);
 			}
+			content->setRelatedChatMessageId(message->getImdnMessageId());
 			message->addContent(content);
 		}
 		return ChatMessageModifier::Result::Done;
diff --git a/src/content/content.cpp b/src/content/content.cpp
index 3a3e3830be8877299239871cab9b3c16baa9ef9f..99b0c302696c66624ae651c8178abfacb5ab8d20 100644
--- a/src/content/content.cpp
+++ b/src/content/content.cpp
@@ -281,6 +281,14 @@ void Content::setFilePath(const std::string &path) {
 	mCache.filePath = path;
 }
 
+void Content::setRelatedChatMessageId(const string &messageId) {
+	mMessageId = messageId;
+}
+
+const string &Content::getRelatedChatMessageId() const {
+	return mMessageId;
+}
+
 void Content::addHeader(const string &headerName, const string &headerValue) {
 	removeHeader(headerName);
 	Header header = Header(headerName, headerValue);
diff --git a/src/content/content.h b/src/content/content.h
index c31085053dead9325448693dad64222e332f6ba0..fb508573909fe40417fed7e0d47bc3ca9cfa912a 100644
--- a/src/content/content.h
+++ b/src/content/content.h
@@ -110,6 +110,9 @@ public:
 	std::list<Header>::const_iterator findHeader(const std::string &headerName) const;
 	const std::string &getCustomHeader(const std::string &headerName) const;
 
+	void setRelatedChatMessageId(const std::string &messageId);
+	const std::string &getRelatedChatMessageId() const;
+
 	void setUserData(const Variant &userData);
 	Variant getUserData() const;
 
@@ -142,6 +145,7 @@ private:
 	void *mCryptoContext = nullptr; // Used to encrypt file for RCS file transfer.
 	bool mIsDirty = false;
 	SalBodyHandler *mBodyHandler = nullptr;
+	std::string mMessageId;
 
 	struct Cache {
 		std::string name;
diff --git a/src/db/main-db.cpp b/src/db/main-db.cpp
index b83614ad2f411d422c6137f82e79710a0832137c..09a3772534d65907f25bf50aeed23fcb79ad9572 100644
--- a/src/db/main-db.cpp
+++ b/src/db/main-db.cpp
@@ -5026,7 +5026,8 @@ list<shared_ptr<Content>> MainDb::getMediaContents(const ConferenceId &conferenc
 	list<shared_ptr<Content>> result = list<shared_ptr<Content>>();
 #ifdef HAVE_DB_STORAGE
 	static const string query =
-	    "SELECT name, path, size, content_type.value, conference_chat_message_event.time "
+	    "SELECT name, path, size, content_type.value, conference_chat_message_event.time, "
+	    "conference_chat_message_event.imdn_message_id "
 	    " FROM chat_message_file_content "
 	    " JOIN chat_message_content ON chat_message_content.id = chat_message_file_content.chat_message_content_id "
 	    " JOIN content_type ON content_type.id = chat_message_content.content_type_id "
@@ -5047,6 +5048,8 @@ list<shared_ptr<Content>> MainDb::getMediaContents(const ConferenceId &conferenc
 			int size = row.get<int>(2);
 			ContentType contentType(row.get<string>(3));
 			time_t creation = d->dbSession.getTime(row, 4);
+			string messageId = row.get<string>(5);
+			lDebug() << "Fetched media content [" << name << "] message id is [" << messageId << "]";
 
 			auto fileContent = FileContent::create<FileContent>();
 			fileContent->setFileName(name);
@@ -5054,6 +5057,7 @@ list<shared_ptr<Content>> MainDb::getMediaContents(const ConferenceId &conferenc
 			fileContent->setFilePath(path);
 			fileContent->setContentType(contentType);
 			fileContent->setCreationTimestamp(creation);
+			fileContent->setRelatedChatMessageId(messageId);
 
 			result.push_back(fileContent);
 		}
@@ -5068,7 +5072,8 @@ list<shared_ptr<Content>> MainDb::getDocumentContents(const ConferenceId &confer
 	list<shared_ptr<Content>> result = list<shared_ptr<Content>>();
 #ifdef HAVE_DB_STORAGE
 	static const string query =
-	    "SELECT name, path, size, content_type.value, conference_chat_message_event.time "
+	    "SELECT name, path, size, content_type.value, conference_chat_message_event.time, "
+	    "conference_chat_message_event.imdn_message_id "
 	    " FROM chat_message_file_content "
 	    " JOIN chat_message_content ON chat_message_content.id = chat_message_file_content.chat_message_content_id "
 	    " JOIN content_type ON content_type.id = chat_message_content.content_type_id "
@@ -5088,6 +5093,8 @@ list<shared_ptr<Content>> MainDb::getDocumentContents(const ConferenceId &confer
 			int size = row.get<int>(2);
 			ContentType contentType(row.get<string>(3));
 			time_t creation = d->dbSession.getTime(row, 4);
+			string messageId = row.get<string>(5);
+			lDebug() << "Fetched document content [" << name << "] message id is [" << messageId << "]";
 
 			auto fileContent = FileContent::create<FileContent>();
 			fileContent->setFileName(name);
@@ -5095,6 +5102,7 @@ list<shared_ptr<Content>> MainDb::getDocumentContents(const ConferenceId &confer
 			fileContent->setFilePath(path);
 			fileContent->setContentType(contentType);
 			fileContent->setCreationTimestamp(creation);
+			fileContent->setRelatedChatMessageId(messageId);
 
 			result.push_back(fileContent);
 		}
@@ -5871,6 +5879,8 @@ void MainDb::loadChatMessageContents(const shared_ptr<ChatMessage> &chatMessage)
 			if (bodyEncodingType == 1) content->setBodyFromUtf8(row.get<string>(3));
 			else content->setBodyFromLocale(row.get<string>(3));
 
+			content->setRelatedChatMessageId(chatMessage->getImdnMessageId());
+
 			// 1.2 - Fetch contents' app data.
 			// TODO: Do not test backend, encapsulate!!!
 			if (getBackend() == MainDb::Backend::Sqlite3) {
diff --git a/tester/group_chat_tester.c b/tester/group_chat_tester.c
index 96818e65b85ee0f309196ff228c2f0f9e68f320d..25e4e5bf01fc519db2d6d3791f4d921551a8ca9d 100644
--- a/tester/group_chat_tester.c
+++ b/tester/group_chat_tester.c
@@ -61,7 +61,9 @@ static bool_t wait_for_chat_room_participants(bctbx_list_t *lcs, LinphoneChatRoo
 			linphone_core_iterate((LinphoneCore *)(iterator->data));
 		}
 #ifdef LINPHONE_WINDOWS_UWP
-		{ bc_tester_process_events(); }
+		{
+			bc_tester_process_events();
+		}
 #elif defined(LINPHONE_WINDOWS_DESKTOP)
 		{
 			MSG msg;
@@ -457,6 +459,7 @@ void _send_file_plus_text(
 
 	msg = linphone_chat_room_create_empty_message(cr);
 	linphone_chat_message_add_file_content(msg, content);
+	BC_ASSERT_PTR_NULL(linphone_content_get_related_chat_message_id(content));
 	linphone_content_unref(content);
 
 	if (text) linphone_chat_message_add_utf8_text_content(msg, text);
@@ -473,6 +476,7 @@ void _send_file_plus_text(
 			linphone_content_set_file_path(content2, sendFilepath2);
 		}
 		linphone_chat_message_add_file_content(msg, content2);
+		BC_ASSERT_PTR_NULL(linphone_content_get_related_chat_message_id(content2));
 		linphone_content_unref(content2);
 	}
 
@@ -532,6 +536,10 @@ void _receive_file_plus_text(bctbx_list_t *coresList,
 		if (!use_buffer) {
 			linphone_content_set_file_path(fileTransferContent, downloaded_file);
 		}
+
+		BC_ASSERT_STRING_EQUAL(linphone_content_get_related_chat_message_id(fileTransferContent),
+		                       linphone_chat_message_get_message_id(msg));
+
 		linphone_chat_message_download_content(msg, fileTransferContent);
 		BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int,
 		                "%d");
@@ -566,6 +574,8 @@ void _receive_file_plus_text(bctbx_list_t *coresList,
 			if (!use_buffer) {
 				linphone_content_set_file_path(fileTransferContent2, downloaded_file);
 			}
+			BC_ASSERT_STRING_EQUAL(linphone_content_get_related_chat_message_id(fileTransferContent2),
+			                       linphone_chat_message_get_message_id(msg));
 			linphone_chat_message_download_content(msg, fileTransferContent2);
 			BC_ASSERT_EQUAL(linphone_chat_message_get_state(msg), LinphoneChatMessageStateFileTransferInProgress, int,
 			                "%d");
@@ -4309,11 +4319,15 @@ static void group_chat_room_send_multipart_custom_content_types(void) {
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content1), "application");
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content1), "vnd.3gpp.mcptt-info+xml");
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_utf8_text(content1), data1);
+		BC_ASSERT_STRING_EQUAL(linphone_content_get_related_chat_message_id(content1),
+		                       linphone_chat_message_get_message_id(pauline->stat.last_received_chat_message));
 
 		LinphoneContent *content2 = bctbx_list_nth_data(contents, 1);
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_type(content2), "application");
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_subtype(content2), "vnd.3gpp.mcptt-location-info+xml");
 		BC_ASSERT_STRING_EQUAL(linphone_content_get_utf8_text(content2), data2);
+		BC_ASSERT_STRING_EQUAL(linphone_content_get_related_chat_message_id(content2),
+		                       linphone_chat_message_get_message_id(pauline->stat.last_received_chat_message));
 	}
 
 	// Clean db from chat room
diff --git a/tester/message_tester.c b/tester/message_tester.c
index ef155b9700a8385b6684e9a3a21391ee131373bc..72cf5dbd832309d78fcce5e270a74fcec2866056 100644
--- a/tester/message_tester.c
+++ b/tester/message_tester.c
@@ -1416,6 +1416,7 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 	BC_ASSERT_PTR_NOT_NULL(content);
 	file_transfer_size = (int)linphone_content_get_file_size(content);
 	BC_ASSERT_NOT_EQUAL(0, file_transfer_size, int, "%d");
+	BC_ASSERT_PTR_NULL(linphone_content_get_related_chat_message_id(content));
 
 	if (two_files) {
 		FILE *file_to_send = NULL;
@@ -1433,6 +1434,7 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 		linphone_content_set_size(content, file_size); /*total size to be transferred*/
 		linphone_content_set_name(content, "ahbahouaismaisbon.wav");
 		linphone_content_set_user_data(content, file_to_send);
+		BC_ASSERT_PTR_NULL(linphone_content_get_related_chat_message_id(content));
 
 		linphone_chat_message_add_file_content(msg, content);
 		BC_ASSERT_PTR_NOT_NULL(linphone_content_get_user_data(content));
@@ -1641,6 +1643,8 @@ void transfer_message_base4(LinphoneCoreManager *marie,
 				BC_ASSERT_STRING_EQUAL(linphone_content_get_name(content), expected_filename);
 				compare_files(send_filepath, linphone_content_get_file_path(content));
 				BC_ASSERT_STRING_NOT_EQUAL(linphone_content_get_subtype(content), "vnd.gsma.rcs-ft-http+xml");
+				BC_ASSERT_STRING_EQUAL(linphone_content_get_related_chat_message_id(content),
+				                       linphone_chat_message_get_message_id(msg));
 
 				if (linphone_factory_is_imdn_available(linphone_factory_get())) {
 					BC_ASSERT_FALSE(wait_for_until(pauline->lc, marie->lc,