""" EmailMessagingGraph.py ---------------------- Private Microsoft Graph mail sender Application permissions, shared mailbox """ import msal import requests from functools import lru_cache from typing import Union, List # ========================= # PRIVATE CONFIG (ONLY YOU) # ========================= TENANT_ID = "7d269944-37a4-43a1-8140-c7517dc426e9" CLIENT_ID = "4b222bfd-78c9-4239-a53f-43006b3ed07f" CLIENT_SECRET = "Txg8Q~MjhocuopxsJyJBhPmDfMxZ2r5WpTFj1dfk" SENDER = "reports@buzalka.cz" AUTHORITY = f"https://login.microsoftonline.com/{TENANT_ID}" SCOPE = ["https://graph.microsoft.com/.default"] @lru_cache(maxsize=1) def _get_token() -> str: app = msal.ConfidentialClientApplication( CLIENT_ID, authority=AUTHORITY, client_credential=CLIENT_SECRET, ) token = app.acquire_token_for_client(scopes=SCOPE) if "access_token" not in token: raise RuntimeError(f"Graph auth failed: {token}") return token["access_token"] def send_mail( to: Union[str, List[str]], subject: str, body: str, *, html: bool = False, ): """ Send email via Microsoft Graph. :param to: email or list of emails :param subject: subject :param body: email body :param html: True = HTML, False = plain text """ if isinstance(to, str): to = [to] payload = { "message": { "subject": subject, "body": { "contentType": "HTML" if html else "Text", "content": body, }, "toRecipients": [ {"emailAddress": {"address": addr}} for addr in to ], }, "saveToSentItems": "true", } headers = { "Authorization": f"Bearer {_get_token()}", "Content-Type": "application/json", } r = requests.post( f"https://graph.microsoft.com/v1.0/users/{SENDER}/sendMail", headers=headers, json=payload, timeout=30, ) if r.status_code != 202: raise RuntimeError( f"sendMail failed [{r.status_code}]: {r.text}" )