You can send and receive email as REPLACE_WITH_IDENTITY@agentmail.to using two Python scripts.
The scripts live in this skill folder and are deployed to ~/.openclaw/workspace/agentmail/.
The scripts contain placeholders which need to be replaced with real-life value:
Copy the scripts and create the venv in the workspace:
DEST=~/.openclaw/workspace/agentmail
SKILL_DIR="$(dirname "$(readlink -f "$0")")" # if running from a script
# or just point SKILL_DIR to this skill folder
mkdir -p "$DEST"
cp "$SKILL_DIR/check_mail.py" "$SKILL_DIR/send_email.py" "$DEST/"
cd "$DEST"
# Create venv (prefer uv, fall back to python)
if command -v uv &>/dev/null; then
uv venv venv
uv pip install --python venv/bin/python agentmail python-dotenv
else
python3 -m venv venv
venv/bin/pip install agentmail python-dotenv
fi
.env filecat > ~/.openclaw/workspace/agentmail/.env << 'EOF'
AGENTMAIL_API_KEY=am_us_.....
EOF
This is only necessary if you don't have the environment variable in your running environment or if you can't read it from your openclaw.json config file.
cd ~/.openclaw/workspace/agentmail
source venv/bin/activate
python check_mail.py # should print "No new mail." on a fresh inbox
cd ~/.openclaw/workspace/agentmail
source venv/bin/activate
python check_mail.py
This downloads all unread messages as JSON files into the workspace directory and marks them as read. Running it again only fetches new mail.
Each message is saved as MAIL.<YYYYMMDDTHHmmss>.<NNN> — timestamp from the message, 3-digit sequence number within the batch.
Example: MAIL.20260226T134244.001
The JSON inside contains:
{ "message_id": "<...>", "thread_id": "...", "timestamp": "2026-02-26 13:42:44+00:00", "from": "Sender Name <sender@example.com>", "to": ["REPLACE_WITH_IDENTITY@agentmail.to"], "cc": null, "subject": "Re: Hello", "text": "Plain-text body...", "html": "<p>HTML body...</p>", "labels": ["received", "unread"], "in_reply_to": "<original-message-id>", "attachments": [] }7w4.net小蔥技能。
# List all mail files (oldest first)
ls -1 MAIL.* 2>/dev/null | sort
# Read one
cat MAIL.20260226T134244.001
# Extract just the text body
python -c "import json,sys; print(json.load(open(sys.argv[1]))['text'])" MAIL.20260226T134244.001
| Code | Meaning |
|---|---|
| 0 | Success (mail downloaded or inbox empty) |
| 1 | Missing API key |
| 2 | API error on initial listing |
| 3 | Total failure (all messages errored) |
cd ~/.openclaw/workspace/agentmail
source venv/bin/activate
python send_email.py
send_email.py is a template with hardcoded recipient/subject/body. For real use, modify its parameters or write a one-off script using the same pattern:
import os
from dotenv import load_dotenv
from agentmail import AgentMail
load_dotenv()
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
client.inboxes.messages.send(
inbox_id="REPLACE_WITH_IDENTITY@agentmail.to",
to="recipient@example.com",
subject="Subject line",
text="Plain-text body.",
)
| Parameter | Required | Description |
|---|---|---|
inbox_id |
yes | Always "REPLACE_WITH_IDENTITY@agentmail.to" |
to |
yes | Recipient email address |
subject |
no | Subject line |
text |
no | Plain-text body |
html |
no | HTML body |
cc |
no | CC addresses |
bcc |
no | BCC addresses |
To reply in the same thread, use reply() with the message_id from a downloaded MAIL.* file:
import json, os
from dotenv import load_dotenv
from agentmail import AgentMail
load_dotenv()
client = AgentMail(api_key=os.getenv("AGENTMAIL_API_KEY"))
# Load the message you want to reply to
with open("MAIL.20260226T134244.001") as f:
msg = json.load(f)
client.inboxes.messages.reply(
inbox_id="REPLACE_WITH_IDENTITY@agentmail.to",
message_id=msg["message_id"],
text="This is my reply.",
)
This preserves threading — the reply appears in the same conversation as the original.
python check_mail.pyMAIL.* files that were createdreply() pattern from section 4rm MAIL.* when done processingcheck_mail.py again later for new messages這個 Skill 質量不錯,文件寫得很詳細,小白也能跟著部署使用。收郵件功能設計合理,能可靠地下載和儲存郵件。發郵件功能比較基礎,實際使用需要自己改程式碼。整體適合有一定技術基礎的使用者使用。