Microsoft 365 & Microsoft Graph Library for Python
—
Quality
Pending
Does it follow best practices?
Impact
Pending
No eval scenarios have been run
Outlook integration for email, calendar, contacts, and mailbox management through Microsoft Graph API with comprehensive messaging capabilities. Provides complete communication and scheduling functionality for Microsoft 365 environments.
Comprehensive email operations including message composition, sending, receiving, organizing, and attachment management with support for rich content and advanced features.
class Message:
"""Outlook email message with comprehensive content and management capabilities."""
# Core Properties
id: str
created_date_time: str
last_modified_date_time: str
change_key: str
categories: List[str]
received_date_time: str
sent_date_time: str
has_attachments: bool
internet_message_id: str
subject: str
body_preview: str
importance: str # "low", "normal", "high"
inference_classification: str
is_delivery_receipt_requested: bool
is_draft: bool
is_read: bool
is_read_receipt_requested: bool
web_link: str
def get(self) -> 'Message':
"""
Retrieve message information and content.
Returns:
Message: Updated message object
"""
def update(self) -> 'Message':
"""
Update message properties.
Returns:
Message: Updated message object
"""
def delete(self) -> None:
"""Delete message (move to Deleted Items)."""
def send(self) -> None:
"""Send draft message."""
def reply(self, comment: str = None) -> 'Message':
"""
Create reply to message.
Args:
comment (str, optional): Reply comment
Returns:
Message: Reply message draft
"""
def reply_all(self, comment: str = None) -> 'Message':
"""
Create reply-all to message.
Args:
comment (str, optional): Reply comment
Returns:
Message: Reply-all message draft
"""
def forward(self, comment: str = None, to_recipients: List[Dict[str, str]] = None) -> 'Message':
"""
Create forward of message.
Args:
comment (str, optional): Forward comment
to_recipients (List[Dict], optional): Forward recipients
Returns:
Message: Forward message draft
"""
def copy(self, destination_id: str) -> 'Message':
"""
Copy message to folder.
Args:
destination_id (str): Destination folder ID
Returns:
Message: Copied message
"""
def move(self, destination_id: str) -> 'Message':
"""
Move message to folder.
Args:
destination_id (str): Destination folder ID
Returns:
Message: Moved message
"""
# Navigation Properties
@property
def body(self) -> 'ItemBody':
"""Message body content."""
@property
def from_(self) -> 'Recipient':
"""Message sender."""
@property
def sender(self) -> 'Recipient':
"""Message sender (may differ from from_ for delegates)."""
@property
def to_recipients(self) -> List['Recipient']:
"""Primary recipients."""
@property
def cc_recipients(self) -> List['Recipient']:
"""CC recipients."""
@property
def bcc_recipients(self) -> List['Recipient']:
"""BCC recipients."""
@property
def reply_to(self) -> List['Recipient']:
"""Reply-to recipients."""
@property
def attachments(self) -> 'AttachmentCollection':
"""Message attachments."""
@property
def extensions(self) -> 'ExtensionCollection':
"""Message extensions."""
class MessageCollection:
"""Collection of email messages with query and management capabilities."""
def get(self) -> 'MessageCollection':
"""Retrieve collection of messages."""
def filter(self, expression: str) -> 'MessageCollection':
"""
Filter messages by OData expression.
Args:
expression (str): OData filter expression
Returns:
MessageCollection: Filtered collection
"""
def select(self, properties: List[str]) -> 'MessageCollection':
"""
Select specific properties to retrieve.
Args:
properties (List[str]): Property names to select
Returns:
MessageCollection: Collection with selected properties
"""
def top(self, count: int) -> 'MessageCollection':
"""
Limit results to top N messages.
Args:
count (int): Maximum number of messages
Returns:
MessageCollection: Limited collection
"""
def order_by(self, property_name: str, ascending: bool = True) -> 'MessageCollection':
"""
Sort messages by property.
Args:
property_name (str): Property to sort by
ascending (bool): Sort direction
Returns:
MessageCollection: Sorted collection
"""
def get_by_id(self, message_id: str) -> Message:
"""
Get message by ID.
Args:
message_id (str): Message unique identifier
Returns:
Message: Message object
"""
def add(self, message_info: Dict[str, Any]) -> Message:
"""
Create new message (draft).
Args:
message_info (Dict): Message properties
Returns:
Message: Created message draft
"""
def send_mail(self, message: Dict[str, Any], save_to_sent_items: bool = True) -> None:
"""
Send message directly without creating draft.
Args:
message (Dict): Message content and recipients
save_to_sent_items (bool): Save copy to Sent Items
"""Email folder organization with support for custom folders, folder hierarchy, and message organization rules.
class MailFolder:
"""Outlook mail folder with comprehensive message organization capabilities."""
# Core Properties
id: str
display_name: str
parent_folder_id: str
child_folder_count: int
unread_item_count: int
total_item_count: int
size_in_bytes: int
is_hidden: bool
def get(self) -> 'MailFolder':
"""
Retrieve folder information.
Returns:
MailFolder: Updated folder object
"""
def update(self) -> 'MailFolder':
"""
Update folder properties.
Returns:
MailFolder: Updated folder object
"""
def delete(self) -> None:
"""Delete folder and all contents."""
def copy(self, destination_id: str) -> 'MailFolder':
"""
Copy folder to destination.
Args:
destination_id (str): Destination folder ID
Returns:
MailFolder: Copied folder
"""
def move(self, destination_id: str) -> 'MailFolder':
"""
Move folder to destination.
Args:
destination_id (str): Destination folder ID
Returns:
MailFolder: Moved folder
"""
# Navigation Properties
@property
def messages(self) -> MessageCollection:
"""Messages in the folder."""
@property
def child_folders(self) -> 'MailFolderCollection':
"""Child folders."""
@property
def message_rules(self) -> 'MessageRuleCollection':
"""Message rules for the folder."""
class MailFolderCollection:
"""Collection of mail folders with management capabilities."""
def get(self) -> 'MailFolderCollection':
"""Retrieve collection of folders."""
def filter(self, expression: str) -> 'MailFolderCollection':
"""
Filter folders by expression.
Args:
expression (str): OData filter expression
Returns:
MailFolderCollection: Filtered collection
"""
def get_by_id(self, folder_id: str) -> MailFolder:
"""
Get folder by ID.
Args:
folder_id (str): Folder unique identifier
Returns:
MailFolder: Folder object
"""
def add(self, folder_info: Dict[str, Any]) -> MailFolder:
"""
Create new folder.
Args:
folder_info (Dict): Folder properties
Returns:
MailFolder: Created folder
"""Comprehensive calendar functionality including event creation, scheduling, meeting management, and calendar sharing with support for recurring events and attendee management.
class Calendar:
"""Outlook calendar with comprehensive scheduling and event management."""
# Core Properties
id: str
name: str
color: str
change_key: str
can_share: bool
can_view_private_items: bool
can_edit: bool
allowed_online_meeting_providers: List[str]
default_online_meeting_provider: str
is_tale_enabled: bool
is_removable: bool
def get(self) -> 'Calendar':
"""
Retrieve calendar information.
Returns:
Calendar: Updated calendar object
"""
def update(self) -> 'Calendar':
"""
Update calendar properties.
Returns:
Calendar: Updated calendar object
"""
def delete(self) -> None:
"""Delete calendar."""
def get_schedule(self, schedules: List[str], start_time: str, end_time: str, availability_view_interval: int = 60) -> List[Dict[str, Any]]:
"""
Get free/busy information for specified time range.
Args:
schedules (List[str]): Email addresses to check
start_time (str): Start time (ISO 8601)
end_time (str): End time (ISO 8601)
availability_view_interval (int): Interval in minutes
Returns:
List[Dict]: Free/busy information
"""
# Navigation Properties
@property
def events(self) -> 'EventCollection':
"""Events in the calendar."""
@property
def calendar_view(self) -> 'EventCollection':
"""Calendar view of events."""
class CalendarCollection:
"""Collection of calendars with management capabilities."""
def get(self) -> 'CalendarCollection':
"""Retrieve collection of calendars."""
def get_by_id(self, calendar_id: str) -> Calendar:
"""
Get calendar by ID.
Args:
calendar_id (str): Calendar unique identifier
Returns:
Calendar: Calendar object
"""
def add(self, calendar_info: Dict[str, Any]) -> Calendar:
"""
Create new calendar.
Args:
calendar_info (Dict): Calendar properties
Returns:
Calendar: Created calendar
"""
class Event:
"""Calendar event with comprehensive scheduling and attendee management."""
# Core Properties
id: str
created_date_time: str
last_modified_date_time: str
change_key: str
categories: List[str]
original_start_time_zone: str
original_end_time_zone: str
i_cal_u_id: str
reminder_minutes_before_start: int
is_reminder_on: bool
has_attachments: bool
subject: str
importance: str
sensitivity: str
is_all_day: bool
is_cancelled: bool
is_organizer: bool
response_requested: bool
series_master_id: str
show_as: str # "free", "tentative", "busy", "oof", "workingElsewhere"
type: str # "singleInstance", "occurrence", "exception", "seriesMaster"
web_link: str
def get(self) -> 'Event':
"""
Retrieve event information.
Returns:
Event: Updated event object
"""
def update(self) -> 'Event':
"""
Update event properties.
Returns:
Event: Updated event object
"""
def delete(self) -> None:
"""Delete event."""
def accept(self, comment: str = None, send_response: bool = True) -> None:
"""
Accept meeting invitation.
Args:
comment (str, optional): Response comment
send_response (bool): Send response to organizer
"""
def decline(self, comment: str = None, send_response: bool = True) -> None:
"""
Decline meeting invitation.
Args:
comment (str, optional): Response comment
send_response (bool): Send response to organizer
"""
def tentatively_accept(self, comment: str = None, send_response: bool = True) -> None:
"""
Tentatively accept meeting invitation.
Args:
comment (str, optional): Response comment
send_response (bool): Send response to organizer
"""
def cancel(self, comment: str = None) -> None:
"""
Cancel event (organizer only).
Args:
comment (str, optional): Cancellation comment
"""
def dismiss_reminder(self) -> None:
"""Dismiss event reminder."""
def snooze_reminder(self, new_reminder_time: str) -> None:
"""
Snooze event reminder.
Args:
new_reminder_time (str): New reminder time (ISO 8601)
"""
def forward(self, to_recipients: List[Dict[str, str]], comment: str = None) -> None:
"""
Forward meeting invitation.
Args:
to_recipients (List[Dict]): Recipients to forward to
comment (str, optional): Forward comment
"""
# Navigation Properties
@property
def body(self) -> 'ItemBody':
"""Event body content."""
@property
def start(self) -> 'DateTimeTimeZone':
"""Event start time."""
@property
def end(self) -> 'DateTimeTimeZone':
"""Event end time."""
@property
def location(self) -> 'Location':
"""Event location."""
@property
def locations(self) -> List['Location']:
"""Multiple event locations."""
@property
def attendees(self) -> List['Attendee']:
"""Event attendees."""
@property
def organizer(self) -> 'Recipient':
"""Event organizer."""
@property
def recurrence(self) -> 'PatternedRecurrence':
"""Event recurrence pattern."""
@property
def attachments(self) -> 'AttachmentCollection':
"""Event attachments."""
@property
def online_meeting(self) -> 'OnlineMeetingInfo':
"""Online meeting information."""
@property
def instances(self) -> 'EventCollection':
"""Event instances (for recurring events)."""
class EventCollection:
"""Collection of calendar events with query and management capabilities."""
def get(self) -> 'EventCollection':
"""Retrieve collection of events."""
def filter(self, expression: str) -> 'EventCollection':
"""
Filter events by expression.
Args:
expression (str): OData filter expression
Returns:
EventCollection: Filtered collection
"""
def select(self, properties: List[str]) -> 'EventCollection':
"""
Select specific properties.
Args:
properties (List[str]): Property names to select
Returns:
EventCollection: Collection with selected properties
"""
def top(self, count: int) -> 'EventCollection':
"""
Limit results to top N events.
Args:
count (int): Maximum number of events
Returns:
EventCollection: Limited collection
"""
def order_by(self, property_name: str, ascending: bool = True) -> 'EventCollection':
"""
Sort events by property.
Args:
property_name (str): Property to sort by
ascending (bool): Sort direction
Returns:
EventCollection: Sorted collection
"""
def get_by_id(self, event_id: str) -> Event:
"""
Get event by ID.
Args:
event_id (str): Event unique identifier
Returns:
Event: Event object
"""
def add(self, event_info: Dict[str, Any]) -> Event:
"""
Create new event.
Args:
event_info (Dict): Event properties
Returns:
Event: Created event
"""File and item attachment support with comprehensive attachment handling for both email messages and calendar events.
class Attachment:
"""Base attachment class with common properties and operations."""
# Core Properties
id: str
last_modified_date_time: str
name: str
content_type: str
size: int
is_inline: bool
def get(self) -> 'Attachment':
"""
Retrieve attachment information.
Returns:
Attachment: Updated attachment object
"""
def delete(self) -> None:
"""Delete attachment."""
class FileAttachment(Attachment):
"""File attachment with content access."""
# Additional Properties
content_id: str
content_location: str
content_bytes: bytes
def get_content(self) -> bytes:
"""
Get attachment content.
Returns:
bytes: Attachment content as bytes
"""
class ItemAttachment(Attachment):
"""Outlook item attachment (message, event, contact)."""
# Navigation Properties
@property
def item(self) -> 'OutlookItem':
"""Attached Outlook item."""
class ReferenceAttachment(Attachment):
"""Reference attachment pointing to cloud content."""
# Additional Properties
source_url: str
provider_type: str
thumbnail_url: str
preview_url: str
permission: str
is_folder: bool
class AttachmentCollection:
"""Collection of attachments with management capabilities."""
def get(self) -> 'AttachmentCollection':
"""Retrieve collection of attachments."""
def get_by_id(self, attachment_id: str) -> Attachment:
"""
Get attachment by ID.
Args:
attachment_id (str): Attachment unique identifier
Returns:
Attachment: Attachment object
"""
def add(self, attachment_info: Dict[str, Any]) -> Attachment:
"""
Add new attachment.
Args:
attachment_info (Dict): Attachment properties and content
Returns:
Attachment: Created attachment
"""from office365.graph_client import GraphClient
client = GraphClient.with_client_secret(client_id, client_secret, tenant)
# Get user's messages
messages = client.me.messages.top(10).get().execute_query()
for message in messages:
print(f"From: {message.from_['emailAddress']['name']}, Subject: {message.subject}")
# Send email
message_info = {
"subject": "Project Update",
"body": {
"contentType": "html",
"content": "<h1>Project Status</h1><p>The project is on track for completion next week.</p>"
},
"toRecipients": [
{
"emailAddress": {
"address": "colleague@company.com",
"name": "Colleague Name"
}
}
]
}
client.me.send_mail(message_info, save_to_sent_items=True).execute_query()
print("Email sent successfully")
# Create draft with attachment
draft_info = {
"subject": "Report with Attachment",
"body": {
"contentType": "text",
"content": "Please find the attached report."
},
"toRecipients": [
{"emailAddress": {"address": "manager@company.com"}}
]
}
draft = client.me.messages.add(draft_info).execute_query()
# Add file attachment
with open("report.pdf", "rb") as file_content:
attachment_info = {
"@odata.type": "#microsoft.graph.fileAttachment",
"name": "monthly_report.pdf",
"contentType": "application/pdf",
"contentBytes": file_content.read()
}
draft.attachments.add(attachment_info).execute_query()
# Send draft
draft.send().execute_query()# Get user's calendar events
events = client.me.events.filter("start/dateTime ge '2024-01-01T00:00:00Z'").top(5).get().execute_query()
for event in events:
print(f"Event: {event.subject}, Start: {event.start['dateTime']}")
# Create calendar event
event_info = {
"subject": "Team Meeting",
"body": {
"contentType": "html",
"content": "Weekly team sync meeting"
},
"start": {
"dateTime": "2024-02-15T10:00:00",
"timeZone": "UTC"
},
"end": {
"dateTime": "2024-02-15T11:00:00",
"timeZone": "UTC"
},
"location": {
"displayName": "Conference Room A"
},
"attendees": [
{
"emailAddress": {
"address": "team@company.com",
"name": "Team Members"
},
"type": "required"
}
],
"reminderMinutesBeforeStart": 15,
"recurrence": {
"pattern": {
"type": "weekly",
"interval": 1,
"daysOfWeek": ["thursday"]
},
"range": {
"type": "endDate",
"startDate": "2024-02-15",
"endDate": "2024-06-15"
}
}
}
new_event = client.me.events.add(event_info).execute_query()
print(f"Created recurring event: {new_event.subject}")# Get mail folders
folders = client.me.mail_folders.get().execute_query()
for folder in folders:
print(f"Folder: {folder.display_name}, Unread: {folder.unread_item_count}")
# Create custom folder
folder_info = {
"displayName": "Project Communications"
}
new_folder = client.me.mail_folders.add(folder_info).execute_query()
# Move messages to folder
inbox = client.me.mail_folders.filter("displayName eq 'Inbox'").get().execute_query()[0]
project_messages = inbox.messages.filter("contains(subject, 'Project Alpha')").get().execute_query()
for message in project_messages:
message.move(new_folder.id).execute_query()
print(f"Moved message: {message.subject}")from typing import Dict, List, Any, Optional
class ItemBody:
"""Content body for messages and events."""
content_type: str # "text" or "html"
content: str
class Recipient:
"""Email recipient information."""
email_address: Dict[str, str] # {"name": str, "address": str}
class DateTimeTimeZone:
"""Date and time with timezone information."""
date_time: str # ISO 8601 format
time_zone: str # Timezone identifier
class Location:
"""Event location information."""
display_name: str
location_email_address: str
address: Dict[str, str]
coordinates: Dict[str, float]
location_uri: str
location_type: str
unique_id: str
unique_id_type: str
class Attendee:
"""Event attendee with response information."""
type: str # "required", "optional", "resource"
status: Dict[str, str] # {"response": str, "time": str}
email_address: Dict[str, str]
class PatternedRecurrence:
"""Event recurrence pattern."""
pattern: Dict[str, Any] # Recurrence pattern details
range: Dict[str, Any] # Recurrence range details
class RecurrencePattern:
"""Recurrence pattern details."""
type: str # "daily", "weekly", "monthly", etc.
interval: int
month: int
day_of_month: int
days_of_week: List[str]
first_day_of_week: str
index: str
class RecurrenceRange:
"""Recurrence range details."""
type: str # "endDate", "noEnd", "numbered"
start_date: str
end_date: str
recurrence_time_zone: str
number_of_occurrences: int
class OnlineMeetingInfo:
"""Online meeting information for events."""
conference_id: str
join_url: str
phones: List[Dict[str, str]]
quick_dial: str
toll_free_numbers: List[str]
toll_number: str
class MessageRule:
"""Email rule for automatic message processing."""
id: str
display_name: str
sequence: int
is_enabled: bool
has_error: bool
conditions: Dict[str, Any]
actions: Dict[str, Any]
exceptions: Dict[str, Any]
class MailboxSettings:
"""User mailbox configuration settings."""
archive_folder: str
automatic_replies_setting: Dict[str, Any]
date_format: str
delegate_meeting_message_delivery_options: str
language: Dict[str, str]
time_format: str
time_zone: str
working_hours: Dict[str, Any]Install with Tessl CLI
npx tessl i tessl/pypi-office365-rest-python-client