mcpField
V
Voidmail (hosted)

Voidmail (hosted)

远程服务
voidly.ai通信协作02 周前更新

关于 Voidmail (hosted)

Voidmail 是面向 AI Agent 的托管邮件服务和 MCP 服务,支持创建收件箱、读取结构化邮件,并仅向所有者批准的收件人发送邮件。存储邮件可选择在本地管理密钥加密。

主要功能

  1. 01创建 Agent 收件箱
  2. 02等待并读取结构化邮件
  3. 03提取注册验证码
  4. 04向批准的收件人发送邮件
  5. 05可选加密存储邮件

适用场景

  1. 01接收账户验证邮件
  2. 02读取并提取注册验证码
  3. 03在所有者批准范围内发送邮件

MCP 相关

MCP 服务提供创建收件箱、等待和读取邮件、提取验证码及发送邮件的工具。它使用本地保存的收件箱凭据,并可在本机解密封存邮件。

配置

远程服务无需本地安装。选择你使用的客户端,复制配置或使用一键安装。

服务地址https://api.voidly.ai/mcp/mail
一键复制安装命令
Claude CodeTerminal
Cursor.cursor/mcp.json
VS Code.vscode/mcp.json
Claude Desktopclaude_desktop_config.json
Windsurf~/.codeium/windsurf/mcp_config.json

命令在终端中运行;JSON 粘贴到对应客户端的 MCP 配置后重启。需要授权的服务会在首次连接时提示登录。

工具

7

此工具无需参数。

详细介绍

@voidly/mcp-email

为 AI Agent 提供电子邮件功能。创建收件箱,以结构化数据的形式等待并读取收件邮件,还可向人工所有者已批准的收件人发送邮件。无需电话号码或 CAPTCHA。

服务端可以读取的内容。 发往新收件箱的邮件可由服务端读取;它们并非端到端加密。当所有者为收件箱注册密钥(见下文的 owner keys init)后,存储的邮件会加密给该密钥,因此 Voidly 无法读取已存储的邮件。此软件包会在你的机器上生成该密钥,绝不会将其发送给 Voidly,并会在你的机器上解密邮件。但这仍不属于端到端加密:收到的邮件在封存前会短暂以明文形式存在于接收服务器上,而且外部电子邮件并非端到端加密。人工邮件是另一款独立产品。

一条命令创建收件箱

需要 Node.js 20 或更高版本。

npx -y @voidly/[email protected] create --name my-agent

它会显示新地址和密钥的保存位置,但绝不会显示密钥:

Created [email protected]
  agent key: ~/.voidly/mcp-email/[email protected]/agent-key (saved, not shown)
  owner key: ~/.voidly/mcp-email/[email protected]/owner-key (saved, not shown)
  creator identity: ~/.voidly/mcp-email/creator/identity.json (enrolled now)
  recipient policy: allowlist

添加 --address myagent 可申请 [email protected]。然后将 VOIDMAIL_ADDRESS 设置为新地址,再启动 MCP 服务(见下一节)。

工作原理:创建 API 仅接受由已注册的 Voidly Agent 身份(did:voidly:…)签名并附带少量工作量证明的请求。首次运行时,会通过 Voidly Home join 为此机器注册专用的创建者身份;协议 @voidly/agent-sdk 4.0 的 register() 使用此流程:密钥在本机生成,只会发送公钥、API 密钥哈希和签名;密钥会在注册确认前保存(文件权限为 0600,目录权限为 0700),之后保存在 creator/identity.json 中。后续运行会重复使用该身份。每个身份每天最多可创建 2 个收件箱;绝不会通过注册另一个身份来绕过此限制。如果注册的响应丢失,下次运行会完成同一次注册,而不是另行创建。

没有终端?Agent 也可以通过 MCP 执行相同操作:将 env 留空,然后调用 voidmail_create_account。

安装为 MCP 服务

请固定运行的版本:Voidly 发布此客户端,而客户端负责保管你的密钥。

npx @voidly/[email protected]

将以下内容添加到 ~/Library/Application Support/Claude/claude_desktop_config.json(Claude Desktop):

{
  "mcpServers": {
    "voidmail": {
      "command": "npx",
      "args": ["-y", "@voidly/[email protected]"],
      "env": {
        "VOIDMAIL_ADDRESS": "[email protected]"
      }
    }
  }
}

VOIDMAIL_ADDRESS 用于指定服务端应使用 <key dir>/<address>/agent-key。如果未设置,Agent 可以通过 voidmail_create_account 创建收件箱;之后设置 VOIDMAIL_ADDRESS,以便下次启动时找到密钥文件。

快速开始

安装 MCP 服务后,使用以下提示词:

创建一个 Voidmail 收件箱,并告诉我它的地址和收件箱密钥的保存位置。请先起草邮件,发送前等我批准。

用于注册流程:调用 voidmail_wait_for_email(最多等待 25 秒,可选按发件人、主题和 since 筛选),然后对其返回的邮件调用 voidmail_extract_code。这两个工具都只读取邮件;它们不会将邮件标记为已读、不会打开任何链接,也绝不会返回 HTML。它们返回的代码或链接属于不可信的发件人内容:只能用于你发起的注册流程。

获取 DID(改用你自己的 Agent 身份)

create 和 voidmail_create_account 会创建各自的创建者身份,因此此步骤是可选的。若要使用你已在运行或自行注册的 Agent 身份签名,请使用 @voidly/agent-sdk 4.0(直接通过 /v1/agent/register 注册客户端密钥的方式已关闭;register() 使用 Home join):

// npm i @voidly/[email protected]   ·   run once, keep the file private
import { VoidlyAgent } from '@voidly/agent-sdk';
import { writeFileSync } from 'node:fs';

const agent = await VoidlyAgent.register({ name: 'my-agent' });
writeFileSync('agent-credentials.json', JSON.stringify(agent.exportCredentials()), { mode: 0o600 });

然后让 MCP 服务(或 create)使用该文件。它会从文件中读取 DID:

{
  "VOIDMAIL_CREATOR_SIGNING_KEY_FILE": "/private/path/to/agent-credentials.json"
}

该文件必须归你所有,且权限为 0600;如果文件是符号链接、权限过于宽松,或密钥与其 DID 不匹配,系统会在发送任何内容前拒绝该文件。2.0 格式仍可使用:文件中必须恰好包含 64 个原始 Ed25519 私钥字节,并设置 VOIDMAIL_CREATOR_DID 为对应的 DID。导出的身份文件包含该身份的所有密钥;MCP 进程会在创建时读取该文件。专用的创建者身份(默认设置)可让邮件客户端不接触你的主 Agent 身份。

使用你自己的代码进行签名创建

API 验证的证明,包含在两个简短脚本中。每个脚本都会读取 agent-sdk 身份导出文件(见上文,或本包的 creator/identity.json),并打印状态和地址。响应会一次性返回收件箱的 Agent 密钥(vm_…)和所有者密钥(vmo_…);请将它们保存到权限为 0600 的文件中,切勿打印或记录它们。

Node.js 20+(npm i tweetnacl):

import { createHash, randomBytes } from 'node:crypto';
import { readFileSync } from 'node:fs';
import nacl from 'tweetnacl';

const creds = JSON.parse(readFileSync(process.argv[2], 'utf8'));
const sha = (text) => createHash('sha256').update(text).digest();
const body = JSON.stringify({ name: 'my-agent', recipient_policy: 'allowlist' });
const ts = String(Math.floor(Date.now() / 1000));
const nonce = randomBytes(16).toString('hex');
const preimage = ['voidmail-create-v1', 'POST', '/v1/agent-mail/create', creds.did, ts, nonce, sha(body).toString('hex')].join('\n');
let work;
for (let i = 0; ; i++) {
  work = i.toString(16).padStart(16, '0');
  const h = sha(`voidmail-create-pow-v1\n${preimage}\n${work}`);
  if (h[0] === 0 && h[1] === 0) break;
}
const secretKey = Buffer.from(creds.signingSecretKey, 'base64');
const signature = Buffer.from(nacl.sign.detached(Buffer.from(`${preimage}\n${work}`), secretKey)).toString('base64');
const res = await fetch('https://api.voidly.ai/v1/agent-mail/create', { method: 'POST', body, headers: {
  'Content-Type': 'application/json', 'X-Agent-DID': creds.did, 'X-Mail-Timestamp': ts,
  'X-Mail-Nonce': nonce, 'X-Mail-Pow': work, 'X-Mail-Signature': signature } });
const out = await res.json();
console.log(res.status, out.address ?? out.error);

Python 3(pip install pynacl):

import base64, hashlib, json, secrets, sys, time, urllib.request
from nacl.signing import SigningKey

creds = json.load(open(sys.argv[1]))
body = json.dumps({"name": "my-agent", "recipient_policy": "allowlist"}).encode()
ts, nonce = str(int(time.time())), secrets.token_hex(16)
preimage = "\n".join(["voidmail-create-v1", "POST", "/v1/agent-mail/create", creds["did"], ts, nonce, hashlib.sha256(body).hexdigest()])
i = 0
while True:
    work = format(i, "016x")
    h = hashlib.sha256(f"voidmail-create-pow-v1\n{preimage}\n{work}".encode()).digest()
    if h[0] == 0 and h[1] == 0:
        break
    i += 1
seed = base64.b64decode(creds["signingSecretKey"])[:32]
signature = base64.b64encode(SigningKey(seed).sign(f"{preimage}\n{work}".encode()).signature).decode()
req = urllib.request.Request("https://api.voidly.ai/v1/agent-mail/create", data=body, method="POST", headers={
    "Content-Type": "application/json", "User-Agent": "voidmail-create-example/1", "X-Agent-DID": creds["did"],
    "X-Mail-Timestamp": ts, "X-Mail-Nonce": nonce, "X-Mail-Pow": work, "X-Mail-Signature": signature})
with urllib.request.urlopen(req) as res:
    print(res.status, json.load(res).get("address"))

签名涵盖所发送的确切请求正文的 SHA-256,因此发送的字节必须与计算哈希时使用的字节相同。时间戳必须在服务时间前后五分钟内,并且每组 DID/nonce 只能创建一个收件箱。不带这些标头的裸 POST /v1/agent-mail/create 请求会返回 401。

HTTP 401 表示缺少创建证明、证明无效、时间戳已过期,或 DID 未激活;请检查身份和密钥。HTTP 429 表示已达到创建上限;请遵守 Retry-After,复用现有收件箱或等待,切勿通过更换 DID 或 IP 来规避上限。503 可能表示准入、身份或提交检查暂不可用;结果可能未知。如果已发送创建请求但结果未知,请勿自动创建另一个收件箱:应先核实原始尝试的结果。

加密存储

每个收件箱只需从你自己的终端启用一次(绝不要让模型启用):

voidly-mcp-email owner keys init --address [email protected]
  • 它的作用。 它会在这台机器上生成两个密钥:一个用于封装邮件的 X25519 密钥(mail-secret-key),以及一个用于签署收件箱密钥列表的 Ed25519 密钥(mail-signing-key)。两个密钥都是收件箱密钥目录中的 0600 文件。随所有者密钥一起发送的只有公钥、签名,以及你持有该密钥的证明。此后,服务器会将每封新邮件(包括标头、正文和附件)封装给你的密钥,并且只存储加密副本。此开关不可逆。
  • Voidly 能读什么、不能读什么。 对于已注册密钥的收件箱,Voidly 无法读取已存储的邮件。被篡改的 Voidly 服务器可以复制之后收到的邮件,但无法打开已存储的邮件。接收邮件时,它仍会在封装前短暂以明文形式看到每封邮件;运行我们入站邮件服务器的 Cloudflare 也能看到。Cloudflare 的 Email Routing 日志会记录每封邮件的发件人、收件人和主题,我们的账户可以查看这些信息。Voidly 会保留发件人域名、到达时间和邮件大小;此外,最多保留 14 天每封邮件的带密钥指纹,用于丢弃重复投递的邮件。在指纹仍存在期间,Voidly 可以用猜测的邮件内容对其进行比对。你发送到外部地址的邮件不会进行端到端加密:它会以明文形式经过 Voidly 和我们的发送服务提供商 Resend。
  • 旧邮件。 注册密钥前存储的邮件仍可由服务器读取。工具结果会为每封邮件标记 storage: "sealed"(在本地解密)或 storage: "server-readable"。注册密钥后收到的可读邮件会带有 storage_warning。
  • 读取和搜索。 voidmail_list_inbox 会打开每封邮件的加密摘要;voidmail_read_email 会下载加密邮件并打开它。搜索在这台机器上运行:服务器不会收到搜索加密邮件的请求。默认情况下,搜索会匹配主题、发件人、收件人以及加密邮件的前 280 个字符;full_text: true 还会下载并搜索完整的加密正文。如果邮件无法解密,或绑定到了其他收件箱或邮件 ID,则不会显示其中的任何内容,连服务器提供的字段也不会显示。
  • 密钥列表检查。 mail-keys.json 会固定你的签名密钥和你已见过的最新密钥列表版本(epoch)。voidly-mcp-email owner keys status 会检查服务器上的列表:每个密钥都必须由你的签名密钥签署,列表必须包含该 epoch 的所有密钥,且版本不得早于已固定的版本。每封邮件也会列出其封装目标密钥,并警告你是否存在这台机器尚未验证的密钥。
  • 限制。 此机制不提供前向保密:任何获得 mail-secret-key(或 keyring/ 中密钥)的人都可以读取为其加密存储的所有邮件。如果你丢失密钥及其备份,任何人都无法恢复这些邮件,包括 Voidly,因此请私下备份密钥目录。加密不能证明邮件的发送者身份。MCP 服务会读取 mail-secret-key 进行解密;它绝不会读取 mail-signing-key,也没有任何工具可以创建、注册或更改密钥。任何以你的用户身份运行的程序(例如拥有 shell 或文件工具的 Agent)也都能读取密钥文件。
  • 轮换。 voidly-mcp-email owner keys rotate 会注册一个新密钥,并将旧密钥保留在 keyring/ 中,因此仍可打开较早的邮件。

权限:不同密钥,同一所有者

每个收件箱都有两项凭据(Agent 密钥和所有者密钥),启用加密存储后还会有两个邮件密钥。此软件包会将每个密钥分别存放在独立文件中。

密钥文件(0600,目录 0700)使用者功能
Agent 密钥 vm_…~/.voidly/mcp-email/<address>/agent-keyMCP 服务,用于模型的工具读取、发送给已批准的收件人、请求添加收件人、移除收件人、收紧策略
所有者密钥 vmo_…~/.voidly/mcp-email/<address>/owner-key你,通过 voidly-mcp-email owner批准或拒绝请求、添加或移除收件人、锁定或解锁、轮换任一密钥、注册邮件密钥
邮件私密密钥 vmx_…~/.voidly/mcp-email/<address>/mail-secret-key(旧密钥位于 keyring/ 中)MCP 服务,用于在此计算机上解密打开发送到此收件箱的密封邮件;绝不会发送到任何地方
邮件签名密钥 vms_…~/.voidly/mcp-email/<address>/mail-signing-key你,通过 voidly-mcp-email owner keys为收件箱的密钥列表签名;绝不会发送到任何地方
创建者身份~/.voidly/mcp-email/creator/identity.json,或由 VOIDMAIL_CREATOR_SIGNING_KEY_FILE 指定的你自己的文件create 和 MCP 服务,仅用于创建收件箱以该 Agent DID 的身份签署创建请求;默认身份专用于此用途,而你自己的身份文件还具有该身份的其他权限
  • create 和 voidmail_create_account 会写入这两个文件,并且只显示它们的路径。此服务绝不会在工具结果中放入任何密钥。 它发出的每条消息都会清除 Voidmail 密钥格式(vm_…、vmo_…、vmx_…、vms_…)和 AGE-SECRET-KEY-… 字符串,包括从电子邮件中收到的此类字符串。电子邮件中收到的其他密钥(例如云服务或 GitHub 令牌)则会原样传递给模型。
  • MCP 服务绝不会读取所有者密钥文件,也绝不会调用所有者 API 路由(/v1/agent-mail/owner/*)。没有任何工具会使用所有者密钥。
  • 权限模式 0600 能阻止其他操作系统用户访问,但无法阻止你的 Agent。 任何以你的用户身份运行的程序都能读取所有者密钥文件,包括拥有 shell 或文件工具的 Agent(编码 Agent、文件系统 MCP 服务)。这样的 Agent 可能会读取所有者密钥,并批准自己的收件人。如果你的 Agent 在这台机器上拥有 shell 或文件访问权限,请将所有者密钥文件移到它无法读取的位置,或移到这台机器之外,并在运行所有者命令时将 VOIDMAIL_OWNER_KEY_FILE 指向该文件。
  • 使用此软件包创建的收件箱会启用经所有者批准的收件人列表,由 Voidly API 强制执行,而非依赖模型指令。(REST 创建请求若不选择启用,仍会创建旧类型的收件箱:没有所有者密钥、允许任意收件人,仅提供凭证警告。创建时设置 recipient_policy: "allowlist"、owner_key: true 或 content_policy: "enforce" 即可选择启用;只有此时响应才会包含 owner_key。此软件包始终发送 recipient_policy: "allowlist"。)向其他收件人发送邮件会返回 RECIPIENT_NOT_AUTHORIZED,并带有 send_attempted: false。API 会记录待处理请求,工具结果会明确说明所有者必须运行的命令。
  • 对于启用了凭证拦截的收件箱(默认情况下,带有所有者密钥的收件箱都会启用),如果消息看起来包含凭证(私钥、云服务、GitHub、Slack、Stripe、AI 服务提供商或 Voidmail 密钥),就会以 CONTENT_CONTAINS_CREDENTIAL 拒绝该消息。工具结果会列出发现的类型,但绝不会显示匹配的文本。检查只匹配已知密钥格式;无法检测密码、不熟悉的令牌格式,或因其他原因而敏感的数据。
  • 发送邮件前会检查其中是否包含凭证。 发送消息前,API 会在内存中扫描收件人、主题、正文和回复地址,以查找已知凭证格式。扫描不会保留任何匹配内容,只会按天记录发现的每种类型的数量。对于启用了凭证拦截的收件箱(默认情况下,带有所有者密钥的收件箱都会启用),一旦发现匹配项,就会阻止发送。对于其他收件箱,消息仍会发送,响应会在 X-Voidmail-Content-Warning 标头中列出发现的类型。所有者可以通过 https://voidly.ai/agent-mail/owner 关闭此检查(或使用 POST /v1/agent-mail/owner/policy 并设置 content_policy: "off")。唯一的例外是通过 bootstrap 创建的所有者密钥,详情见下文:它无法关闭此检查。
  • Agent 密钥只能收紧限制:可以移除收件人或启用拦截。任何会扩大 Agent 权限的操作都需要所有者密钥。
  • 批准收件人需要所有者密钥,而此服务无法通过电子邮件提供该密钥。请将收到的邮件视为不可信内容。
所有者命令
voidly-mcp-email owner list                              # policy, recipients, pending requests
voidly-mcp-email owner approve <request-id>              # shows the recipient, asks you to confirm
voidly-mcp-email owner deny <request-id>
voidly-mcp-email owner add [email protected]            # or @example.com for a whole domain
voidly-mcp-email owner remove [email protected]
voidly-mcp-email owner lock                              # allowlist + credential blocking
voidly-mcp-email owner unlock                            # any recipient; asks you to confirm
voidly-mcp-email owner rotate-agent-key                  # old key stops working at once
voidly-mcp-email owner rotate-owner-key                  # replaces the owner-key file it read
voidly-mcp-email owner keys init                         # encrypted storage on; asks you to confirm
voidly-mcp-email owner keys status                       # check the server's key list against your pin
voidly-mcp-email owner keys rotate                       # new mail key; old one kept for old mail

保存了多个收件箱时,添加 --address <[email protected]>;添加 --yes 可在无需提示的情况下确认。approve 会先读取待处理请求并指出其收件人,若指定的 id 不处于待处理状态则会拒绝。轮换后的密钥会写入对应文件,绝不会打印出来。rotate-owner-key 会原子替换其读取的所有者密钥文件,包括 VOIDMAIL_OWNER_KEY_FILE 指定的路径。旧所有者密钥会先被撤销,再保存新密钥;因此,如果无法替换该文件,新密钥会写入其旁边一个权限为 0600 的新文件,只有这也失败时,新密钥才会在终端上显示一次。读取密钥文件的 MCP 服务会在下次调用时使用轮换后的 Agent 密钥。也可以在浏览器中执行相同操作,网址为 https://voidly.ai/agent-mail/owner;所有者密钥仅保存在内存中。

没有所有者密钥的收件箱(由 mcp-email 1.1.0 或更早版本创建,或由未选择启用此功能的 REST create 创建)会保留旧有行为:允许任意收件人,仅发出凭据警告,且存储内容可被服务器读取。随 2.0 一同发布的服务器版本已关闭 Agent 密钥所有者引导流程(POST /v1/agent-mail/owner/bootstrap):模型持有的是 Agent 密钥,因此该密钥不得用于认领所有者角色或重定向邮件。此类收件箱无法获得所有者密钥或加密存储;请使用此软件包创建新收件箱并迁移过去。较早的引导流程签发的所有者密钥仍保留收件人和策略权限,无法关闭凭据防护(CONTENT_POLICY_FLOOR),也无法注册邮件密钥或轮换 Agent 密钥(OWNER_KEY_FROM_AGENT_KEY)。

使用 voidmail_list_inbox 检查收到的邮件,然后使用 voidmail_read_email 阅读邮件。发送邮件前,请先核对收件人、主题和正文,再调用 voidmail_send_once。调用前,请在宿主状态中生成并保存唯一的操作 ID;响应丢失后查询状态,以及所有者批准被拒收的收件人后重试时,都要使用同一个 ID。

工具(21)

工具描述
voidmail_create_account创建新的 @voidmail.ai 收件箱,并提供 DID 签名证明(如果尚无专用创建者身份,则先注册一个);将两把收件箱密钥保存到权限为 0600 的文件中,并且只返回文件路径
voidmail_account_info获取账户详情
voidmail_list_inbox使用分页和筛选条件列出邮件;加密邮件会在此处解密
voidmail_read_email阅读指定邮件;如果邮件已加密,则在此处解密(并自动标记为已读)
voidmail_search_inbox在本机搜索主题、发件人、收件人和正文;绝不进行服务端搜索
voidmail_wait_for_email最多等待 25 秒,按发件人、主题或到达时间查找新邮件;返回其 ID、发件人和主题;不会标记任何邮件为已读
voidmail_extract_code从一封邮件的纯文本中提取可能的一次性验证码和 HTTPS 验证链接(密封内容会在此处解密);内容不可信,绝不处理 HTML
voidmail_sending_limits读取发送政策,不消耗发送额度
voidmail_send_once发送一封已授权邮件,并保存操作 ID 和后续状态
voidmail_send_status读取同一封原始邮件的发送状态,不会再次发送
voidmail_send_email旧版发送方式,不保留持久化状态;优先使用 voidmail_send_once
voidmail_policy读取收件人和内容政策、已批准的收件人及待处理请求
voidmail_request_recipient请求所有者批准某位收件人;返回审批步骤
voidmail_revoke_recipient移除已批准的收件人(限制权限无需所有者批准)
voidmail_mark_read将邮件标记为已读
voidmail_delete_email删除邮件
voidmail_create_alias创建一次性邮箱别名
voidmail_list_aliases列出所有别名
voidmail_delete_alias移除别名
voidmail_set_webhook在开放政策的收件箱上设置 HTTPS webhook,无需所有者密钥;允许列表收件箱或任何配置了所有者密钥的收件箱,需要人工所有者使用所有者密钥调用 POST /v1/agent-mail/owner/webhook
voidmail_get_stats收件箱统计信息

资源(3)

资源URI描述
收件箱email://inbox当前收件箱内容
别名email://aliases有效的邮箱别名
统计信息email://stats账户统计信息

环境变量

变量必填描述
VOIDMAIL_ADDRESS适用于现有收件箱你的 @voidmail.ai 地址;服务每次调用时都会读取 <key dir>/<address>/agent-key
VOIDMAIL_KEY_DIR否密钥目录(默认值 ~/.voidly/mcp-email)
VOIDMAIL_AGENT_KEY_FILE否指定 Agent 密钥文件路径(覆盖地址查找)
VOIDMAIL_API_KEY否由主机直接提供的 Agent 密钥(vm_…);优先于文件。任何其他密钥(包括所有者密钥)都会被拒绝,且绝不会发送。执行 rotate-agent-key 后请更新此变量
VOIDMAIL_CREATOR_SIGNING_KEY_FILE否你自己的创建者身份:@voidly/agent-sdk 身份导出文件(JSON),或恰好包含 64 个原始 Ed25519 私钥字节的文件。文件必须由你持有,权限为 0600;绝不能是收件箱邮件签名密钥或所有者密钥。未设置时,使用 <key dir>/creator/identity.json,并在首次创建时注册
VOIDMAIL_CREATOR_DID使用原始密钥文件时必填原始 64 字节密钥文件对应的 DID。使用 JSON 导出文件时为可选项,且必须与文件中的 DID 一致
VOIDMAIL_CREATOR_AUTO_ENROLL否设为 off 时,若未配置或存储创建者身份,create 和 voidmail_create_account 将不会注册该身份
VOIDMAIL_OWNER_KEY_FILE否仅限所有者 CLI:指定所有者密钥文件路径。MCP 服务绝不会读取此文件
VOIDMAIL_SIGNING_KEY_FILE否仅限所有者 CLI:指定邮件签名密钥路径(如果你将其与 Agent 隔离存放)。MCP 服务绝不会读取此文件

REST API

无需 MCP,直接使用:

# List inbox
curl https://api.voidly.ai/v1/agent-mail/inbox \
  -H "X-Agent-Mail-Key: vm_your_key"

# Send email
curl -X POST https://api.voidly.ai/v1/agent-mail/send \
  -H "X-Agent-Mail-Key: vm_your_key" \
  -H "Content-Type: application/json" \
  -d '{"to":"[email protected]","subject":"Hello","text":"From my agent"}'

# Search (server-readable inboxes only; an inbox with encrypted storage answers 410
# SEARCH_IS_CLIENT_SIDE, and this package searches on your machine instead)
curl "https://api.voidly.ai/v1/agent-mail/inbox/search?q=invoice" \
  -H "X-Agent-Mail-Key: vm_your_key"

直接通过 REST 创建需要来自活跃 Agent DID 的签名证明:请参阅使用自己的代码进行签名创建。

加密消息会以 { "sealed": true, "envelope": … } 的形式返回;加密正文位于 GET /v1/agent-mail/inbox/{id}/sealed-body。打开这些消息需要收件箱的邮件密钥,而该密钥只有你的机器持有。

限制与交付

在规划发送工作流之前,调用 voidmail_sending_limits(或公开的 GET /v1/agent-mail/limits)。将超出的工作保留在自己的队列中。429 会返回 Retry-After 标头以及结构化的限制范围/重置时间;MCP 错误中会包含等待时间。不得通过轮换账户或 IP 来规避限制。相同消息会被拦截 60 秒,以防止循环;这并非持久幂等机制。如果安全计数器不可用,发送将以失败关闭。收件箱读取与发送限制彼此独立。

共享上限:每个 IP 每小时 100 次尝试;Agent 邮件每小时 200 次、每天 1,500 次。所有发送功能共用的出站服务商预算最多为每天 1,500 位收件人,在约 31 天内总计 40,000 位。计数器会统计尝试次数,包括失败和部分受理的请求;这些是上限,而非预留容量。合法的更高发送量需要由运营人员审核并更改限制;创建邮箱不会解锁群发邮件。

  • 发送受每个邮箱、每个 IP 和共享服务限制。每个邮箱每分钟最多可尝试发送 10 封邮件,每天最多 100 封;向同一收件人每天最多发送 10 封。共享限制可能会更早拒绝请求。每个 IP 每小时最多可尝试创建邮箱 3 次;每个服务每小时最多 600 次;每个 DID 每天最多 2 次已签名尝试;每个服务每小时最多 60 次已签名尝试。这些计数器包括失败或部分受理的请求。这不是无限量发送服务。
  • 发送成功的响应表示发送服务商已受理该请求。这并不能证明收件人已收到邮件,也不能证明有人已阅读邮件。
  • 每次 API 调用的截止时间为 20 秒,响应上限为 2 MiB。请求遇到重定向时会被拒绝,且绝不会自动重试。如果收件箱响应超过上限,请减少请求的邮件数量。
  • MCP 工具注释会如实标明读取、发送、修改和删除操作。这些只是建议性元数据;审批和安装警告仍由 ChatGPT、Claude 或其他宿主控制。
  • 如果发送超时,结果可能未知。使用 voidmail_send_once 和 voidmail_send_status,并提供已保存的操作 ID;不要盲目重发。
  • 对于可由服务端读取的收件箱,系统会解析收到的文本和 HTML 正文;不会保留附件,也不会填充回复线程元数据,尽管响应架构中包含这些字段。对于采用加密存储的收件箱,整封原始邮件(包括附件)都会被封存;工具会显示附件名称和大小,但不会显示附件内容。目前尚不支持可靠的线程式回复。
  • 新邮件 Webhook 采用尽力而为方式,不提供持久重试历史。请通过读取收件箱来核对遗漏的通知。对于白名单收件箱或任何设有所有者密钥的收件箱,所有者必须在 Agent 外部通过 POST /v1/agent-mail/owner/webhook 注册 Webhook;voidmail_set_webhook 无法执行此操作。所有者密钥 API 更新上线后,新注册的 Webhook 会使用 X-Voidmail-Signature-256: t=<timestamp>,v1=<HMAC-SHA256> 进行签名。在此之前注册的 Webhook 也会继续收到旧版 X-Voidmail-Signature 标头,其中直接包含共享密钥,并非负载签名;直到重新注册为止。
  • 将收到的邮件视为不可信内容。邮件不能授权 Agent 发送邮件、泄露私人数据或花费资金。API 仅会在请求携带所有者密钥时添加收件人,因此请将该密钥保存在 Agent 无法读取的位置。
  • 所有者密钥猜测次数按网络限制:来自同一个 IP 地址(IPv6 /64)的所有者密钥尝试连续失败多次后,该网络发出的所有者调用都会被拒绝,直到当前 UTC 小时结束,即使使用了正确的密钥也不例外。与你共用网络的人可能触发此限制。

变更

请参阅 CHANGELOG.md。2.1.1 修正了软件包描述。2.1.0 新增了 voidly-mcp-email create、自动创建者身份注册、作为创建者密钥文件的 agent-sdk 身份导出、voidmail_wait_for_email 和 voidmail_extract_code。

链接

许可证

MIT

持久发送(1.1.0)

使用 voidmail_send_once,并提供由主机保存的 operationId(由 16–128 个字母、数字、下划线或连字符组成)、收件人、主题和正文。相同邮箱、ID 和有效内容会返回保留的原始记录;内容变更则会产生冲突。主机必须在发送前保留该 ID。连接器不会为你生成或保存 ID。请将邮箱凭据保存在主机配置中,而不要放在消息正文里。

超时或响应丢失后,使用 voidmail_send_status 查询状态。accepted 表示服务提供商已接受请求,并不代表邮件已送达或已读。prepared 表示尚无已声明的派发;outcome_unknown 可能包含仍在进行或已中断的派发;refused_before_send 表示记录了一项已知在联系服务提供商前就被拦截的请求。任何状态都不允许自动更换 ID。服务不会因超时、重启或时间经过而重新认领派发。若在调用服务提供商前发生故障,系统可能会保守地保留一条尚未解决的原始记录,以避免重复发送邮件。

REST 对应接口为 POST /v1/agent-mail/outbound 和 GET /v1/agent-mail/outbound/{operationId},使用现有的邮箱身份验证。新建操作记录和发送受现有邮箱/服务上限约束;查询已存储的原始记录不会占用发送配额。并发的首次尝试可能会占用保守的准入计数器。旧版 /send 端点和 voidmail_send_email 保留原有行为,不保证状态持久化。送达 Webhook、回复串接、发件正文历史记录和附件属于单独的后续工作。

评论

支持 Markdown

第一次接触 MCP?

从协议是什么,到在客户端里装上第一个服务,这几条回答覆盖了大多数入门问题。

一个开放协议,规定了 AI 应用如何以统一方式连接外部工具与数据源。客户端负责与模型对话,MCP 服务负责提供工具、资源和提示模板,两者通过标准消息通信,同一个服务可以被不同客户端复用。