Full access to Exchange 2010 EWS for managing emails, folders, attachments, calendar events, contacts, tasks, and out-of-office settings.
# exchange2010
Exchange 2010 EWS integration for emails, calendar, contacts, and tasks.
## Setup
Requires credentials in `.env.credentials`:
```
EXCHANGE_SERVER=mail.company.com
EXCHANGE_DOMAIN=company
EXCHANGE_EMAIL=user@company.com
EXCHANGE_PASSWORD=your_password
```
## Features
- ✅ **Email**: Read unread, send, search, mark as read
- ✅ **Email Attachments**: Download, extract text (PDF, TXT)
- ✅ **Email Folders**: Browse Sent, Drafts, Trash, Junk
- ✅ **Calendar**: View, create, update, delete, search events
- ✅ **Recurring Events**: Detect and manage series
- ✅ **Shared Calendars**: Access other Exchange mailboxes
- ✅ **Contacts**: Search address book, resolve names (GAL)
- ✅ **Tasks/To-Do**: Manage, create, complete tasks
- ✅ **Out-of-Office**: Read and set absence messages
- ✅ **EWS Filters**: Fast search with `subject__contains`, `start__gte`, etc.
- ✅ **List Calendars**: Show all calendar folders
## Examples
### Read Emails
```python
from skills.exchange2010 import get_account, get_unread_emails
account = get_account()
emails = get_unread_emails(account, limit=10)
for email in emails:
print(f"{email['subject']} from {email['sender']}")
```
### Today's Events
```python
from skills.exchange2010 import get_today_events
# Your own events
today = get_today_events()
# Events from shared calendar
today = get_today_events('shared@company.com')
```
### Search Events
```python
from skills.exchange2010 import search_calendar_by_subject
from datetime import date
# Fast search for Ekadashi
ekadashi = search_calendar_by_subject(
email_address='shared@company.com',
search_term='Ekadashi',
start_date=date(2025, 1, 1),
end_date=date(2026, 12, 31)
)
print(f"Found: {len(ekadashi)} events")
```
### Create Event
```python
from skills.exchange2010 import create_calendar_event
from datetime import datetime
create_calendar_event(
subject="Team Meeting",
start=datetime(2026, 2, 7, 14, 0),
end=datetime(2026, 2, 7, 15, 0),
body="Project discussion",
location="Conference Room A"
)
```
### Update Event
```python
from skills.exchange2010 import update_calendar_event
from datetime import datetime
# Reschedule
update_calendar_event(
event_id='AAQkAG...',
start=datetime(2026, 2, 10, 14, 0),
end=datetime(2026, 2, 10, 15, 0),
location="New Room B"
)
```
### Browse Email Folders
```python
from skills.exchange2010 import get_folder_emails, list_email_folders
# List all folders
folders = list_email_folders(account)
for f in folders:
print(f"{f['name']}: {f['unread_count']} unread")
# Sent Items
sent = get_folder_emails('sent', limit=10)
# Drafts
drafts = get_folder_emails('drafts')
# Trash
trash = get_folder_emails('trash')
```
### Search Emails
```python
from skills.exchange2010 import search_emails
# By sender
emails = search_emails(sender='boss@company.com', limit=10)
# By subject
emails = search_emails(subject='Invoice', folder='inbox')
# Unread only
emails = search_emails(is_unread=True, limit=20)
```
### Mark Email as Read
```python
from skills.exchange2010 import mark_email_as_read
mark_email_as_read(email_id='AAQkAG...')
```
### Download Attachments
```python
from skills.exchange2010 import get_email_attachments
# Show info
attachments = get_email_attachments(email_id='AAQkAG...')
for att in attachments:
print(f"{att['name']}: {att['size']} bytes")
# Download
attachments = get_email_attachments(
email_id='AAQkAG...',
download_path='/tmp/email_attachments'
)
```
### Extract Text from Attachments
**Prerequisite**: `pip install PyPDF2` for PDF text extraction
```python
from skills.exchange2010 import process_attachment_content
results = process_attachment_content(email_id='AAQkAG...')
for result in results:
print(f"File: {result['name']}")
if 'extracted_text' in result:
print(f"Content: {result['extracted_text'][:500]}...")
```
### Search Contacts
```python
from skills.exchange2010 import search_contacts, resolve_name
# Search contacts
contacts = search_contacts('John Doe')
for c in contacts:
print(f"{c['name']}: {c['email']}")
# Resolve name (GAL)
result = resolve_name('john.doe@company.com')
if result:
print(f"Found: {result['name']} - {result['email']}")
```
### Manage Tasks
```python
from skills.exchange2010 import get_tasks, create_task, complete_task, delete_task
from datetime import datetime, timedelta
# Show open tasks
tasks = get_tasks()
for task in tasks:
status = '✅' if task['is_complete'] else '⏳'
print(f"{status} {task['subject']}")
# Create new task
task_id = create_task(
subject="Finish report",
body="Q1 report due Friday",
due_date=datetime.now() + timedelta(days=3),
importance="High"
)
# Mark as complete
complete_task(task_id)
# Delete
delete_task(task_id)
```
### Find Recurring Events
```python
from skills.exchange2010 import get_recurring_events
recurring = get_recurring_events(
email_address='shared@company.com',
days=30
)
for r in recurring:
print(f"{r['subject']}: {r['recurrence']}")
```
### Out-of-Office
```python
from skills.exchange2010 import get_out_of_office, set_out_of_office
from datetime import datetime, timedelta
# Check status
oof = get_out_of_office()
print(f"Out of office active: {oof['enabled']}")
# Enable
set_out_of_office(
enabled=True,
internal_reply="I am on vacation until Feb 15th.",
external_reply="I am on vacation until Feb 15th.",
start=datetime.now(),
end=datetime.now() + timedelta(days=7),
external_audience='All' # 'All', 'Known', 'None'
)
# Disable
set_out_of_office(enabled=False, internal_reply="")
```
### Send Email
```python
from skills.exchange2010 import send_email
send_email(
to=["recipient@example.com"],
subject="Test",
body="Hello!",
cc=["cc@example.com"]
)
```
## API Reference
### Email
| Function | Description |
|----------|-------------|
| `get_account()` | Connect to Exchange |
| `get_unread_emails(account, limit=50)` | Get unread emails |
| `search_emails(search_term, sender, subject, is_unread, folder, limit)` | Search emails |
| `send_email(to, subject, body, cc, bcc)` | Send email |
| `mark_email_as_read(email_id)` | Mark as read |
| `get_email_attachments(email_id, download_path)` | Download attachments |
| `process_attachment_content(email_id, attachment_name)` | Extract text |
### Email Folders
| Function | Description |
|----------|-------------|
| `get_folder_emails(folder_name, limit, is_unread)` | Emails from folder |
| `list_email_folders(account)` | List all folders |
### Calendar
| Function | Description |
|----------|-------------|
| `get_today_events(email_address)` | Today's events |
| `get_upcoming_events(email_address, days)` | Next N days |
| `get_calendar_events(account, start, end)` | Events in range |
| `get_shared_calendar_events(email, start, end)` | Shared calendar |
| `search_calendar_by_subject(email, term, start, end)` | Fast search |
| `create_calendar_event(subject, start, end, body, location)` | Create event |
| `update_calendar_event(event_id, ...)` | Update event |
| `get_event_details(event_id)` | Show details |
| `delete_calendar_event(event_id)` | Delete event |
| `get_recurring_events(email, start, end)` | Recurring events |
| `list_available_calendars(account)` | List calendars |
| `count_ekadashi_events(email, start_year)` | Count Ekadashi |
### Contacts
| Function | Description |
|----------|-------------|
| `search_contacts(search_term, limit)` | Search contacts |
| `resolve_name(name)` | Resolve name (GAL) |
### Tasks
| Function | Description |
|----------|-------------|
| `get_tasks(status, folder)` | Get tasks |
| `create_task(subject, body, due_date, importance, categories)` | Create task |
| `complete_task(task_id)` | Mark complete |
| `delete_task(task_id)` | Delete task |
### Out-of-Office
| Function | Description |
|----------|-------------|
| `get_out_of_office(email_address)` | Read status |
| `set_out_of_office(enabled, internal_reply, ...)` | Set OOF |
## Notes
- **Exchange 2010 SP2** explicitly used as version
- **DELEGATE** access type for own and shared mailboxes
- **EWS Filters** (`subject__contains`, `start__gte`) are faster than iteration
- **Timezones**: Automatic conversion to EWSDateTime with UTC
- **27 functions** available in total
don't have the plugin yet? install it then click "run inline in claude" again.