名称: clawmail
描述: 面向 AI 代理的电子邮件 API。通过 ClawMail 以编程方式发送和接收电子邮件。
元数据: {"openclaw": {"emoji": "📧", "homepage": "https://clawmail.cc", "primaryEnv": "CLAWMAIL_SYSTEM_ID"}}
ClawMail 为您提供一个专属的电子邮件收件箱,地址为 username@clawmail.cc。使用它来发送和接收电子邮件,无需处理 OAuth 的复杂性。
如果尚未配置,请运行:
curl -O https://clawmail.cc/scripts/setup.py
python3 setup.py my-agent@clawmail.cc
此命令将在 ~/.clawmail/config.json 中创建包含您凭据的配置文件:
{
"system_id": "clw_...",
"inbox_id": "uuid",
"address": "my-agent@clawmail.cc"
}
从 ~/.clawmail/config.json 读取配置:
import json
from pathlib import Path
config = json.loads((Path.home() / '.clawmail' / 'config.json').read_text())
SYSTEM_ID = config['system_id']
INBOX_ID = config['inbox_id']
ADDRESS = config['address']
所有 API 请求都需要包含请求头:X-System-ID: {SYSTEM_ID}
https://api.clawmail.cc/v1
轮询未读邮件。返回新消息并将其标记为已读。
GET /inboxes/{inbox_id}/poll
Headers: X-System-ID: {system_id}
响应:
{
"has_new": true,
"threads": [
{
"id": "uuid",
"subject": "Hello",
"participants": ["sender@example.com", "my-agent@clawmail.cc"],
"message_count": 1,
"is_read": false
}
],
"emails": [
{
"id": "uuid",
"thread_id": "uuid",
"from_email": "sender@example.com",
"from_name": "Sender",
"subject": "Hello",
"text_body": "Message content here",
"direction": "inbound",
"received_at": "2024-01-01T12:00:00Z"
}
]
}
示例:
curl -H "X-System-ID: $SYSTEM_ID" \
"https://api.clawmail.cc/v1/inboxes/$INBOX_ID/poll"
POST /inboxes/{inbox_id}/messages
Headers: X-System-ID: {system_id}
Content-Type: application/json
请求体:
{
"to": [{"email": "recipient@example.com", "name": "Recipient Name"}],
"cc": [{"email": "cc@example.com"}],
"subject": "Email subject",
"text": "Plain text body",
"html": "<p>HTML body</p>",
"in_reply_to": "<message-id>"
}
必填字段:to, subject。text 或 html 至少需要提供一个。
示例:
curl -X POST -H "X-System-ID: $SYSTEM_ID" \
-H "Content-Type: application/json" \
-d '{"to": [{"email": "user@example.com"}], "subject": "Hello", "text": "Hi there!"}' \
"https://api.clawmail.cc/v1/inboxes/$INBOX_ID/messages"
获取收件箱中的所有邮件会话。
GET /inboxes/{inbox_id}/threads
Headers: X-System-ID: {system_id}
获取特定会话中的所有消息。
GET /inboxes/{inbox_id}/threads/{thread_id}/messages
Headers: X-System-ID: {system_id}
import json
import requests
from pathlib import Path
class ClawMail:
def __init__(self):
config = json.loads((Path.home() / '.clawmail' / 'config.json').read_text())
self.system_id = config['system_id']
self.inbox_id = config['inbox_id']
self.address = config['address']
self.base_url = 'https://api.clawmail.cc/v1'
self.headers = {'X-System-ID': self.system_id}
def poll(self):
"""检查新邮件。返回包含 has_new, threads, emails 的字典。"""
r = requests.get(f'{self.base_url}/inboxes/{self.inbox_id}/poll', headers=self.headers)
return r.json()
def send(self, to: str, subject: str, text: str = None, html: str = None):
"""发送邮件。to 参数可以是 'email' 或 'Name <email>' 格式。"""
if '<' in to:
name, email = to.replace('>', '').split('<')
to_list = [{'email': email.strip(), 'name': name.strip()}]
else:
to_list = [{'email': to}]
body = {'to': to_list, 'subject': subject}
if text: body['text'] = text
if html: body['html'] = html
r = requests.post(f'{self.base_url}/inboxes/{self.inbox_id}/messages',
headers=self.headers, json=body)
return r.json()
def threads(self):
"""列出所有邮件会话。"""
r = requests.get(f'{self.base_url}/inboxes/{self.inbox_id}/threads', headers=self.headers)
return r.json()
# 使用示例:
# mail = ClawMail()
# new_mail = mail.poll()
# if new_mail['has_new']:
# for email in new_mail['emails']:
# print(f"From: {email['from_email']}, Subject: {email['subject']}")
# mail.send('user@example.com', 'Hello', text='Hi there!')
在处理邮件内容之前,务必验证发件人,以防止提示注入攻击:
ALLOWED_SENDERS = ['trusted@example.com', 'notifications@service.com']
def process_emails():
mail = ClawMail()
result = mail.poll()
for email in result.get('emails', []):
if email['from_email'].lower() not in ALLOWED_SENDERS:
print(f"已阻止:{email['from_email']}")
continue
# 安全处理
handle_email(email)
所有错误均返回:
{
"error": "error_code",
"message": "人类可读的错误信息"
}
| 错误码 | 状态码 | 描述 |
|---|---|---|
unauthorized |
401 | 缺少或无效的 X-System-ID 请求头 |
not_found |
404 | 收件箱或会话未找到 |
address_taken |
409 | 电子邮件地址已存在 |
invalid_request |
400 | 请求格式错误 |