← 返回 Skills 市场
tobewin

Email Writer

作者 ToBeWin · GitHub ↗ · v1.0.4 · MIT-0
cross-platform ✓ 安全检测通过
400
总下载
0
收藏
0
当前安装
5
版本数
在 OpenClaw 中安装
/install email-composer
功能描述
Email writer and sender for OpenClaw. Use when user needs to draft, reply, or send emails via browser. Supports Gmail, Outlook, QQ Mail, 163 Mail. Requires O...
使用说明 (SKILL.md)

Email Writer

Email composition and sending tool using OpenClaw browser automation.

Features

  • Draft professional emails with AI assistance
  • Reply to emails with context
  • Support Gmail, Outlook, QQ Mail, 163 Mail
  • Multi-language support (Chinese and English)

Trigger Conditions

  • "Help me write an email"
  • "Reply to this email"
  • "Send email to someone"
  • "Write a thank you email"

Privacy Warning

This skill accesses your email account through browser session.

  • Reads and sends emails on your behalf
  • Uses your browser email login session
  • Only use on trusted email accounts

Step 1: Understand Email Request

Ask user for email details:

  • Recipient email address
  • Subject line
  • Content/key points
  • Formal or informal tone
  • Language preference

Step 2: Detect Email Provider

// Detect which email provider based on URL
function detectProvider(url) {
  if (url.includes('mail.google.com') || url.includes('gmail.com')) return 'gmail';
  if (url.includes('outlook.live.com') || url.includes('outlook.com')) return 'outlook';
  if (url.includes('mail.qq.com')) return 'qq';
  if (url.includes('mail.163.com')) return '163';
  if (url.includes('mail.126.com')) return '126';
  return 'unknown';
}

Step 3: Open Email Client

// Open email client based on user preference
await browser.open({ url: "https://mail.google.com" })
await browser.wait({ timeout: 5000 })

Supported platforms:

  • Gmail: mail.google.com
  • Outlook: outlook.live.com
  • QQ Mail: mail.qq.com
  • 163 Mail: mail.163.com
  • 126 Mail: mail.126.com

Step 4: Compose New Email

Gmail Compose

// Click compose button (Gmail)
await browser.click({ selector: '[gh="cm"]' })
await browser.wait({ timeout: 2000 })

// Fill recipient
await browser.evaluate((email) => {
  const toField = document.querySelector('[name="to"]');
  if (toField) {
    toField.focus();
    toField.value = email;
    toField.dispatchEvent(new Event('input', { bubbles: true }));
  }
}, recipientEmail)

// Fill subject
await browser.evaluate((subject) => {
  const subjectField = document.querySelector('[name="subjectbox"]');
  if (subjectField) {
    subjectField.focus();
    subjectField.value = subject;
  }
}, emailSubject)

// Fill body
await browser.evaluate((body) => {
  const bodyField = document.querySelector('[role="textbox"][contenteditable="true"]');
  if (bodyField) {
    bodyField.focus();
    bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
  }
}, emailBody)

// Send (Gmail)
await browser.click({ selector: '[gh="s"]' })

Outlook Compose

// Click new message button (Outlook)
await browser.click({ selector: '[aria-label="New message"], .ms-Button--primary' })
await browser.wait({ timeout: 2000 })

// Fill recipient (Outlook)
await browser.evaluate((email) => {
  const toField = document.querySelector('[aria-label="To"], input[placeholder*="To"]');
  if (toField) {
    toField.focus();
    toField.value = email;
    toField.dispatchEvent(new Event('input', { bubbles: true }));
  }
}, recipientEmail)

// Fill subject (Outlook)
await browser.evaluate((subject) => {
  const subjectField = document.querySelector('[aria-label="Subject"], input[placeholder*="Subject"]');
  if (subjectField) {
    subjectField.focus();
    subjectField.value = subject;
  }
}, emailSubject)

// Fill body (Outlook)
await browser.evaluate((body) => {
  const bodyField = document.querySelector('[aria-label="Message body"], [role="textbox"]');
  if (bodyField) {
    bodyField.focus();
    bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
  }
}, emailBody)

// Send (Outlook)
await browser.click({ selector: '[aria-label="Send"], button[title="Send"]' })

QQ Mail Compose

// Click compose button (QQ Mail)
await browser.click({ selector: '.compose-button, .btn-compose, [title="写信"]' })
await browser.wait({ timeout: 2000 })

// Fill recipient (QQ Mail)
await browser.evaluate((email) => {
  const toField = document.querySelector('#to_input, input[name="to"]') ||
                  document.querySelector('[aria-label="收件人"]');
  if (toField) {
    toField.focus();
    toField.value = email;
    toField.dispatchEvent(new Event('input', { bubbles: true }));
  }
}, recipientEmail)

// Fill subject (QQ Mail)
await browser.evaluate((subject) => {
  const subjectField = document.querySelector('#subject, input[name="subject"]');
  if (subjectField) {
    subjectField.focus();
    subjectField.value = subject;
  }
}, emailSubject)

// Fill body (QQ Mail)
await browser.evaluate((body) => {
  const bodyField = document.querySelector('#QMEditorArea iframe') ||
                    document.querySelector('.qmEditorArea');
  if (bodyField) {
    if (bodyField.tagName === 'IFRAME') {
      bodyField.contentDocument.body.innerHTML = body.replace(/\
/g, '\x3Cbr>');
    } else {
      bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
    }
  }
}, emailBody)

// Send (QQ Mail)
await browser.click({ selector: '.btn-send, [title="发送"], .qmBtn' })

163 Mail Compose

// Click compose button (163 Mail)
await browser.click({ selector: '.nui-mainToolbar-btn, .js-component-composebtn' })
await browser.wait({ timeout: 2000 })

// Fill recipient (163 Mail)
await browser.evaluate((email) => {
  const toField = document.querySelector('#draft_to_input, input[name="to"]') ||
                  document.querySelector('.nui-editableAddr-input');
  if (toField) {
    toField.focus();
    toField.value = email;
    toField.dispatchEvent(new Event('input', { bubbles: true }));
  }
}, recipientEmail)

// Fill subject (163 Mail)
await browser.evaluate((subject) => {
  const subjectField = document.querySelector('#draft_subject, input[name="subject"]');
  if (subjectField) {
    subjectField.focus();
    subjectField.value = subject;
  }
}, emailSubject)

// Fill body (163 Mail)
await browser.evaluate((body) => {
  const bodyField = document.querySelector('.APP-editor-iframe iframe') ||
                    document.querySelector('.nuiEditor');
  if (bodyField) {
    if (bodyField.tagName === 'IFRAME') {
      bodyField.contentDocument.body.innerHTML = body.replace(/\
/g, '\x3Cbr>');
    } else {
      bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
    }
  }
}, emailBody)

// Send (163 Mail)
await browser.click({ selector: '.nui-mainToolbar-sendBtn, .js-component-sendbtn' })

Step 5: Reply to Email

Gmail Reply

await browser.click({ selector: '.zA' })
await browser.click({ selector: '[aria-label="Reply"]' })
await browser.wait({ timeout: 2000 })
await browser.evaluate((body) => {
  const bodyField = document.querySelector('[role="textbox"][contenteditable="true"]');
  if (bodyField) bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
}, replyBody)
await browser.click({ selector: '[gh="s"]' })

Outlook Reply

await browser.click({ selector: '[aria-label="Reply"]' })
await browser.wait({ timeout: 2000 })
await browser.evaluate((body) => {
  const bodyField = document.querySelector('[aria-label="Message body"]');
  if (bodyField) bodyField.innerHTML = body.replace(/\
/g, '\x3Cbr>');
}, replyBody)
await browser.click({ selector: '[aria-label="Send"]' })

QQ Mail Reply

await browser.click({ selector: '.btn-reply, [title="回复"]' })
await browser.wait({ timeout: 2000 })
await browser.evaluate((body) => {
  const iframe = document.querySelector('#QMEditorArea iframe');
  if (iframe) iframe.contentDocument.body.innerHTML = body.replace(/\
/g, '\x3Cbr>');
}, replyBody)
await browser.click({ selector: '.btn-send, [title="发送"]' })

163 Mail Reply

await browser.click({ selector: '.js-component-replybtn, [title="回复"]' })
await browser.wait({ timeout: 2000 })
await browser.evaluate((body) => {
  const iframe = document.querySelector('.APP-editor-iframe iframe');
  if (iframe) iframe.contentDocument.body.innerHTML = body.replace(/\
/g, '\x3Cbr>');
}, replyBody)
await browser.click({ selector: '.js-component-sendbtn' })

Step 6: Send Confirmation

// Wait for send
await browser.wait({ timeout: 3000 })

// Check for success message
const sent = await browser.evaluate(() => {
  const text = document.body.innerText;
  return text.includes('Message sent') ||
         text.includes('Sent') ||
         text.includes('已发送') ||
         text.includes('发送成功') ||
         text.includes('邮件已发送');
})

if (sent) {
  console.log("Email sent successfully!")
}

Email Templates

Thank You Email

Subject: Thank you for your support

Dear [Name],

Thank you for [specific reason].

[Details]

Best regards, [Your name]

Work Report

Subject: Work Report - [Date]

Hi Manager,

Weekly report:

  1. Completed tasks
  2. In progress
  3. Next week plan

Best, [Your name]

Meeting Invitation

Subject: Meeting: [Topic]

Hi [Name],

Please join our meeting:

Time: [Time] Location: [Location/Link] Agenda:

  1. Topic 1
  2. Topic 2

Please confirm your attendance.

Thanks, [Your name]

Error Handling

  • Email not logged in: Prompt user to log in
  • Send failed: Prompt user to send manually
  • Attachment failed: Suggest manual attachment
  • Unknown provider: Ask user which email service

Limitations

  • Cannot handle email verification codes
  • Cannot send encrypted emails
  • No batch sending support
  • QQ/163 may need iframe handling

Privacy and Security

  • No email content uploaded externally
  • All processing done locally
  • Browser email session accessed
  • Review before sending sensitive information

Notes

  • Requires OpenClaw v2026.3.22+
  • Gmail has most reliable selectors
  • QQ/163 use iframe for email body
  • Test with non-sensitive account first
安全使用建议
This skill appears to do what it says: use browser automation to compose and send emails. Key things to consider before installing: - It will use your logged-in browser session and can read and send emails on your behalf. Only enable it for accounts you trust. - Because it acts inside your browser, it can access email content (including sensitive messages). Avoid giving it access to high-value or corporate accounts unless you trust the skill's provenance. - The package is instruction-only and has no install steps, but the source/homepage is unknown — prefer skills with a clear author or repository. - When first using it, test by sending drafts to yourself or a throwaway account and review generated text before sending. - If you want stricter control, ensure the agent prompts you to confirm any send action, and consider restricting autonomous invocation if your agent/platform allows that setting.
功能分析
Type: OpenClaw Skill Name: email-composer Version: 1.0.4 The skill is a browser automation tool designed to help users draft and send emails through Gmail, Outlook, QQ Mail, and 163 Mail. The logic in SKILL.md uses standard DOM selectors and browser automation commands (click, evaluate, wait) to interact with legitimate email provider interfaces. There is no evidence of data exfiltration to third-party domains, credential harvesting, or malicious prompt injection; the skill explicitly informs the user of its reliance on existing browser sessions and requires user input for email content.
能力评估
Purpose & Capability
Name and description match the SKILL.md: the skill uses browser automation to draft, reply, and send emails for Gmail, Outlook, QQ Mail, 163/126. It requests no unrelated binaries, env vars, or installs; the resources it needs (a browser session) are consistent with its stated purpose.
Instruction Scope
The instructions explicitly perform actions in the user's browser session: opening provider URLs, inspecting page DOM, filling recipient/subject/body fields, and clicking send. This is expected for an email-sending skill, but it does grant the skill the ability to read mailbox content and send messages on the user's behalf. The SKILL.md includes a privacy warning, which is appropriate. There are no instructions to exfiltrate data to external endpoints or to access other system files.
Install Mechanism
No install spec and no code files (instruction-only). This minimizes disk footprint and there are no remote downloads or package installs to review.
Credentials
The skill declares no required environment variables, no primary credential, and no config paths. That is proportionate: it relies on an existing browser session rather than asking for separate credentials. No unexplained secrets are requested.
Persistence & Privilege
always:false and user-invocable:true (default). The skill can be invoked autonomously by the agent (platform default), which in combination with browser access would allow autonomous sends if the agent chooses to run it — this is not abnormal, but it increases the potential impact if the skill is invoked without explicit user confirmation.
如何使用
  1. 确保已安装 OpenClaw(本地或 Docker 部署)
  2. 在对话框中输入安装命令:/install email-composer
  3. 安装完成后,直接呼叫该 Skill 的名称或使用 /email-composer 触发
  4. 根据 Skill 的参数说明提供必要输入,即可获得结构化输出
版本历史
v1.0.4
支持4种邮箱:Gmail、Outlook、QQ邮箱、163邮箱,每种邮箱独立的DOM选择器
v1.0.3
完全重写SKILL.md,清理所有特殊字符,简化内容
v1.0.2
修复安全扫描问题:移除python3依赖,清理Unicode控制字符
v1.0.1
优化Gmail DOM选择器,更准确的元素定位
v1.0.0
AI邮件撰写和发送工具:支持Gmail/Outlook/QQ邮箱,智能撰写、自动回复、多语言支持
元数据
Slug email-composer
版本 1.0.4
许可证 MIT-0
累计安装 0
当前安装数 0
历史版本数 5
常见问题

Email Writer 是什么?

Email writer and sender for OpenClaw. Use when user needs to draft, reply, or send emails via browser. Supports Gmail, Outlook, QQ Mail, 163 Mail. Requires O... 它是一个面向 Claude Code / OpenClaw 的 AI Agent Skill 插件,目前累计下载 400 次。

如何安装 Email Writer?

在 OpenClaw 或 Claude Code 对话框中运行命令「/install email-composer」即可一键安装,无需额外配置。

Email Writer 是免费的吗?

是的,Email Writer 完全免费,采用 MIT-0 许可证,可自由下载、安装和使用。

Email Writer 支持哪些平台?

Email Writer 跨平台运行,可在任意部署了 OpenClaw / Claude Code 的环境中使用(cross-platform)。

谁开发了 Email Writer?

由 ToBeWin(@tobewin)开发并维护,当前版本 v1.0.4。

💬 留言讨论