如何查看ejabberd中消息的送达状态(已送达/未送达)
解决XEP-0184消息送达状态记录问题
数据库排查
- 多数XMPP服务器默认不会将XEP-0184的送达响应写入PostgreSQL,先检查服务器是否开启了相关回执记录插件,比如Prosody的
mod_receipts或Ejabberd的mod_receipt。 - 查看数据库表结构,确认是否存在
message_acks、delivery_receipts这类专门存储回执的表。如果没有,说明需要通过自定义模块实现记录逻辑。
自定义模块钩子实现提示
Prosody服务器
- 利用
message/host钩子拦截所有经过服务器的消息 stanza,识别XEP-0184的received响应元素(命名空间为urn:xmpp:receipts)。 - 提取消息ID、发送方JID、接收方JID等关键信息,写入自定义的PostgreSQL表。
- 核心代码示例:
local function process_receipt(event) local stanza = event.stanza local receipt = stanza:get_child("received", "urn:xmpp:receipts") if receipt then local msg_id = receipt.attr.id local from_jid = stanza.attr.from local to_jid = stanza.attr.to -- 写入PostgreSQL local db_store = module:open_store("delivery_status", "sql") db_store:set(nil, { msg_id = msg_id, from_jid = from_jid, to_jid = to_jid, status = "delivered", timestamp = os.time() }) end end module:hook("message/host", process_receipt)
Ejabberd服务器
- 使用
xmpp_receive或filter_packet钩子捕获包含received回执的消息。 - 通过Ejabberd内置的SQL API执行数据库写入操作,可参考
mod_mam的数据库交互逻辑。 - 核心代码示例(Erlang):
handle_event({xmpp_receive, From, To, Packet}, _State) -> case xml:get_subtag(Packet, "received") of false -> ok; Receipt -> MsgId = xml:get_tag_attr_s("id", Receipt), FromJID = jid:to_string(From), ToJID = jid:to_string(To), % 执行插入SQL ejabberd_sql:sql_query( "INSERT INTO delivery_status (msg_id, from_jid, to_jid, status, timestamp) " "VALUES ($1, $2, $3, 'delivered', now())", [MsgId, FromJID, ToJID] ) end, ok;
通用配置步骤
- 创建PostgreSQL自定义表:
CREATE TABLE delivery_status ( id SERIAL PRIMARY KEY, msg_id VARCHAR(255) NOT NULL, from_jid VARCHAR(255) NOT NULL, to_jid VARCHAR(255) NOT NULL, status VARCHAR(20) NOT NULL CHECK (status IN ('pending', 'delivered')), timestamp TIMESTAMP NOT NULL DEFAULT CURRENT_TIMESTAMP );
- 发送消息时,在记录消息的同时将对应记录的
status设为pending;收到回执后更新为delivered。 - 确保自定义模块拥有数据库读写权限,避免因权限不足导致写入失败。
内容的提问来源于stack exchange,提问作者pinoyyid
相关产品推荐
相关产品推荐

