Send Message
This document explains how to send messages from the client SDK, applicable to one-to-one chat, group chat, and chatroom scenarios.
The client SDK has a message frequency limit - a maximum of 5 messages can be sent per second.
Sending Messages
sendMessage is the fundamental interface in IMLib for message transmission, supporting both built-in and custom message types. For specific message types, IMLib also provides multiple convenient syntactic sugar methods.
Interface
RongIMLib.sendMessage(conversation, message, options)
Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| conversation | IConversationOption | Yes | Target conversation |
| message | BaseMessage | Yes | Message instance to be sent. Must be a subclass of BaseMessage, either IMLib built-in messages (e.g., RongIMLib.TextMessage) or custom message instances registered via RongIMLib.registerMessageType() |
| options | ISendMessageOptions | No | Sending configuration options. Defines optional behaviors during message sending, such as expandability and push notifications |
Example
The following example demonstrates how to use sendMessage to send a text message mentioning "Zhang San" in a group chat.
1. Define Target Conversation and Message Content
Since this is a group @ message, mentionedInfo needs to be added.
// Define target conversation - here we define a group conversation
const conversation = { conversationType: RongIMLib.ConversationType.GROUP, targetId: '<Target ID>' }
// Instantiate the message to be sent - RongIMLib.TextMessage is a built-in text message type
const message = new RongIMLib.TextMessage({
// Text content
content: 'Text content',
// (Optional) Additional information attached to the message, transparently transmitted to the recipient
extra: 'Additional message information',
// For group messages requiring @ mentions, add the mentionedInfo field
mentionedInfo: {
// @ type: ALL or INDIVIDUAL
type: RongIMLib.MentionedType.SINGAL,
// List of @ users
userIdList: ['zhangsan'],
// @ content
mentionedContent: ''
}
})
2. Configure Sending Options
Construct ISendMessageOptions to define sending behavior. For group @ messages, set isMentioned to true.
// Configuration properties
const options = {
// Set isMentioned to true for @ messages
isMentioned: true,
// Pre-send callback - the returned message can be used for list rendering
onSendBefore: (message) => {
console.log('Pre-send callback', message)
}
}
3. Call the Send Method
Call sendMessage and update message status based on the returned messageId.
// Send message
RongIMLib.sendMessage(conversation, message, options).then(res => {
if (res.code === RongIMLib.ErrorCode.SUCCESS) {
// On success, update the message status to "sent" using the returned messageId
console.log('Message sent successfully', res.data)
} else {
console.log('Message sending failed', res.code, res.msg)
}
})
4. Handle Failed Messages
If sending fails, mark the message status as failed using the returned messageId and provide a resend option.
-
If the message doesn't reach RC servers or the server returns failure, recipients won't receive it.
-
In poor network conditions, messages might reach recipients successfully while the sender times out waiting for acknowledgment. Resending in such cases may cause duplicate messages. See FAQ for details.
5. Resending Messages
When resending, maintain identical message content to the original.
Since SDK 5.5.1, you can specify the original message's messageId in options for deduplication. RC servers don't deduplicate - applications should use this ID to identify duplicates. Get messageId from the onSendBefore callback's message object or sending results.
// Define target conversation - here a group conversation
const conversation = { conversationType: RongIMLib.ConversationType.GROUP, targetId: '<Target ID>' }
// Instantiate message - RongIMLib.TextMessage is a built-in text type
const message = new RongIMLib.TextMessage({ content: 'Text content' })
// Configuration
const options = {
// Original message's messageId - obtain from onSendBefore callback or results
messageId: 0
}
RongIMLib.sendMessage(conversation, message, options).then(res => {
if (res.code === RongIMLib.ErrorCode.SUCCESS) {
// On success, update status using messageId
console.log('Message sent successfully', res.data)
} else {
// On failure, update status using messageId
console.log('Message sending failed', res.code, res.msg)
}
})
sendMessage Interface Details
sendMessage accepts three parameters: conversation, message, and options.
-
conversation defines the target conversation. See IConversationOption.
Parameter Type Description conversationType ConversationType Conversation type targetId string Recipient ID -
message contains the content to send, supporting either IMLib built-in messages (e.g., RongIMLib.TextMessage) or custom messages registered via RongIMLib.registerMessageType().
-
options defines optional sending behaviors like expandability and push. See ISendMessageOptions
Parameter Type Description isStatusMessageboolean (Deprecated) Whether status message (optional) disableNotification boolean Whether to send silent messages (optional) pushContent string Push content (optional) pushData string Push notification additional data (optional) isMentioned boolean Whether @ message. Only valid for group/ultra group conversations (optional) mentionedType1|2(Deprecated) @ type: 1: @all 2: @specific users (optional) mentionedUserIdListstring[] (Deprecated) List of @ user IDs (optional) directionalUserIdList string[] For targeted messages, only valid for group/ultra group conversations. Note: SDK versions <5.9.4 only support groups for targeted messages. (optional) isVoipPush boolean When recipient is iOS device and offline, they'll receive Voip Push. Doesn't affect Android. (optional) canIncludeExpansion boolean Whether message can be expanded expansion [key: string]: string Message expansion data (optional) isFilerWhiteBlacklist boolean Blocklist/allowlist (optional) pushConfig IPushConfig Mobile push configuration (optional) (similar to Android/iOS MessagePushConfig) onSendBefore Function Pre-send callback (≥5.4.0) messageId number When resending, specify original message's messageId. All parameters must match original message (≥5.5.1) disableUpdateLastMessage boolean Disable updating conversation's last message, default false (≥5.12.2) needReceipt boolean Whether read receipt is required, default false (≥5.20.0) IPushConfigParameter Details
| Parameter | Type | Description |
|---|---|---|
| pushTitle | string | Push notification title. If not set: for one-to-one chats, the sender's name is displayed; for group chats, the group name is displayed; for custom messages, no title is displayed by default |
| pushContent | string | Push notification content |
| pushData | string | Additional information for remote push notifications |
| iOSConfig | IiOSPushConfig | (Optional) |
| androidConfig | IAndroidPushConfig | (Optional) |
| disablePushTitle | boolean | Whether to hide the push title. Only effective for iOS platform |
| forceShowDetailContent | boolean | Whether to force push |
| templateId | string | Push notification template ID |
| harmonyOSConfig | IHarmonyOSPushConfig | (Optional) |
Built-in Message Types
IMLib provides predefined message types including text, voice, image, GIF, file, etc.
Text Message
ITextMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Text content |
Code Example
new RongIMLib.TextMessage({ content: '' })
Image Message
IImageMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| content | string | Yes | Image thumbnail as Base64 string. Generate the thumbnail yourself (recommended longest side ≤ 240px), encode as Base64 and put into content. Base64 string length should be around 5k, max 10k. Note: some tools add Data URI prefix when converting images to Base64, e.g. data:image/jpeg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD. Remove the Data URI prefix, keeping only the data part, e.g. /9j/4AAQSkZJRgABAgAAZABkAAD. |
| imageUri | string | Yes | Remote access URL of the image |
| thumWidth | number | No | Thumbnail width (supported since v5.18.0) |
| thumHeight | number | No | Thumbnail height (supported since v5.18.0) |
Code Example
new RongIMLib.ImageMessage({
content: '', // Image thumbnail as Base64 string, max 80KB
imageUri: '' // Remote access URL of the image
})
File Message
IFileMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | File name |
| size | number | Yes | File size in bytes |
| type | string | Yes | File type |
| fileUrl | string | Yes | Remote download URL of the file |
Code Example
new RongIMLib.FileMessage({
name: '',
size: 1000,
type: '',
fileUrl: ''
})
HQ Voice Message
IHQVoiceMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| remoteUrl | string | Yes | Remote media resource URL |
| duration | number | Yes | Voice duration in seconds. Must be ≤60s |
| type | string | No | Encoding type, default aac. If using Android/iOS IMKit SDK, use default aac format as IMKit only supports aac for recording/playback. If your app handles audio separately, other formats can be used. |
Code Example
new RongIMLib.HQVoiceMessage({
remoteUrl: '<aac file URL>',
duration: 60,
})
Short Video Message
ISightMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| sightUrl | string | Yes | Remote video resource URL. If using Android/iOS IMKit SDK, must use H.264 + AAC encoded files as IMKit only supports this combination for recording/playback. |
| content | string | Yes | Base64 string of the first frame thumbnail. Generate thumbnail (recommended longest side ≤240px), encode as Base64. Length should be around 5k, max 10k. Remove any Data URI prefix from the Base64 string. |
| duration | number | Yes | Video duration. Default server limit is 2 minutes. Contact sales to adjust. |
| size | number | Yes | Video size in bytes |
| name | number | Yes | Video name |
Code Example
new RongIMLib.SightMessage({
sightUrl: "<Remote video URL>",
content: "<Thumbnail base64>"
duration: 10,
size: 100,
name: "Video name"
})
GIF Message
IGIFMessageContent Parameter Details
| Key | Type | Required | Description |
|---|---|---|---|
| gifDataSize | number | Yes | GIF file size in bytes |
| remoteUrl | string | Yes | Remote storage URL of the GIF |
| width | number | Yes | Image width |
| height | number | Yes | Image height |
Code Example
new RongIMLib.GIFMessage({
gifDataSize: 30,
remoteUrl: '<Image URL>',
width: 300,
height: 200
})
Reference Message
IReferenceMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| referMsgUserId | string | Yes | User ID of the referenced message sender |
| referMsg | any | Yes | Reference message object |
| content | string | Yes | Input text message content |
| objName | string | Yes | Type of the referenced message |
Code Example
new RongIMLib.ReferenceMessage({
referMsgUserId: '<Referenced user ID>',
referMsg: {
content: 'Referenced message text'
},
referMsgUid: 'Referenced message UId',
content: 'Message content to send',
objName: RongIMLib.MessageType.TEXT
})
Location Message
ILocationMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| longitude | number | Yes | Longitude |
| latitude | number | Yes | Latitude |
| poi | string | Yes | Location information |
| content | string | Yes | Location thumbnail as Base64 string without prefix |
Code Example
new RongIMLib.LocationMessage({
latitude: '<Latitude>',
longitude: '<Longitude>',
poi: 'Location info',
content: '<base64>'
})
Rich Content Message
IRichContentMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| title | string | Yes | Title |
| content | string | Yes | Summary content |
| imageUri | string | Yes | Display image URL |
| url | string | Yes | Article link URL |
Code Example
new RongIMLib.RichContentMessage({
title: 'Title',
content: 'Content summary',
imageUri: '<Image URL>',
url: '<Article URL>'
})
Information Notification Message
Supported since v5.8.1
IInformationNotificationMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| message | string | Yes | Notification bar message content |
| extra | string | No | Additional information for the notification bar |
Code Example
new RongIMLib.InformationNotificationMessage({
message: 'Notification bar message content',
extra: 'Additional information for the notification bar',
})
Command Message
Supported since v5.8.1
ICommandMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| name | string | Yes | Command name |
| data | string | Yes | Command content |
Code Example
new RongIMLib.CommandMessage({
name: 'Command name',
data: 'Command content',
})
Group Notification Message
Supported since v5.8.1
IGroupNotificationMessageContent Parameter Details
| Parameter | Type | Required | Description |
|---|---|---|---|
| operatorUserId | string | Yes | Operator's user ID |
| operation | string | Yes | Operation name for group notifications |
| data | string | Yes | Operation data |
| message | string | Yes | Message content |
| extra | string | No | Extended information |
Code Example:
new RongIMLib.GroupNotificationMessage({
operatorUserId: 'Operator user ID',
operation: 'Group notification operation name',
data: 'Operation data',
message: 'Message content'
})
Emoji Message
For web clients, simply send Emoji messages using the text message type (TextMessage).
- RC provides an Emoji plugin with 128 built-in Emoji images. These can be used for the emoji picker in the message input box or extended with custom configurations.
- When sending messages, you must send the native Emoji characters directly. For example: 😀. Conversion method:
symbolToEmoji. - When receiving messages in the Web SDK, Emojis are received in Unicode format (e.g.,
ef600). They must be converted to display as native Emojis correctly.
Code Example:
// Define target conversation
const conversation = { conversationType: RongIMLib.ConversationType.PRIVATE, targetId: '<Target ID>' }
// Instantiate message to send - RongIMLib.TextMessage is the built-in text message type
const message = new RongIMLib.TextMessage({ content: '😀' })
// Send
RongIMLib.sendMessage(conversation, message).then(res => {})
Emoji Plugin
-
Plugin Compatibility
Chrome Firefox Safari IE Edge iPhone Android 30+ 30+ 10+ 7+ ✔️ iOS 8.0+ Safari and WeChat browser Chrome and WeChat browser on Android 4.4+ -
Importing the Emoji Plugin
<!-- Non-minified version -->
<script src="https://cdn.ronghub.com/RongEmoji-2.2.11.js"></script>
<!-- Minified version -->
<script src="https://cdn.ronghub.com/RongEmoji-2.2.11.min.js"></script>tipEmoji code example: https://rongcloud.github.io/web-emoji-demo/src/index.html
- When importing the SDK via
import * as RongIMLib from '@rongcloud/imlib-next', the Emoji plugin must be called with thewindowprefix (e.g.,window.RongIMLib.RongIMEmoji.init()). - The RongEmoji plugin only supports CDN import and is not available via npm.
-
Emoji Initialization (Default Parameters)
RongIMLib.RongIMEmoji.init(); -
Emoji Initialization (Custom Configuration)
configparameter details:Parameter Type Required Description Minimum Version size Number No Emoji size (default: 24, recommended: 18-58) 2.2.6 url String No Emoji sprite image URL 2.2.6 lang String No Emoji name language (default: zh) 2.2.6 extension Object No Custom emoji extensions 2.2.6 // Emoji reference: http://unicode.org/emoji/charts/full-emoji-list.html
var config = {
size: 25,
url: '//f2e.cn.ronghub.com/sdk/emoji-48.png',
lang: 'en',
extension: {
dataSource: {
u1F914: { // Custom emoji for u1F914
en: 'thinking face', // English name
zh: '思考', // Chinese name
tag: '🤔', // Native Emoji
position: '0 0' // Position coordinates in sprite
}
},
url: '//cdn.ronghub.com/thinking-face.png' // Custom emoji sprite URL
}
};
RongIMLib.RongIMEmoji.init(config); -
Get Emoji List
var list = RongIMLib.RongIMEmoji.list;
/*list => [{
unicode: 'u1F600',
emoji: '😀',
node: span,
symbol: '[笑嘻嘻]'
}]
*/ -
Emoji to Text
Displays emoji names when native emoji rendering is unsupported (useful for message input).
var message = '😀😁Test Emoji';
// Convert native emojis in message to their names
RongIMLib.RongIMEmoji.emojiToSymbol(message);
// => '[笑嘻嘻][露齿而笑]Test Emoji' -
Text to Emoji
When sending messages, the message body must use native emoji characters.
var message = '[笑嘻嘻][露齿而笑]Test Emoji';
// Convert emoji names in message to native emojis
RongIMLib.RongIMEmoji.symbolToEmoji(message);
// => '😀😁Test Emoji' -
Emoji to HTML
After receiving messages in the Web SDK, native emoji characters are decoded into Unicode codes and require conversion for proper display.
var message = '\uf600Test Emoji';
// Convert native emojis (including Unicode) in message to HTML
RongIMLib.RongIMEmoji.emojiToHTML(message);
// => "<span class='rong-emoji-content' name='[笑嘻嘻]'>😀</span>Test Emoji" -
Text to HTML
var message = '[露齿而笑]Test Emoji';
// Convert emoji names in message to HTML
RongIMLib.RongIMEmoji.symbolToHTML(message);
// => "<span class='rong-emoji-content' name='[露齿而笑]'>😁</span>Test Emoji"
Extended Attributes
All messages support two types of extended attributes (user and extra) for transmitting custom business data.
user: Carries user data in messages. Currently supports four properties:user.id,user.name,user.portraitUri, anduser.extra.extra: String-type data that RC does not parse. The business layer handles serialization/deserialization logic.
Code Example
new RongIMLib.TextMessage({
content: '',
extra: '',
user: {
id: '',
name: '',
portraitUri: '',
extra: ''
}
})
When sending FileMessage, ImageMessage, HQVoiceMessage, SightMessage, and GIFMessage, constructing the message instance requires a remote resource URL, which means the business layer needs to first upload the local resource to be sent before building the message instance, making the process relatively complex.
To address this, IMLib has implemented corresponding syntactic sugar methods to encapsulate both the local resource upload process and the message construction process, making it easier for the business layer to integrate.
Sending File Messages
Parameter Description
| Parameter | Type | Required | Description |
|---|---|---|---|
| conversation | IConversationOption | Yes | Conversation |
| msgBody | ISendFileMessageOptions | Yes | Message content to be sent |
| hooks | IUploadHooks | No | Callback hooks during upload |
| sendOptions | IUploadMessageOption | No | Message configuration |
Code Example
const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // File to be uploaded
user: { id: '', name: '', portraitUri: '', extra: '' }, // User information carried in the message (optional)
extra: '' // Transparent data carried in the message (optional)
}
const hooks = {
onProgress (progress) {}, // Upload progress listener (optional)
onComplete (fileInfo) { // Callback hook upon upload completion (optional)
console.log(fileInfo.url) // File storage URL
// To build a custom message, return new ABCMesssage('')
// ABCMesssage is defined via custom message implementation `const ABCMesssage = RongIMLib.registerMessageType(...)`
// If no return value is provided, SDK defaults to sending FileMessage
}
}
const options = {
contentDisposition: 'attachment' // How file links are displayed in browsers (only valid for aws, stc uploads) 'inline': preview in browser, 'attachment': direct download. If not provided, HTML files are previewed while others are downloaded directly.
// ... Other optional configurations
},
RongIMLib.sendFileMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// Successfully sent
}
})
Sending Image Messages
Parameter Description
| Parameter | Type | Required | Description |
|---|---|---|---|
| conversation | IConversationOption | Yes | Conversation |
| msgBody | ISendImageMessageOptions | Yes | Message content to be sent |
| hooks | IUploadHooks | No | Callback hooks during upload |
| sendOptions | IImageMessageOption | No | Message configuration |
Code Example
const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // File to be uploaded
user: { id: '', name: '', portraitUri: '', extra: '' }, // User information carried in the message (optional)
extra: '' // Transparent data carried in the message (optional)
}
const hooks = {
onProgress (progress) {}, // Upload progress listener (optional)
onComplete (fileInfo) { // Callback hook upon upload completion (optional)
console.log(fileInfo.url) // File storage URL
// To build a custom message, return new ABCMesssage('')
// ABCMesssage is defined via custom message implementation `const ABCMesssage = RongIMLib.registerMessageType(...)`
// If no return value is provided, SDK defaults to sending FileMessage
}
}
const options = {
contentDisposition: 'inline' // 'inline' | 'attachment' , determines how links are displayed in browsers when using aws upload
// ... Other optional configurations
},
RongIMLib.sendImageMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// Successfully sent
}
})
Sending High-Quality Voice Messages
If your business also uses IMKit SDK for Android/iOS, please use the default aac format, as IMKit's audio recording and playback only support the aac format and cannot play other formats by default. If your Android/iOS app handles audio recording and playback independently, you can choose the format as needed.
Parameter Description
| Parameter | Type | Required | Description |
|---|---|---|---|
| conversation | IConversationOption | Yes | Conversation |
| msgBody | ISendHQVoiceMessageOptions | Yes | Message content to be sent |
| hooks | IUploadHooks | No | Callback hooks during upload |
| sendOptions | IUploadMessageOption | No | Message configuration |
Code Example
const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // File to be uploaded
user: { id: '', name: '', portraitUri: '', extra: '' }, // User information carried in the message (optional)
extra: '' // Transparent data carried in the message (optional)
}
const hooks = {
onProgress (progress) {}, // Upload progress listener (optional)
onComplete (fileInfo) { // Callback hook upon upload completion (optional)
console.log(fileInfo.url) // File storage URL
// To build a custom message, return new ABCMesssage('')
// ABCMesssage is defined via custom message implementation `const ABCMesssage = RongIMLib.registerMessageType(...)`
// If no return value is provided, SDK defaults to sending FileMessage
}
}
const options = {
contentDisposition: 'attachment' // How file links are displayed in browsers (only valid for aws, stc uploads) 'inline': preview in browser, 'attachment': direct download. If not provided, HTML files are previewed while others are downloaded directly.
// ... Other optional configurations
},
RongIMLib.sendHQVoiceMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// Successfully sent
}
})
Sending Short Video Messages
If your application uses the IMKit SDK on Android/iOS, you must use files encoded with H.264 + AAC, as IMKit's short video recording and playback only support this encoding combination.
Parameter Description
| Parameter | Type | Required | Description |
|---|---|---|---|
| conversation | IConversationOption | Yes | Conversation |
| msgBody | ISendSightMessageOptions | Yes | Message content to be sent |
| hooks | IUploadHooks | No | Callback hooks during upload |
| sendOptions | IUploadMessageOption | No | Message configuration |
Code Example
const conversation = {
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: ''
}
const msgBody = {
file, // File to upload
user: { id: '', name: '', portraitUri: '', extra: '' }, // User information carried in the message (optional)
extra: '', // Pass-through information carried in the message (optional)
duration: 10, // Duration
thumbnail: '' // Thumbnail
}
const hooks = {
onProgress (progress) {}, // Upload progress listener (optional)
onComplete (fileInfo) { // Callback hook when upload completes (optional)
console.log(fileInfo.url) // File storage URL
// To construct a custom message: return new ABCMesssage('')
// ABCMesssage definition via custom message implementation `const ABCMesssage = RongIMLib.registerMessageType(...)`
// If no return value is provided, SDK will send FileMessage by default
}
}
const options = {
contentDisposition: 'attachment' // File link display behavior in browsers (only valid for aws/stc uploads) 'inline': preview in browser, 'attachment': direct download. If not provided, HTML files will preview while others download directly.
// ... Other optional configurations
},
RongIMLib.sendSightMessage(
conversation,
msgBody,
hooks,
options
).then(({ code, data: message }) => {
if (code === 0) {
// Successfully sent
}
})
Sending Typing Status
To synchronize typing status to a specific conversation, call the sendTypingStatusMessage method.
Code Example
RongIMLib.sendTypingStatusMessage({
conversationType: RongIMLib.ConversationType.PRIVATE,
targetId: '<targetId>'
}, RongIMLib.MessageType.TEXT)
Why Resending Failed Messages May Cause Duplicates
This issue may occur when the sender has poor network connectivity.
Scenario
When User A sends a message to User B, the message successfully reaches the server and is delivered to recipient B. However, User A may not receive the server's acknowledgment due to network issues, causing User A to assume the message failed to send. If User A resends the message, User B will receive a duplicate.
Solution
Rong Cloud server does not handle message deduplication. Starting from SDK version 5.5.1, resending messages can include the original message's messageId. Applications can handle duplicates themselves.
Both sent and received messages contain a messageId field, which is a client-generated message ID. When resending messages from the Web client, include the failed message's messageId in the options parameter. Applications can filter duplicates by checking senderUserId and messageId before displaying messages.
Legacy Issues
- When recalling resent messages, only one message may be recalled while the other remains.
- When duplicate messages are received, even if filtered to display only one, the unread count will still show 2.
How to Implement Message Forwarding and Bulk Sending
Forwarding Messages: The IMLib SDK does not provide a dedicated forwarding interface. To implement message forwarding, applications can call the message sending API.
Bulk Sending: Bulk sending refers to sending messages to multiple users. More precisely, it means sending to multiple Target IDs?, where each Target ID may represent a user, group, or chatroom. The client SDK does not provide a direct API for bulk sending. Consider these approaches:
- Have the application loop through the client's message sending API. Note that the client SDK limits message sending to 5 messages per second.
- Integrate the IM Server API on your application server to handle bulk sending. The Send Private Message interface supports sending to multiple users in one call. You can also use the Send Group Message and Send Chatroom Message interfaces to send to multiple groups or chatrooms simultaneously.