Install
$ agentstack add skill-alexjmoore8-claude-code-tools-send-o365-email ✓ scanned · ✓ verified, works with Claude Code, Cursor, and more.
Security review
✓ PassedNo issues found. Passed automated security review. · v0.1.0 How review works →
- ✓ Prompt-injection patterns
- ✓ Secret / credential exfiltration
- ✓ Dangerous shell & filesystem operations
- ✓ Untrusted network calls
- ✓ Known-malicious package signatures
What it can access
- ● Network access Used
- ✓ Filesystem access No
- ✓ Shell / process execution No
- ✓ Environment & secrets No
- ✓ Dynamic code execution No
From automated source analysis of v0.1.0. “Used” means the capability is present in the source — more access means more to trust, not that it’s unsafe.
Verified badge
Passed review? Show it. Paste this badge into your README, it links to the public security report.
Reliability & compatibility
Declared compatibility
Compatibility is declared by the source manifest. End-to-end runtime verification is coming, see below.
We're building live execution health for every listing: tool-call success rate, median latency, uptime, and last-checked timestamps, measured, not self-reported. It isn't live yet, so we don't show numbers we can't stand behind.
How agent discovery & health will work →About
Send email from your O365 account via Microsoft Graph API. No dependencies -- uses only curl, awk, grep, and standard POSIX tools pre-installed on Mac, Linux, WSL, and Git Bash.
Configuration
TENANT_ID=YOUR_TENANT_ID
CLIENT_ID=YOUR_CLIENT_ID
TOKEN_PATH=~/.config/claude-o365/token.json
SKILL_DIR=~/.claude/skills/send-o365-email
Set O365_TENANT_ID and O365_CLIENT_ID as environment variables, or edit the values directly in auth.sh. See the README for Azure app registration instructions.
Usage
/send-o365-email [--to ] [--cc ] [--subject ] [--body ] [--attach ...]
All arguments optional -- ask for any missing required fields (to, subject, body) before proceeding. If the user says "send to myself", use send.sh --me to resolve their address. --to and --cc accept comma-separated addresses.
Workflow
Step 0: Ensure permissions
Use the Read tool to read ~/.claude/settings.json (it may not exist yet).
Check whether ALL of these are present in permissions.allow:
"Skill(send-o365-email)"
"Bash(~/.claude/skills/send-o365-email/auth.sh*)"
"Bash(~/.claude/skills/send-o365-email/send.sh*)"
"Bash(chmod +x ~/.claude/skills/send-o365-email/*.sh)"
If any are missing, present the following to the user and ask if they want to proceed:
> One-time permission setup for send-o365-email > > To run headlessly (e.g. for automation or scheduled sends), this skill needs to add the following entries to your ~/.claude/settings.json: > > | Permission | What it allows | > |---|---| > | Skill(send-o365-email) | Trust this skill to run | > | Bash(~/.claude/skills/send-o365-email/auth.sh*) | Run the auth script | > | Bash(~/.claude/skills/send-o365-email/send.sh*) | Run the send script | > | Bash(chmod +x ~/.claude/skills/send-o365-email/*.sh) | Make scripts executable on first run | > > Pros: Fully headless after this -- no more prompts, works in automation and cron jobs. Permissions are narrowly scoped to this skill's scripts only. > Cons: These are added to your global ~/.claude/settings.json and apply to all Claude sessions (due to a known Claude Code bug where skill-level permissions aren't enforced). > > Want to add these permissions? (yes/no) > - Yes: permissions added, restart Claude Code, all future runs are headless > - No: skill still works, but you'll see approval prompts each run
If the user says yes, add all missing entries to the allow array (preserving all existing content) and write the file back with the Write tool. Tell the user: "Done -- please restart Claude Code. All future runs of this skill will be fully headless." Then stop -- do not proceed until they restart.
If the user says no, continue. They will see prompts this run -- that is fine.
If the file doesn't exist and user says yes, create it:
{
"permissions": {
"allow": [
"Skill(send-o365-email)",
"Bash(~/.claude/skills/send-o365-email/auth.sh*)",
"Bash(~/.claude/skills/send-o365-email/send.sh*)",
"Bash(chmod +x ~/.claude/skills/send-o365-email/*.sh)"
]
}
}
Continue to Step 1.
Step 1: Ensure scripts are executable
chmod +x ~/.claude/skills/send-o365-email/*.sh
Step 2: Check existing token
~/.claude/skills/send-o365-email/auth.sh check
TOKEN_VALID-- skip to Step 4NEEDS_REFRESH-- go to Step 3bNEEDS_AUTH-- go to Step 3a
Step 3a: Authenticate -- Device Code Flow
First, request the device code (returns immediately):
~/.claude/skills/send-o365-email/auth.sh device-start
This prints:
VISIT_URL:https://microsoft.com/devicelogin
USER_CODE:XXXXXXXX
Immediately tell the user: "Go to [VISITURL] and enter code [USERCODE] to sign in. Then say 'done' when complete."
Wait for the user to confirm they have signed in, then poll for the token (use a timeout of 300000ms):
~/.claude/skills/send-o365-email/auth.sh device-poll
On TOKEN_SAVED, continue to Step 4. On error, report to user.
Step 3b: Refresh token
~/.claude/skills/send-o365-email/auth.sh refresh
On TOKEN_SAVED, continue to Step 4. On REFRESH_FAILED, fall back to Step 3a.
Step 4: Resolve "myself" / "me" recipients
If the user said "send to myself" or similar:
~/.claude/skills/send-o365-email/send.sh --me
Use the printed address as the recipient.
Step 5: Send the email
~/.claude/skills/send-o365-email/send.sh --to "ADDR" --subject "SUBJECT" --body "BODY"
Add --cc "ADDR" if CC was provided. Add --attach "/path/to/file" for each attachment (repeat the flag).
For attachments: pass the path directly to --attach. The script handles Unicode spaces automatically (e.g. macOS screenshot filenames use U+202F between the time and AM/PM).
If the user drops an image into the chat, the source path is in the [Image: source: /path/to/file] metadata -- use that path directly with --attach.
Outputs:
SENT= success, proceed to Step 6TOKEN_EXPIRED= go to Step 3b, then retry Step 5ERROR:...= report to user
Step 6: Report result
Tell the user the email was sent, the recipient(s), and the current timestamp.
Notes
- Sends from your own O365 inbox -- always the authenticated account
- Token stored at
~/.config/claude-o365/token.json(chmod 600), same security model as AWS CLI - Access token valid ~1hr; refresh token ~90 days; subsequent sends are headless
- No dependencies beyond
curland standard POSIX tools (pre-installed on Mac/Linux/WSL/Git Bash) - Scripts live in the skill directory and are executed in place -- no copying needed
Source & license
This open-source skill is cataloged on AgentStack and links to its original source — we do not rehost the code.
- Author: alexjmoore8
- Source: alexjmoore8/claude-code-tools
- License: MIT
Install and usage instructions live in the source repository linked above.
Reviews
No reviews yet, be the first.
Write a review
Versions
- v0.1.0 Imported from the upstream source.