Skip to content
Back to skills

Email Client

ASecurity

Use when the user asks to access or manage email or a registered email account. Do not use when the primary request is inbox triage or shared Google authentication setup.

  • 4 stars
  • 0 votes
  • 0 copies
  • 2 views
  • Added September 2, 2026
ai-agentsgosecurity

Works with

  • cli
  • mcp

Security analysis

A100/100

Pro scans all 20 files and shows the line behind each finding

Scanned September 20, 2026

npx -y skills add MoeenNehzati/famulus --skill email-client --agent claude-code

Installs into .claude/skills of the current project.

Are you the author of Email Client?

Add the live security badge to your README. It updates with every re-scan.

Security grade badge for Email Client
[![Security: A — Skills Directory](https://www.skillsdirectory.com/api/skills/moeennehzati-email-client/badge)](https://www.skillsdirectory.com/skills/moeennehzati-email-client)

More formats (shields.io, HTML) on the badges page. Keep it an A: scan every change in CI with Pro.

Download with Pro
SKILL.md
---
name: email-client
description: >-
  Use when the user asks to access or manage email or a registered email account. Do not use when the primary request is inbox triage or shared Google authentication setup.
---

<!-- BEGIN BLUEPRINT INTERFACES -->
> Generated from `blueprint.yaml`. Do not edit this block by hand.

### Managed setup

When first exposed to this skill in a session, invoke `famulus_dispatcher.invoke_security_2` once with:

```json
{
  "caller": "email-client",
  "interface": "email-client.interface.setup",
  "version": 2,
  "arguments": {
    "positionals": [],
    "options": {},
    "stdin": null
  }
}
```

Do not repeat this initial call during the session. Obtain permission before carrying out setup, then follow the returned setup-manager instructions exactly. If the result is busy or failed, stop and report it.

Executable Interfaces:

Send the required `caller` (caller skill), `interface`, `version`, and `arguments`; optional `dry_run` defaults to false. Compact uses ordered `positionals` plus an option mapping; ordered raw argv uses `positionals: []` plus every argv token in list `options`. Never mix forms.
- `email-client._rtx.interface.accounts-add` — Register a new account nickname. Gmail IMAP/SMTP settings are the default; pass explicit host/port flags for other providers. App-password auth is the default; use --auth gmail-oauth for Gmail OAuth.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--auth": "app-password|gmail-oauth", "--display-name": "name", "--email": "addr", "--imap-host": "H", "--imap-port": "P", "--nickname": "nick", "--smtp-host": "H", "--smtp-port": "P", "--starttls": true}, "positionals": [], "stdin": null}
    Required options: ["--email", "--nickname"]; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.accounts-list` — List registered account nicknames with their email/display name (no secrets).
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {}, "positionals": [], "stdin": null}
    Required options: []; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.accounts-remove` — Remove an account nickname from the registry; optionally purge its stored credentials too.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--nickname": "nick", "--purge-credentials": true}, "positionals": [], "stdin": null}
    Required options: ["--nickname"]; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.accounts-set-password` — Store the IMAP or SMTP credential for an account in the host credential store. The secret is read from stdin, never a CLI argument.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--nickname": "nick", "--purpose": "imap|smtp"}, "positionals": [], "stdin": null}
    Required options: ["--nickname", "--purpose"]; positional arity: 0..0; stdin: permitted
- `email-client._rtx.interface.accounts-update` — Update fields on an existing account nickname.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--auth": "app-password|gmail-oauth", "--display-name": "name", "--email": "addr", "--imap-host": "H", "--imap-port": "P", "--nickname": "nick", "--smtp-host": "H", "--smtp-port": "P"}, "positionals": [], "stdin": null}
    Required options: ["--nickname"]; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.live-smoke` — Run explicit live provider smoke checks for one account. --imap and --smtp-auth authenticate without sending; --send-self sends a test email to the account's own address.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--body": "text", "--imap": true, "--send-self": true, "--smtp-auth": true, "-a": "nickname"}, "positionals": [], "stdin": null}
    Required options: ["-a"]; positional arity: 0..0; stdin: forbidden
  - Alternative: `long-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--body": "text", "--imap": true, "--send-self": true, "--smtp-auth": true}, "positionals": [], "stdin": null}
    Required options: ["--account"]; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.mail-attachments` — List attachment metadata for one or more emails as JSON. Returns one record per requested UID with attachment entries containing filename, content_type, size_bytes, size_human, and disposition.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--folder": "inbox|sent|drafts|trash|all|<literal>", "-a": "nickname"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["-a"]; positional arity: 1..unbounded; stdin: forbidden
  - Alternative: `long-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--folder": "inbox|sent|drafts|trash|all|<literal>"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["--account"]; positional arity: 1..unbounded; stdin: forbidden
- `email-client._rtx.interface.mail-folders` — List IMAP folders for an account (JSON).
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"-a": "nickname"}, "positionals": [], "stdin": null}
    Required options: ["-a"]; positional arity: 0..0; stdin: forbidden
  - Alternative: `long-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname"}, "positionals": [], "stdin": null}
    Required options: ["--account"]; positional arity: 0..0; stdin: forbidden
- `email-client._rtx.interface.mail-list` — List email envelopes for an account as JSON (fields: id, flags, subject, from, date, message_id). --folder accepts aliases inbox|sent|drafts|trash|all or any literal IMAP folder name (default inbox). --after narrows server-side by day (IMAP SINCE). Filters are key=value (exact, comma-separated=OR) or key~=value (regex, case-insensitive) over id/subject/from/date/message_id/flags, ANDed across distinct keys, applied client-side after fetch. Unfiltered + undated scans the whole folder (slow on large mailboxes) — pair filters with --after.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--after": "YYYY-MM-DD", "--folder": "inbox|sent|drafts|trash|all|<literal>", "--limit": "N", "-a": "nickname"}, "positionals": ["key=value|key~=value..."], "stdin": null}
    Required options: ["-a"]; positional arity: 0..unbounded; stdin: forbidden
  - Alternative: `long-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--after": "YYYY-MM-DD", "--folder": "inbox|sent|drafts|trash|all|<literal>", "--limit": "N"}, "positionals": ["key=value|key~=value..."], "stdin": null}
    Required options: ["--account"]; positional arity: 0..unbounded; stdin: forbidden
- `email-client._rtx.interface.mail-read` — Read one email by UID (the "id" field from mail-list). Prints Subject/From/To/ Date/Message-ID, then In-Reply-To/References only if the message is a reply, then an Attachments section (none or one line per attachment with filename, MIME type, and size), then a blank line, then the decoded body (text/plain preferred; falls back to HTML with tags stripped).
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--folder": "inbox|sent|drafts|trash|all|<literal>", "-a": "nickname"}, "positionals": ["uid"], "stdin": null}
    Required options: ["-a"]; positional arity: 1..1; stdin: forbidden
  - Alternative: `long-account`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--folder": "inbox|sent|drafts|trash|all|<literal>"}, "positionals": ["uid"], "stdin": null}
    Required options: ["--account"]; positional arity: 1..1; stdin: forbidden
- `email-client._rtx.interface.mail-save-attachments` — Save attachments from one or more emails into a directory. Use --all to save every attachment, or repeat --name to save only selected filenames. Returns JSON describing the saved files.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `short-account-all`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--all": true, "--folder": "inbox|sent|drafts|trash|all|<literal>", "--out": "dir", "-a": "nickname"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["--all", "--out", "-a"]; positional arity: 1..unbounded; stdin: forbidden
  - Alternative: `long-account-all`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--all": true, "--folder": "inbox|sent|drafts|trash|all|<literal>", "--out": "dir"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["--account", "--all", "--out"]; positional arity: 1..unbounded; stdin: forbidden
  - Alternative: `short-account-name`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--folder": "inbox|sent|drafts|trash|all|<literal>", "--name": "filename...", "--out": "dir", "-a": "nickname"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["--name", "--out", "-a"]; positional arity: 1..unbounded; stdin: forbidden
  - Alternative: `long-account-name`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--account": "nickname", "--folder": "inbox|sent|drafts|trash|all|<literal>", "--name": "filename...", "--out": "dir"}, "positionals": ["uid", "uid..."], "stdin": null}
    Required options: ["--account", "--name", "--out"]; positional arity: 1..unbounded; stdin: forbidden
- `email-client._rtx.interface.send-email` — Send an email via SMTP; body comes from stdin.
  - Caller: `email-client`
  - Version: 1
  - Security level: 2
  - Alternative: `owner`
    Arguments JSON (replace labels with actual values). Omit optional positionals and options that are not needed.
    {"options": {"--attach": "/path[:DisplayName]", "--from": "nickname", "--in-reply-to": "msg-id", "--references": "refs", "--subject": "subject", "--to": "addr..."}, "positionals": [], "stdin": null}
    Required options: ["--from", "--subject", "--to"]; positional arity: 0..0; stdin: permitted

Instruction Interfaces:

These are LLM-readable instruction surfaces. Read and follow them directly; do not invoke the MCP server for them.
- `connect-google.interface.default@1` — Route Google OAuth-client preparation according to whether a valid Desktop client is already installed.
<!-- END BLUEPRINT INTERFACES -->
# Email

Accounts are selected by registered nickname. If the nickname is unknown, invoke
`email-client._rtx.interface.accounts-list` and use its JSON result; do not infer an
account from an address or provider.

## Reading and attachments

Use `email-client._rtx.interface.mail-list` to obtain message UIDs and envelope metadata.
Prefer an `after` date when filtering a large folder because filtering without a date
may scan the entire folder. Folder aliases and the filter grammar are defined by the
interface contract.

Use `email-client._rtx.interface.mail-read` for a human-readable message. Use
`email-client._rtx.interface.mail-attachments` when structured attachment metadata is
needed, and `email-client._rtx.interface.mail-save-attachments` only when files should be
written. Use `email-client._rtx.interface.mail-folders` when the target folder is unknown.

## Sending and replies

Use `email-client._rtx.interface.send-email`; provide the body on stdin. For a reply, first
obtain the original `message_id` from `email-client._rtx.interface.mail-list`, pass it as
`in-reply-to`, and use a reply subject. Override `references` only when the caller has
the complete ancestor chain. To send local files, repeat `--attach` with an absolute
`/path[:DisplayName]` value. Attach only the files the user reviewed or requested.

## Managing accounts

Use `email-client._rtx.interface.accounts-list`, `email-client._rtx.interface.accounts-add`,
`email-client._rtx.interface.accounts-update`, and `email-client._rtx.interface.accounts-remove`
for registry changes. Use `email-client._rtx.interface.accounts-set-password` for
app-password credentials; the secret must be supplied on stdin and never as an
argument or ordinary configuration value.

For shared Google setup or Gmail reauthorization, first invoke
`connect-google.interface.default` with the selected registered nickname. Its
deterministic coordinator creates a credential file, asks Gmail's owner to probe
the account profile, and stores the path only after verification. Treat only
`complete: true` as successful setup; report an incomplete Gmail result and retry
through connect-google with the same file.

Existing legacy per-account Gmail OAuth credentials remain runtime-readable
until a verified credential-file binding replaces them. Do not offer legacy
setup as a new route.

## Live checks

Use `email-client._rtx.interface.live-smoke` for explicit provider checks. The IMAP and
SMTP-auth modes authenticate without sending. The send-self mode sends a real message
to the account's address, so invoke it only when the user requested a delivery check.

Files in this skill

  • SKILL.md14.7 KB
  • _rtx/__init__.py59 B
  • _rtx/_email_accounts.py19 KB
  • _rtx/_email_smoke.py4.8 KB
  • _rtx/_imap_gateway.py21.7 KB
  • _rtx/_oauth_tokens.py11.5 KB
  • _rtx/_smtp_transport.py8.4 KB
  • _rtx/blueprint.yaml5.4 KB
  • _rtx/blueprints/rtx-email-accounts.yaml53 KB
  • _rtx/blueprints/rtx-email-smoke.yaml8.4 KB
  • _rtx/blueprints/rtx-imap-gateway.yaml30.1 KB
  • _rtx/blueprints/rtx-init.yaml700 B
  • _rtx/blueprints/rtx-smtp-transport.yaml7.7 KB
  • _rtx/tests/test_accounts.py14.2 KB
  • _rtx/tests/test_gmail_credential_file_binding.py15.6 KB
  • _rtx/tests/test_mail.py19.8 KB
  • _rtx/tests/test_oauth_tokens.py6.9 KB
  • _rtx/tests/test_smoke.py2.6 KB
  • blueprint.yaml3.7 KB
  • blueprints/gateway.yaml4.8 KB

Attribution

Is this your skill, or is something wrong with this listing? Request removal or report an issue. Author removals are honored within 72 hours.

Comments

Loading comments…