Skip to content

Message lifecycle: reply, forward, move, and copy messages.

Covers the most common post-receive operations: - Reply to sender (with modified body) - Forward to another recipient - Move to a different folder - Copy to a different folder

The pattern: create a draft → optionally edit → save or send.

Permissions

Requires delegated permission Mail.ReadWrite and Mail.Send.

Reference

View source

import sys

from office365.graph_client import GraphClient
from tests.settings import client_id, password, tenant, username


def get_latest_inbox_message(client: GraphClient):
    """Return the most recent message in the inbox, or None."""
    messages = client.me.mail_folders["inbox"].messages.top(1).get().execute_query()
    return messages[0] if len(messages) > 0 else None


def main():
    client = GraphClient(tenant=tenant).with_username_and_password(client_id, username, password)

    # -- Step 1: pick a message to work with --
    message = get_latest_inbox_message(client)
    if message is None:
        sys.exit("No messages in inbox.")

    # Load subject and body for display
    message.select(["subject", "body"]).execute_query()
    print(f'Source message: "{message.subject}"\n')

    # -- Step 2: reply --
    draft = message.create_reply().execute_query()
    # Draft body is auto-populated; append a line
    body = draft.body.get_property("content", "")
    draft.set_property("body", {"contentType": "Text", "content": body + "\n\n---\nSent via Microsoft Graph SDK"})
    draft.update().execute_query()
    draft.send().execute_query()
    print("✓ Reply sent (with appended signature).")

    # -- Step 3: forward --
    forward_to = "meganb@contoso.onmicrosoft.com"
    message.forward(to_recipients=[forward_to], comment="FYI — see below.").execute_query()
    print(f"✓ Forwarded to {forward_to}.")

    # -- Step 4: move to a subfolder --
    # Ensure a subfolder exists
    inbox = client.me.mail_folders["inbox"]
    child_folders = inbox.child_folders.get().execute_query()
    archive_folder = next((f for f in child_folders if f.display_name == "Archive"), None)

    if archive_folder is None:
        archive_folder = inbox.child_folders.add("Archive").execute_query()
        print("  (Created 'Archive' folder)")

    moved = message.move(archive_folder.id).execute_query()
    print(f"✓ Moved to '{archive_folder.display_name}' (new id: {moved.id})")

    # -- Step 5: copy back to inbox --
    inbox = client.me.mail_folders["inbox"]
    # Refresh the message reference from its new location
    client.me.messages[moved.id].copy(inbox.id).execute_query()
    print("✓ Copied back to Inbox.")


if __name__ == "__main__":
    main()

← Back to Messages