Created
June 8, 2026 08:36
-
-
Save DurandA/e9d134a60a26f5196a74fc1b7d6fe829 to your computer and use it in GitHub Desktop.
Send test email from CLI using Microsoft Graph API
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #!/usr/bin/env -S uv run | |
| # | |
| # /// script | |
| # requires-python = ">=3.11" | |
| # dependencies = [ | |
| # "azure-identity", | |
| # "msgraph-sdk", | |
| # ] | |
| # /// | |
| # | |
| # Minimal example to send an email using Microsoft Graph API. | |
| # | |
| # Prerequisites: | |
| # 1. Register an app in Azure Portal (https://portal.azure.com) | |
| # 2. Under "Certificates & secrets", create a client secret | |
| # 3. Under "API permissions", add Microsoft Graph > Application > Mail.Send | |
| # 4. Grant admin consent for the Mail.Send permission | |
| # 5. Set the environment variables below | |
| # | |
| # Environment variables: | |
| # MICROSOFT_GRAPH_TENANT_ID=your-azure-tenant-id | |
| # MICROSOFT_GRAPH_CLIENT_ID=your-app-client-id | |
| # MICROSOFT_GRAPH_CLIENT_SECRET=your-app-client-secret | |
| # | |
| # Usage: | |
| # ./msgraph_send_email.py --from sender@example.com --to recipient@example.com \ | |
| # --subject "Hello" --body "Test email" | |
| import argparse | |
| import asyncio | |
| import os | |
| from azure.identity import ClientSecretCredential | |
| from msgraph import GraphServiceClient | |
| from msgraph.generated.models.body_type import BodyType | |
| from msgraph.generated.models.email_address import EmailAddress | |
| from msgraph.generated.models.item_body import ItemBody | |
| from msgraph.generated.models.message import Message | |
| from msgraph.generated.models.recipient import Recipient | |
| from msgraph.generated.users.item.send_mail.send_mail_post_request_body import ( | |
| SendMailPostRequestBody, | |
| ) | |
| TENANT_ID = os.environ.get("MICROSOFT_GRAPH_TENANT_ID") | |
| CLIENT_ID = os.environ.get("MICROSOFT_GRAPH_CLIENT_ID") | |
| CLIENT_SECRET = os.environ.get("MICROSOFT_GRAPH_CLIENT_SECRET") | |
| SCOPES = ["https://graph.microsoft.com/.default"] | |
| async def send_email(from_addr: str, to_addr: str, subject: str, body: str) -> None: | |
| """Send an email using Microsoft Graph API with client credentials authentication.""" | |
| credential = ClientSecretCredential( | |
| tenant_id=TENANT_ID, | |
| client_id=CLIENT_ID, | |
| client_secret=CLIENT_SECRET, | |
| ) | |
| client = GraphServiceClient(credentials=credential, scopes=SCOPES) | |
| message = Message( | |
| subject=subject, | |
| body=ItemBody(content=body, content_type=BodyType.Text), | |
| to_recipients=[ | |
| Recipient(email_address=EmailAddress(address=to_addr)), | |
| ], | |
| ) | |
| request_body = SendMailPostRequestBody(message=message, save_to_sent_items=True) | |
| await client.users.by_user_id(from_addr).send_mail.post(request_body) | |
| print(f"Email sent from {from_addr} to {to_addr}") | |
| def main() -> None: | |
| parser = argparse.ArgumentParser(description="Send email via Microsoft Graph API") | |
| parser.add_argument("--from", dest="from_addr", required=True, help="Sender email") | |
| parser.add_argument("--to", required=True, help="Recipient email address") | |
| parser.add_argument("--subject", required=True, help="Email subject") | |
| parser.add_argument("--body", required=True, help="Email body text") | |
| args = parser.parse_args() | |
| missing = [] | |
| if not TENANT_ID: | |
| missing.append("MICROSOFT_GRAPH_TENANT_ID") | |
| if not CLIENT_ID: | |
| missing.append("MICROSOFT_GRAPH_CLIENT_ID") | |
| if not CLIENT_SECRET: | |
| missing.append("MICROSOFT_GRAPH_CLIENT_SECRET") | |
| if missing: | |
| print(f"Error: Missing environment variables: {', '.join(missing)}") | |
| return | |
| asyncio.run(send_email(args.from_addr, args.to, args.subject, args.body)) | |
| if __name__ == "__main__": | |
| main() |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment