You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何查看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;

通用配置步骤

  1. 创建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
);
  1. 发送消息时,在记录消息的同时将对应记录的status设为pending;收到回执后更新为delivered。
  2. 确保自定义模块拥有数据库读写权限,避免因权限不足导致写入失败。

内容的提问来源于stack exchange,提问作者pinoyyid

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.20 15:09:24