PicoClaw Delta Chat 频道接入指南:基于 deltachat-rpc-server 的端到端加密邮件机器人
【免费下载链接】picoclawTiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity项目地址: https://gitcode.com/gh_mirrors/pi/picoclaw
导读
PicoClaw 的 Delta Chat 频道让机器人以端到端加密邮件消息的形式收发消息:PicoClaw 通过 stdio 以 JSON-RPC 2.0 驱动本地deltachat-rpc-server子进程,由后者托管邮箱账户、IMAP/SMTP 连接、消息存储与加密密钥,从而在 Go 二进制中完全摆脱 CGO/原生依赖。读完本文,你将掌握从安装 RPC 服务器、使用 chatmail 中继自动开户、配置channel_list.deltachat全部参数,到理解消息收发、附件媒体、群组触发与跨帖投递限制的完整实战方案。本文以 docs/channels/deltachat/README.md 为骨架,并对照 pkg/channels/deltachat 源码与测试展开底层原理。
架构:PicoClaw 如何驱动 Delta Chat
Delta Chat 是基于邮箱的端到端加密即时通讯工具,其核心(deltachat-core-rust)负责 IMAP/SMTP 连接、消息存储与 Autocrypt 加密密钥管理。PicoClaw 并不直接链接该核心,而是:
- 启动一个本地
deltachat-rpc-server子进程(来自deltachat-rpc-serverpip 包或预编译发布二进制); - 通过新行分隔的 JSON-RPC 2.0(stdio)向它发起调用;
- 由 RPC 服务器完成邮箱相关的全部重活。
这一设计在 包注释 中有明确说明:“PicoClaw does not link the Delta Chat core directly… keeps the Go binary free of CGO/native deps”。实现细节见 rpc.go:rpcClient以exec.Command(serverPath)拉起子进程,并通过DC_ACCOUNTS_PATH环境变量把账户数据库目录传给服务器(startRPC);由于服务器会异步、乱序应答,每次调用都以自增id关联到pendingmap 中的等待者(call)。RPC 服务器的 stderr 日志会被转发进 PicoClaw 的日志系统,方便排障。
通道的启动流程(Start)依次为:创建数据目录 → 启动 RPC 服务器 → 轮询get_system_info等待就绪(waitReady,最多 40 次、每次间隔 250ms)→ 确保账户配置完成(ensureAccount)→ 可选加入邀请链接(joinInviteLink)→ 进入消息监听循环并打印邀请链接与二维码。
安装 deltachat-rpc-server
Delta Chat 频道要求本机存在deltachat-rpc-server可执行文件。两种安装途径:
# 方式一:pip 安装(会一并装好可执行文件) pip install deltachat-rpc-server # 验证是否进入 PATH which deltachat-rpc-server如果deltachat-rpc-server不在PATH中,可在频道配置里用settings.rpc_server_path指定其绝对路径。源码中resolveServerPath(deltachat.go)的逻辑是:未配置时调用exec.LookPath("deltachat-rpc-server")在PATH中查找,找不到即报deltachat-rpc-server not found on PATH;配置了路径则先展开~再校验文件存在性。测试 TestResolveServerPathUsesPATH 验证了从PATH解析的行为。
预编译二进制亦可通过 Delta Chat core 的官方发布渠道获取(详见原文档说明),但安装后必须确保其位于
PATH或提供rpc_server_path。
配置
最小可用配置与首次开户
最简单的接入方式是让 PicoClaw 借助 Delta Chat 本地账户库,在 chatmail 服务器上自动创建机器人邮箱。此时email填入一个“中继标记(relay marker)”——仅含服务器域名的@server形式,本地部分留空,例如:
{ "channel_list": { "deltachat": { "enabled": true, "type": "deltachat", "allow_from": ["friend@example.org"], "group_trigger": { "mention_only": true }, "settings": { "email": "@nine.testrun.org", "display_name": "PicoClaw Bot", "avatar_image": "/home/me/bot-avatar.png" } } } }启动后,PicoClaw 通过deltachat-rpc-server创建账户,随后停止并报错,错误信息中包含生成的完整邮箱地址。将中继标记替换为完整地址后重新运行:
{ "email": "bot123@nine.testrun.org", "display_name": "PicoClaw Bot", "avatar_image": "/home/me/bot-avatar.png" }该两段式流程在源码中有精确实现:parseDeltaChatEmailSetting(deltachat.go)识别以@开头的标记并校验域名合法性;createChatmailBootstrapAccount(deltachat.go)调用add_account与add_transport_from_qr(QR 内容形如DCACCOUNT:https://<server>/new,见buildChatmailAccountQR)创建账户、读取生成的addr,然后故意返回“created chatmail account … Update … email … then run PicoClaw again”的错误,把新地址交给用户。若创建中途失败,cleanupPendingAccount会调用stop_ongoing_process与remove_account清理残留账户。测试 TestNewDeltaChatChannel 覆盖了缺失 email 时报错指引、中继标记合法、无密码引用既有账户等场景。
若email缺失,启动错误会列出内置的 chatmail 中继选项(该列表与 Parla 的CHATMAIL_RELAYS保持同步,见 defaultChatmailRelays)。你可以使用列表中的任一标记,或采用相同@server.name形式指向自建 chatmail 中继。
密码、数据目录与凭据安全
- PicoClaw 创建的 chatmail 账户不需要
password。邮箱口令由 JSON-RPC 服务器持有,因此当email指向data_dir中已配置好的账户时,直接省略password即可。 - 遗留的密码路径仅用于需要 PicoClaw 自行配置/重配置的传统邮箱账户。该模式下
password属于安全字段:首次加载配置时会被迁移到~/.picoclaw/.security.yml,也可以通过环境变量PICOCLAW_CHANNELS_DELTACHAT_PASSWORD注入。 - 源码中密码的用途体现在
configureAccount(deltachat.go):它把addr、mail_server、mail_port、send_server、send_port、mail_pw等键经batch_set_config写入,再以 90 秒超时调用configure校验凭据(configureTimeout,deltachat.go)。accountConfigChanged会在每次启动时比对受管键,发现变化即触发重配置(deltachat.go)。
参数总览
| 字段 | 必填 | 说明 |
|---|---|---|
email | 是 | 机器人完整邮箱地址,或首次运行的@server中继标记(如@nine.testrun.org) |
rpc_server_path | 否 | deltachat-rpc-server路径;仅当它不在PATH时需要 |
password | 否 | 仅遗留模式;当 PicoClaw 必须自行配置/重配置传统邮箱时需要 |
display_name | 否 | 启动时应用的资料名称,显示给联系人,并用于群组提及检测 |
avatar_image | 否 | 启动时应用的资料头像路径;支持~展开,文件缺失时告警并忽略 |
data_dir | 否 | 账户数据库目录,默认~/.picoclaw/deltachat/<channel-name> |
invite_link | 否 | 启动时加入的 Delta Chat 邀请链接 |
allow_crosspost | 否 | 默认false。为true时,通过allow_from放行的发送者可将message工具的目标指向当前会话之外的会话,或按邮箱/联系人/会话名解析收件人 |
imap_server、imap_port | 否 | 密码模式下手动覆盖 IMAP |
smtp_server、smtp_port | 否 | 密码模式下手动覆盖 SMTP |
上述字段在结构体 DeltaChatSettings 中均有对应的 JSON 标签与PICOCLAW_CHANNELS_DELTACHAT_*环境变量(如PICOCLAW_CHANNELS_DELTACHAT_EMAIL、PICOCLAW_CHANNELS_DELTACHAT_RPC_SERVER_PATH),可在不落盘的情况下注入配置。频道默认data_dir的解析逻辑见 resolveDataDir,形如~/.picoclaw/deltachat/<channel-name>;未显式命名频道时使用deltachat作为目录名。
标准频道字段同样适用,包括allow_from、group_trigger和reasoning_channel_id。频道的注册入口在 init.go:init()中通过channels.RegisterFactory注册类型deltachat的工厂函数,读取cfg.Channels[channelName]并解码为*config.DeltaChatSettings后构造通道。
首次运行:从开户到上线
完整首跑流程如下:
- 配置
email为@server形式(如@nine.testrun.org); - 运行 PicoClaw(
picoclaw g生成/校验配置后正常启动):它创建 chatmail 账户,把生成的完整邮箱打印在启动错误中并退出; - 将
email更新为完整地址,再次运行 PicoClaw; - 后续启动时,PicoClaw 按
email选取已配置账户、应用可选资料设置、通过batch_set_config把账户标记为bot({"bot": "1"},见 deltachat.go)、调用start_io开始收发,随后进入监听循环。
对于“全新data_dir+ 遗留password”的场景,PicoClaw 仍可配置传统邮箱账户并校验凭据;此后该账户从本地数据目录复用。
Delta Chat 要求对端先获取机器人的加密密钥才能给它发消息。因此启动时 PicoClaw 会打印机器人的邀请链接和二维码(见printInviteLink,deltachat.go,底层调用get_chat_securejoin_qr_code,终端以半块字符渲染二维码)。好友应在 Delta Chat 中通过该邀请添加机器人,而不是直接输入裸邮箱地址。
行为细节
- 私聊:通过
allow_from校验后总是响应。 - 群聊:遵循
group_trigger;未配置时每条群消息都会被处理。group_trigger.mention_only: true表示仅在提及机器人时响应。 - 忽略规则:机器人自己发出的消息、设备会话(device chat)、info/系统消息一律忽略(见 handler.go)。群内提及检测(
mentionsBot)同时匹配display_name与邮箱本地部分(如@bot123),且是大小写不敏感的整词匹配(handler.go)。 - 入站附件:图片、音频、视频、文档等附件会注册进媒体存储并交给 Agent,使其可以查看图片或直接操作文件。Delta Chat 把附件存放在账户目录内(该目录是工具不允许读取的位置),因此
registerInboundFile(handler.go)先把附件复制到共享媒体临时目录(read_file/load_image允许访问),再以随轮次释放的 scope 注册副本。若媒体存储不可用,则改为在正文内联追加[attachment: /path]。纯文件消息会获得[media](音频为[voice])占位文本,确保轮次不被空内容守卫丢弃(handler.go)。 - 出站附件:Agent 产出媒体时,每个文件作为独立 Delta Chat 消息发送(以字幕为正文)。
SendMedia(deltachat.go)逐 part 解析媒体引用并调用send_msg。Delta Chat 会从文件本身推断视图类型(viewtype),因此图片、GIF、视频可原生渲染;唯一的显式指定是语音回复,强制为Voice使其以语音气泡呈现(deltaChatViewtype,send_tts来源或文件名含voice的音频 part 命中)。 - 跨帖投递(crosspost):默认关闭。Agent 随时可以回复当前会话的数字 chat ID;但发送到另一个数字 chat ID,或按邮箱/联系人/会话名解析收件人,需要
settings.allow_crosspost: true且当前发送者通过allow_from;allow_from: ["*"]则对任意发送者放开。底层校验链在resolveOutboundChatID→requireOutboundRecipientResolution(deltachat.go):数字 ID 只有在等于当前会话时直接放行,否则与名称/邮箱解析一样要求 crosspost 权限;canCrosspost会构造SenderInfo并逐一比对allow_from条目。收件人解析支持mailto:前缀、纯邮箱地址、联系人显示名、会话名,多个匹配时返回歧义错误(deltachat.go)。 - 语音:配置语音 Provider 后双向可用——入站语音留言由 Agent 的 ASR 转写后交给模型;Agent 也可以语音回复,以原生 Delta Chat 语音消息投递(
send_tts)。这依赖voice下配置的 ASR/TTS Provider,并非 Delta Chat 专属配置。通道通过VoiceCapabilities()声明 ASR 与 TTS 均可用(deltachat.go)。 - 输入指示:Delta Chat 基于邮件没有输入指示器,
StartTyping为空操作(deltachat.go)。 - 已读标记:通过 allow-list 校验的入站消息在派发成功后调用
markseen_msgs标记已读;派发失败则保持未读(handler.go)。
疑难排查
| 症状 | 修复 |
|---|---|
deltachat-rpc-server not found on PATH或rpc_server_path ... not found | 把 RPC 服务器安装到 PATH,或将rpc_server_path设为绝对路径 |
email is required | 从列出的 chatmail 服务器中选一个,将email设为首次运行标记(如@nine.testrun.org),运行picoclaw g,再把标记替换为生成的完整邮箱 |
created chatmail account ... | 把email中的@server标记替换为生成的完整邮箱,重新运行 PicoClaw |
account ... is not configured in data_dir | 将data_dir指向现有的 JSON-RPC 账户存储,或使用email="@server"创建一个 |
configure (check email/password/server) | 检查凭据、应用专用密码要求,或使用 IMAP/SMTP 覆盖项 |
| 机器人不在群里应答 | 检查group_trigger;提及display_name或使用配置的前缀 |
| 机器人忽略某发送者 | 把发送者邮箱加入allow_from,或使用["*"]开放访问 |
| 发送者无法给机器人发消息 | 用启动时的二维码/邀请重新添加机器人,让 Delta Chat 建立加密 |
| Agent 无法给某邮箱/名字/其他会话 ID 发送 | 启用settings.allow_crosspost,并在allow_from中放行控制方发送者;出于隐私考虑该能力默认关闭 |
延伸阅读
- 频道设计与通用字段:本仓库 pkg/channels 目录及 channels 文档(中文见 pkg/channels/README.zh.md)
- 各聊天平台接入总览:Chat Apps Configuration
- 配置详解(含安全字段迁移):configuration(中文见 docs/guides/configuration.zh.md)
- 其余频道的独立接入文档见 docs/channels 目录
【免费下载链接】picoclawTiny, Fast, and Deployable anywhere — automate the mundane, unleash your creativity项目地址: https://gitcode.com/gh_mirrors/pi/picoclaw
创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考