mail139
mail139 — 139.com Email Downloader 📬
Download and search emails from 139.com via IMAP using pure Python stdlib. No pip installs needed.
Prerequisites
MAIL139_ID— 139.com email address (e.g.you@139.com)MAIL139_TOKEN— account password/token (fallbacks: prompt orMAIL139_PASSWORD)- If either is missing, stop and tell the user to set them:
export MAIL139_ID="you@139.com" export MAIL139_TOKEN="your-password" - IMAP access must be enabled in the 139.com account settings (设置 → POP3/SMTP/IMAP)
Tool Location
The CLI script is bundled with this skill:
{baseDir}/mail139.py
All commands follow the pattern:
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" <command> [options]
# or simply rely on env defaults:
MAIL139_ID=you@139.com MAIL139_TOKEN=secret python3 {baseDir}/mail139.py <command> [options]
When to Use This Skill
Activate when the user wants to:
- Read, check, or view emails from their 139.com inbox
- Download or save emails to disk
- Search emails by keyword or date
- List mailbox folders on 139.com
- Export emails as JSON or
.emlfiles - Save email attachments from 139.com
Trigger phrases: "check my 139 email", "read my 139.com inbox", "download emails from 139", "search my 139 mail", "list my 139 folders", "save emails from 139.com", "139邮箱", "ä¸å›½ç§»åŠ¨é‚®ç®±", "check inbox"
Commands Reference
List Folders
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" list-folders
Lists all IMAP mailboxes/folders on the account. Run this first if the user wants to fetch from a non-INBOX folder and you don't know the exact folder name.
Folder names are decoded from IMAP modified UTF-7 (handles Chinese names); copy the exact output when passing --folder.
Fetch Emails
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch [options]
| Option | Default | Description |
|---|---|---|
--folder <name> |
INBOX |
IMAP folder to fetch from |
--limit <N> |
10 |
Max emails to fetch (newest first) |
--since <DD-Mon-YYYY> |
— | Only emails on or after this date |
--search <text> |
— | Filter by text in headers or body |
--format <fmt> |
text |
Output format: text, json, or eml |
--output <dir> / -o <dir> |
— | Directory to save output files |
--save-attachments |
off | Save attachments (defaults to ~/Downloads if --output is omitted) |
--mark-read |
off | Mark fetched emails as read on the server |
For
--format eml, files are written to--output. If--outputis omitted, the existing~/Downloadsdirectory is used. If~/Downloadsdoes not exist, the command exits with an error.
HTML bodies are converted to plain text via
lynx --dumpwhen available (fallback to internal stripping). No HTML tags appear in printed/JSON bodies.
Examples:
# Print latest 10 emails to console
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch
# Fetch last 20 emails as JSON
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch \
--limit 20 --format json
# Save as JSON to a directory
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch \
--format json -o ./emails
# Save raw .eml files and extract attachments
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch \
--format eml --save-attachments -o ./emails
# Fetch from Sent folder since a date
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch \
--folder "Sent Messages" --since "01-Jan-2025" --limit 50
# Search for emails containing a keyword
python3 {baseDir}/mail139.py -u "$MAIL139_ID" -p "$MAIL139_TOKEN" fetch \
--search "invoice" --format json
Output Format Details
text
Prints each email to stdout with a header block (UID, Date, From, To, Subject, Attachments) and up to 2 000 characters of body text. Ideal for quick reading.
json
Produces an array of objects. Each object has:
{
"uid": "1234",
"date": "Mon, 10 Mar 2025 09:00:00 +0800",
"from": "sender@example.com",
"to": "you@139.com",
"subject": "Hello",
"content_type": "text/plain",
"body": "Email body text…",
"attachments": ["report.pdf"]
}
Written to emails.json inside --output, or printed to stdout if no --output is given.
eml
Saves each email as <uid>.eml — a raw RFC 822 file openable in any email client. Requires --output.
Important Details
Date Format for --since
Use IMAP date format: DD-Mon-YYYY — e.g. 01-Jan-2025, 15-Mar-2026.
Folder Names
139.com folder names may be in Chinese. Always run list-folders first if unsure. Common folders:
INBOX— inbox (always English)Sent Messages— sent mailDrafts— draftsDeleted Messages— trash
Attachment Saving
Attachments are saved to <output>/<uid>_attachments/<filename>. If --output is not set, attachments default to ~/Downloads/<uid>_attachments/. The --save-attachments flag works independently of --output. By default attachments are saved to ~/Downloads if --output is not specified.
Read-Only by Default
Without --mark-read, the script opens the mailbox read-only and leaves no server-side trace. Pass --mark-read only if the user explicitly asks to mark emails as read.
Behavioral Rules
- Always use
python3to invoke the script. - Prefer env vars for credentials (
$MAIL139_ID,$MAIL139_TOKENfallback$MAIL139_PASSWORD) — never echo passwords in plain text in explanations. - If
MAIL139_IDorMAIL139_TOKENare not set, stop and ask the user to export them before proceeding (or be ready to prompt for password). - Default to
--format textfor casual "check my email" requests; usejsonwhen the user wants to process or save data; useemlwhen they want to archive or open in an email client. - When the user asks to search, use
--searchfor keyword filters and--sincefor date filters; combine both when appropriate. - When the user asks for a specific folder, run
list-foldersfirst if you are unsure of the exact folder name. - Do not use
--mark-readunless the user explicitly asks to mark emails as read. - After fetching JSON, parse and summarise the results for the user — don't just dump the raw JSON unless asked.
- If a command fails, read stderr and explain the issue in plain language (e.g. wrong password, IMAP not enabled, network error).
- For attachment tasks,
--save-attachmentsworks without--output— attachments will be saved to~/Downloads/<uid>_attachments/by default. Only set--outputif the user wants a specific location.