如何获取已发送消息的MAM消息ID?(eJabberd+Strophe.js环境)
解决已发送消息的MAM ID获取问题
刚上手MAM结合eJabberd和Strophe.js的时候,确实容易在已发送消息的服务器ID追踪上卡壳,我来给你梳理几个实用的解决思路:
1. 实时捕获发送消息后的服务器回执ID
这是最直接高效的方式——当你用Strophe发送消息后,eJabberd会在返回的确认消息里带上<stanza-id/>元素,你只需要在发送后监听对应的回调事件,把这个ID和本地存储的消息绑定即可。
举个Strophe的代码示例:
// 发送消息 const sendMsg = (toJid, content) => { const msg = $msg({ to: toJid, type: 'chat' }) .c('body').t(content); connection.send(msg.tree()); }; // 监听服务器返回的消息回执,提取stanza-id connection.addHandler((stanza) => { // 筛选自己发送的消息的回执(根据from/to判断,或者消息类型) const isSentByMe = stanza.getAttribute('to') === connection.jid; if (isSentByMe && stanza.getAttribute('type') === 'chat') { const stanzaIdNode = stanza.querySelector('stanza-id[by="你的服务器域名"]'); if (stanzaIdNode) { const mamId = stanzaIdNode.getAttribute('id'); const body = stanza.querySelector('body')?.textContent; // 将mamId和消息内容绑定,存入本地存储 saveSentMessageToLocal({ content: body, mamId: mamId, timestamp: Date.now() }); } } return true; }, null, 'message', 'chat');
注意:要确保eJabberd配置里开启了发送消息的归档,并且允许返回stanza-id。
2. 反向通过MAM查询补全历史已发送消息的ID
如果是之前已经发送、但没记录ID的历史消息,可以发起MAM查询,筛选出自己作为发送方的消息,再通过内容/时间戳匹配本地存储的消息,补上MAM ID。
代码示例:
// 构造MAM查询,仅获取自己发送给指定联系人的消息 const querySentMessages = (contactJid) => { const mamQuery = $iq({ type: 'set', id: 'mam-sent-query' }) .c('query', { xmlns: 'urn:xmpp:mam:2' }) .c('x', { xmlns: 'jabber:x:data', type: 'submit' }) .c('field', { var: 'FORM_TYPE', type: 'hidden' }) .c('value').t('urn:xmpp:mam:2').up().up() .c('field', { var: 'with' }).c('value').t(contactJid).up().up() .c('field', { var: 'from' }).c('value').t(connection.jid).up().up() .c('set', { xmlns: 'http://jabber.org/protocol/rsm' }).c('max').t('20'); connection.sendIQ(mamQuery, (result) => { const messages = result.querySelectorAll('message'); messages.forEach(msg => { const mamId = msg.querySelector('stanza-id').getAttribute('id'); const body = msg.querySelector('body')?.textContent; // 匹配本地存储的已发送消息,更新mamId字段 updateLocalSentMessageByContent(body, mamId); }); }, (err) => { console.error('MAM查询已发送消息失败:', err); }); };
这种方法适合补全历史数据,但实时场景还是优先用第一种方式。
3. 确认eJabberd的MAM配置正确性
最后一定要检查你的eJabberd.yml配置,确保已发送消息会被归档并携带stanza-id:
mod_mam: default: always # 自动归档所有会话消息 store_messages: true stanza_id_required: true # 强制所有归档消息携带stanza-id require_privacy: false # 允许查询自己发送的消息 max_archive_query_results: 50
如果stanza_id_required没开,服务器可能不会在已发送消息里返回这个元素,这会直接导致你拿不到ID。
内容的提问来源于stack exchange,提问作者serpaulius
相关产品推荐
相关产品推荐

