Exchange On-Prem Skill
Overview
This skill provides EWS (SOAP) operations for on‑prem Exchange 2016 CU21: mail, folders, and calendar/meetings.
Requirements
- Node.js 20+ (22+ recommended)
- Exchange EWS endpoint:
/EWS/Exchange.asmx
Quick Start
- Install deps:
npm install
- Create encrypted config:
npm run setup-config -- \
--exchange-url https://mail.example.com/EWS/Exchange.asmx \
--username user \
--auth-mode ntlm \
--password "<password>" \
--master-key "<masterKey>"
- Verify:
npm run verify-login
Safety Policy
- Read-first by default
- Any write operation requires explicit confirmation
- Write commands require
--confirm true(orEXCHANGE_WRITE_CONFIRM=true) --dry-runis supported for write commands to preview SOAP body--insecure true(if used) only relaxes TLS validation per request and does not change global Node TLS settings
Config Model
File: config/exchange.config.json
Required fields: exchange_url, username, auth_mode, secret_store
Optional: domain
Capability Groups & Status
Status:
READY: implemented and verifiedRESTRICTED: write/risky actions require explicit confirmationLIMITED: implemented but blocked by environment limitations
A) Mailbox & Items
FindItem(mail list/read window):READYSearchMail(keyword in subject/body/recipients):READYGetItem:READYGetUnreadCount:READYCreateItem(mail create):READYRESTRICTEDUpdateItem:READYRESTRICTEDMoveItem / CopyItem / DeleteItem:READYRESTRICTEDSendItem:READYRESTRICTEDReplyItem / ReplyAll:READYRESTRICTEDMarkAllItemsAsRead:READYRESTRICTEDArchiveItem:LIMITEDRESTRICTED
B) Folders
GetFolder:READYFindFolder:READYCreateFolder:READYRESTRICTEDUpdateFolder:READYRESTRICTEDDeleteFolder:READYRESTRICTED
C) Calendar & Meetings
- Calendar window read (
FindItem + CalendarView):READY - Create meeting (
CreateItemCalendarItem):READYRESTRICTED
D) Structure & Config
exchange.config.jsoncreate/update:READY- Scripts organized by module folders:
READY - SKILL.md commands and status updated:
READY
Defaults That Matter
get-mail/search-maildefault scope isall(msgfolderroot).get-mail/search-maildefault includes subfolders of the scope.get-mail/search-maildefault time window is last 3650 days. Use--days-backto narrow.get-calendardefault time window is next 7 days. Use--start-time/--end-timeto override.
Command List
Read commands:
npm run verify-loginnpm run get-mail -- --unread-only --limit 10npm run get-mail -- --scope all --limit 10(all folders under msgfolderroot)npm run get-mail -- --scope all --days-back 3650 --limit 10npm run search-mail -- --query "keyword" --limit 10npm run search-mail -- --scope all --query "keyword" --limit 10npm run get-item -- --item-id <EWS_ITEM_ID>npm run get-unread-count -- --scope all(all folders under msgfolderroot)npm run get-folder -- --distinguished-id inboxnpm run find-folder -- --parent-distinguished-id msgfolderroot --traversal Shallow --limit 50npm run get-calendar -- --limit 20npm run get-calendar -- --start-time 2026-03-01T00:00:00+08:00 --end-time 2026-05-01T00:00:00+08:00 --limit 200
Write commands (require confirm):
npm run create-mail -- --confirm true --to a@b.com --subject "s" --body "b"npm run reply-item -- --confirm true --item-id <id> --body "thanks"(supports--reply-all true)npm run update-item -- --confirm true --item-id <id> --subject "new"(auto-fetches ChangeKey if omitted)npm run mark-all-read -- --confirm true --distinguished-id inboxnpm run create-folder -- --confirm true --display-name "My Folder" --parent-distinguished-id inboxnpm run update-folder -- --confirm true --folder-id <id> --change-key <ck> --display-name "New Name"npm run delete-folder -- --confirm true --folder-id <id> --delete-type MoveToDeletedItemsnpm run move-item -- --confirm true --item-id <id> --target-distinguished-id inboxnpm run copy-item -- --confirm true --item-id <id> --target-distinguished-id draftsnpm run delete-item -- --confirm true --item-id <id> --delete-type MoveToDeletedItemsnpm run send-item -- --confirm true --item-id <draftId>npm run send-item -- --confirm true --item-id <draftId> --change-key <ck>(recommended; send will auto-fetch ChangeKey if omitted)npm run archive-item -- --confirm true --item-id <id>npm run create-meeting -- --confirm true --subject "Weekly Sync" --start "2026-03-18T09:00:00+08:00" --end "2026-03-18T09:30:00+08:00" --required a@b.com --location "Room A" --body "Agenda" --send-invitations SendToAllAndSaveCopy
Send receipt verification:
create-mail,reply-item,send-itemsupport--verify-sent true|false,--verify-window-minutes <n>,--verify-max-entries <n>,--verify-strict true|false