microsoft-365-graph-openclaw

Microsoft 365 Graph for OpenClaw with webhook-based wake signals. Reduce recurring LLM cost from inbox polling while managing Outlook mail, calendar, OneDrive, and contacts via Microsoft Graph.

Safety Notice

This listing is from the official public ClawHub registry. Review SKILL.md and referenced scripts before running.

Copy this and send it to your AI assistant to learn

Install skill "microsoft-365-graph-openclaw" with this command: npx skills add draeden79/microsoft-365-graph-openclaw

Microsoft 365 Graph for OpenClaw Skill

1. Quick prerequisites

  1. Python 3 with requests installed.
  2. Default auth values:
    • Client ID (personal-account default): 952d1b34-682e-48ce-9c54-bac5a96cbd42
    • Tenant (personal-account default): consumers
    • Default scopes: Mail.ReadWrite Mail.Send Calendars.ReadWrite Files.ReadWrite.All Contacts.ReadWrite offline_access
    • For work/school accounts, use --tenant-id organizations (or tenant GUID) and a tenant-approved --client-id.
    • The public default client ID is for quick testing. For production, prefer your own App Registration.
  3. Tokens are stored in state/graph_auth.json (ignored by git).
  4. Required runtime envs for push mode:
    • OPENCLAW_HOOK_URL
    • OPENCLAW_HOOK_TOKEN
    • GRAPH_WEBHOOK_CLIENT_STATE
    • OPENCLAW_SESSION_KEY

Permission profiles (least privilege by use case) are documented in docs/permission-profiles.md.

2. Assisted OAuth flow (Device Code)

  1. Run:
    python scripts/graph_auth.py device-login \
      --client-id 952d1b34-682e-48ce-9c54-bac5a96cbd42 \
      --tenant-id consumers
    
  2. The script prints a URL and device code.
  3. Open https://microsoft.com/devicelogin, enter the code, and approve with the target account.
  4. Check and manage auth state:
    • python scripts/graph_auth.py status
    • python scripts/graph_auth.py refresh
    • python scripts/graph_auth.py clear
  5. Other scripts call utils.get_access_token(), which refreshes tokens automatically when needed.
  6. Scope override is disabled in graph_auth.py; the skill always uses DEFAULT_SCOPES.

Detailed reference: references/auth.md.

3. Email operations

  • List/filter: python scripts/mail_fetch.py --folder Inbox --top 20 --unread
  • Fetch specific message: ... --id <messageId> --include-body --mark-read
  • Move message: add --move-to <folderId> to the command above.
  • Send email (saveToSentItems enabled by default):
    python scripts/mail_send.py \
      --to user@example.com \
      --subject "Update" \
      --body-file replies/thais.html --html \
      --cc teammate@example.com \
      --attachment docs/proposal.pdf
    
  • Use --no-save-copy only when you intentionally do not want Sent Items storage.

More examples and filters: references/mail.md.

4. Calendar operations

  • List custom date window:
    python scripts/calendar_sync.py list \
      --start 2026-03-03T00:00Z --end 2026-03-05T23:59Z --top 50
    
  • Create Teams or in-person event: use create; add --online for Teams link.
  • For personal Microsoft accounts (tenant=consumers), Teams meeting provisioning via Graph might not return a join URL; create the Teams meeting in Outlook/Teams first and add the resulting link to the event body when needed.
  • Update/cancel events by event_id returned in JSON output.

Full examples: references/calendar.md.

5. OneDrive / Files

  • List folders/files: python scripts/drive_ops.py list --path /
  • Upload: ... upload --local notes/briefing.docx --remote /Clients/briefing.docx
  • Download: ... download --remote /Clients/briefing.docx --local /tmp/briefing.docx
  • Move / share links: use move and share subcommands.
  • The script resolves localized/special-folder aliases (for example Documents and Documentos).

More details: references/drive.md.

6. Contacts

  • List/search: python scripts/contacts_ops.py list --top 20
  • Create: ... create --given-name Jane --surname Doe --email jane.doe@example.com
  • Update/Delete: ... update <contactId> ... / ... delete <contactId>
  • Contacts are part of the default scope set and supported as a first-class workflow.

More details: references/contacts.md.

7. Mail push mode (Webhook Adapter)

  • Adapter server (Graph handshake + clientState validation + enqueue):
    python scripts/mail_webhook_adapter.py serve \
      --host 0.0.0.0 --port 8789 --path /graph/mail \
      --client-state "$GRAPH_WEBHOOK_CLIENT_STATE"
    
  • Subscription lifecycle (create/status/renew/delete/list):
    python scripts/mail_subscriptions.py create \
      --notification-url "https://graph-hook.example.com/graph/mail" \
      --client-state "$GRAPH_WEBHOOK_CLIENT_STATE" \
      --minutes 4200
    
    • Default resource is me/messages (recommended for better delivery coverage). Override with --resource only for advanced/scoped scenarios.
  • Async worker (dedupe + default wake signal to OpenClaw /hooks/wake):
    python scripts/mail_webhook_worker.py loop \
      --session-key "$OPENCLAW_SESSION_KEY" \
      --hook-url "$OPENCLAW_HOOK_URL" \
      --hook-token "$OPENCLAW_HOOK_TOKEN"
    
    • Default mode is wake (/hooks/wake, mode=now). Use --hook-action agent only when you explicitly need per-message rich payload delivery.
  • Worker queue files:
    • state/mail_webhook_queue.jsonl
    • state/mail_webhook_dedupe.json
  • Automated EC2 bootstrap (Caddy + systemd + renew timer):
    sudo bash scripts/setup_mail_webhook_ec2.sh \
      --domain graphhook.example.com \
      --hook-url http://127.0.0.1:18789/hooks/wake \
      --hook-token "<OPENCLAW_HOOK_TOKEN>" \
      --session-key "hook:graph-mail" \
      --client-state "<GRAPH_WEBHOOK_CLIENT_STATE>" \
      --repo-root "$(pwd)"
    
    • Use --dry-run to preview all privileged writes and service actions before applying changes.
  • One-command setup (steps 2..6):
    sudo bash scripts/run_mail_webhook_e2e_setup.sh \
      --domain graphhook.example.com \
      --hook-token "<OPENCLAW_HOOK_TOKEN>" \
      --hook-url "http://127.0.0.1:18789/hooks/wake" \
      --session-key "hook:graph-mail" \
      --test-email "tar.alitar@outlook.com"
    
    • Use --dry-run for a no-mutation execution plan (no /etc writes, no systemctl, no subscription create, no email send).
    • Output ends with READY_FOR_PUSH: YES when setup is fully validated.
  • Include OpenClaw hook config in automation:
    sudo bash scripts/run_mail_webhook_e2e_setup.sh \
      --domain graphhook.example.com \
      --hook-token "<OPENCLAW_HOOK_TOKEN>" \
      --configure-openclaw-hooks \
      --openclaw-config "/home/ubuntu/.openclaw/openclaw.json" \
      --openclaw-service-name "auto" \
      --openclaw-hooks-path "/hooks" \
      --openclaw-allow-request-session-key true \
      --test-email "tar.alitar@outlook.com"
    
  • Minimal-input smoke tests:
    sudo bash scripts/run_mail_webhook_smoke_tests.sh \
      --domain graphhook.example.com \
      --create-subscription \
      --test-email tar.alitar@outlook.com
    
    • Output ends with READINESS VERDICT: READY_FOR_PUSH only after all critical checks pass.
  • Setup and runbook: references/mail_webhook_adapter.md.

8. Privileged operations boundary

The core Graph scripts are unprivileged (graph_auth.py, mail_fetch.py, mail_send.py, calendar_sync.py, drive_ops.py, contacts_ops.py).

The setup scripts below are privileged and should be manually reviewed before execution:

  • scripts/setup_mail_webhook_ec2.sh
  • scripts/run_mail_webhook_e2e_setup.sh

When run without --dry-run, they can:

  • Write /etc/default/graph-mail-webhook
  • Write /etc/caddy/Caddyfile
  • Write /etc/systemd/system/*.service and *.timer
  • Enable/restart services via systemctl
  • Optionally patch OpenClaw config and restart OpenClaw services

Recommended safety sequence:

  1. Run with --dry-run
  2. Review emitted actions and target files
  3. Run on a non-production host first
  4. Apply to production only after approval

9. Logging and conventions

  • Each script appends one JSON line to state/graph_ops.log with timestamp, action, and key parameters.
  • Tokens and logs must never be committed.
  • Commands assume execution from the repository root. Adjust paths if running elsewhere.

10. Troubleshooting

SymptomAction
401/invalid_grantRun graph_auth.py refresh; if it fails, run clear and repeat device login.
403/AccessDeniedMissing scope or licensing/policy issue. Re-run device login with required scope(s).
429/ThrottledScripts do basic retry; wait a few seconds and retry.
requests.exceptions.SSLErrorVerify local system date/time and TLS trust chain.

This skill provides OAuth-driven workflows for email, calendar, files, contacts, and push-based mail automation via Microsoft Graph.

Source Transparency

This detail page is rendered from real SKILL.md content. Trust labels are metadata-based hints, not a safety guarantee.

Related Skills

Related by shared tags or category signals.

General

Sendflare

通过 Sendflare SDK 发送带附件的电子邮件,管理联系人列表,支持 CC/BCC 和安全 API 认证。

Registry SourceRecently Updated
General

Playtomic - Book courts using padel-tui

This skill should be used when the user asks to "book a padel court", "find available padel courts", "search padel courts near me", "reserve a Playtomic cour...

Registry SourceRecently Updated
General

Fund Keeper

国内场外基金智能顾问 + 股票行情查询。实时估值、买卖建议、收益统计、定投计划、OCR 识图、股票 - 基金联动。支持离线模式、多数据源缓存。

Registry SourceRecently Updated