From 0d5673b02c0c4daf495219ecdb195ef2dd4328f6 Mon Sep 17 00:00:00 2001 From: wpanda Date: Wed, 4 Feb 2026 12:56:12 +0100 Subject: [PATCH] =?UTF-8?q?script=20uj=20v=C3=A4ltozatok?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Doc/Aufgabe.md | 11 +- Doc/Default-01.md | 4 + Scripts/powershell/o365_mail.ps1 | 91 ++++++++++ Scripts/python/import_pdf_from_o365_de.py | 12 ++ .../python/import_pdf_from_o365_de_v.1.0.py | 168 ++++++++++++++++++ Scripts/python/mail_o365.py | 102 +++++++++++ Scripts/python/o365_mail.py | 21 +++ 7 files changed, 402 insertions(+), 7 deletions(-) create mode 100644 Scripts/powershell/o365_mail.ps1 create mode 100644 Scripts/python/import_pdf_from_o365_de_v.1.0.py create mode 100644 Scripts/python/mail_o365.py create mode 100644 Scripts/python/o365_mail.py diff --git a/Doc/Aufgabe.md b/Doc/Aufgabe.md index 8da4f65..388b761 100644 --- a/Doc/Aufgabe.md +++ b/Doc/Aufgabe.md @@ -6,14 +6,11 @@ https://www.tc-telefon.de/Kontakt/ -- https://www.behnke-online.de/de/partner-plz-20000-29999 -4. +4. Bestellen 5 DisplayPort -5. +6. IXOS Benutzer von Jan -verbung@meszely.eu -ionOs#6774#IonOs +7. Drucker Alster +j.berg 1234 -NB -12 -49 diff --git a/Doc/Default-01.md b/Doc/Default-01.md index 2344ef5..5b95e96 100644 --- a/Doc/Default-01.md +++ b/Doc/Default-01.md @@ -127,6 +127,10 @@ virgI6774#Virgi virgI6774# +verbung@meszely.eu +ionOs#6774#IonOs + + nogy tudom a hälozati jelszot viszaällitani windows serveren valami reset-networkpassword Reset-ComputerMachinePassword -Server dc01.domain.local -Credential (Get-Credential) diff --git a/Scripts/powershell/o365_mail.ps1 b/Scripts/powershell/o365_mail.ps1 new file mode 100644 index 0000000..dc137c5 --- /dev/null +++ b/Scripts/powershell/o365_mail.ps1 @@ -0,0 +1,91 @@ +# Requires -Modules @{ModuleName='Microsoft.Graph.Applications';ModuleVersion='1.19.0'}, @{ModuleName='Microsoft.Graph.Mail';ModuleVersion='1.19.0'} + +# ============================================================================== +# KONFIGURÁCIÓ +# ============================================================================== +# Adatok az Azure App Regisztrációból +# Tennant ID : caee3499-03f8-4175-9fa8-a935248d0ece +$TENANT_ID = "caee3499-03f8-4175-9fa8-a935248d0ece" +# Client Id : 3a08b279-1fc3-419f-a77e-31f12a0f65f7 +$CLIENT_ID = "3a08b279-1fc3-419f-a77e-31f12a0f65f7" +# Key : Rk-8Q~nJ.sZ-xUiNxtEDdzVgoFFosODLVHX~jdrh (érték, nem Secret ID) +$CLIENT_SECRET = "Rk-8Q~nJ.sZ-xUiNxtEDdzVgoFFosODLVHX~jdrh" + +# Figyelt postafiók +$USER_EMAIL = "i.meszely@aps-hh.de" + +# Microsoft Graph API végpontok (alapértelmezett, nem kell módosítani) +$GRAPH_API_ENDPOINT = "https://graph.microsoft.com/v1.0" + +# Scopes needed for the application +# Mail.ReadWrite for reading, marking as read, and eventually moving emails +$SCOPES = @("Mail.ReadWrite") + +# ============================================================================== +# FÜGGVÉNYEK +# ============================================================================== + +Function Connect-GraphAPI { + <# + .SYNOPSIS + Csatlakozik a Microsoft Graph API-hoz kliens hitelesítő adatokkal. + .DESCRIPTION + Ez a függvény megpróbál csatlakozni a Microsoft Graph API-hoz az Azure AD alkalmazás regisztrációjában megadott + kliens hitelesítő adatok (Tenant ID, Client ID, Client Secret) segítségével. + Sikeres kapcsolat esetén egy Access Token-t ad vissza. Hiba esetén null-t ad vissza és hibaüzenetet ír ki. + .OUTPUTS + Access Token (String) vagy $null + #> + [CmdletBinding()] + Param() + + Write-Host "Graph API-hoz való csatlakozás megkezdése..." -ForegroundColor Cyan + + try { + # Ellenőrizzük, hogy a szükséges modulok telepítve vannak-e + $requiredModules = @("Microsoft.Graph.Applications", "Microsoft.Graph.Mail") + foreach ($module in $requiredModules) { + if (-not (Get-Module -ListAvailable -Name $module)) { + Write-Warning "A(z) '$module' PowerShell modul nincs telepítve. Kérjük telepítse futtatás előtt: Install-Module $module" + return $null + } + } + + # Csatlakozás a Graph API-hoz kliens hitelesítő adatokkal + # A -Scopes paraméterben az alkalmazásengedélyek neveit kell megadni + $connectResult = Connect-MgGraph -TenantId $TENANT_ID -ClientId $CLIENT_ID -ClientSecret $CLIENT_SECRET -Scopes $SCOPES -ErrorAction Stop + + if ($connectResult) { + Write-Host "Sikeresen csatlakozott a Graph API-hoz." -ForegroundColor Green + # Lekérjük az Access Token-t + $token = (Get-MsalToken).AccessToken + return $token + } else { + Write-Error "Nem sikerült csatlakozni a Graph API-hoz." + return $null + } + } + catch { + Write-Error "Hiba történt a Graph API-hoz való csatlakozás során: $($_.Exception.Message)" + Write-Host "Kérjük, ellenőrizze a konfigurációs beállításokat (TENANT_ID, CLIENT_ID, CLIENT_SECRET) és az alkalmazásengedélyeket az Azure AD-ben." -ForegroundColor Yellow + return $null + } +} + +# ============================================================================== +# FŐ LOGIKA +# ============================================================================== +function Main { + $accessToken = Connect-GraphAPI + + if (-not $accessToken) { + Write-Error "Nem sikerült Access Token-t szerezni. Kilépés." + return + } + + Write-Host "Access Token sikeresen lekérve. Kész a Graph API hívásokhoz." -ForegroundColor Green + # Itt fogjuk később implementálni az e-mailek feldolgozását +} + +# Fő függvény meghívása +Main \ No newline at end of file diff --git a/Scripts/python/import_pdf_from_o365_de.py b/Scripts/python/import_pdf_from_o365_de.py index b87f90b..cc2612e 100644 --- a/Scripts/python/import_pdf_from_o365_de.py +++ b/Scripts/python/import_pdf_from_o365_de.py @@ -45,6 +45,7 @@ def get_graph_api_token(): result = app.acquire_token_for_client(scopes=SCOPES) if "access_token" in result: + print("Graph API-Token erfolgreich abgerufen.") return result["access_token"] else: print("Fehler beim Abrufen des Tokens!") @@ -157,6 +158,17 @@ def main(): # Für das Verschieben ist die Berechtigung Mail.ReadWrite erforderlich! print(f" Fehler beim Verschieben der E-Mail: {response.status_code} - {response.text}") + # E-Mail als gelesen markieren + print(f" Markiere E-Mail '{subject}' (ID: {msg_id}) als gelesen...") + mark_as_read_url = f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/messages/{msg_id}" + mark_as_read_payload = {"isRead": True} + + response = requests.patch(mark_as_read_url, headers=headers, json=mark_as_read_payload) + if response.status_code == 200: + print(" E-Mail erfolgreich als gelesen markiert.") + else: + print(f" Fehler beim Markieren der E-Mail als gelesen: {response.status_code} - {response.text}") + print("\nVerarbeitung abgeschlossen.") diff --git a/Scripts/python/import_pdf_from_o365_de_v.1.0.py b/Scripts/python/import_pdf_from_o365_de_v.1.0.py new file mode 100644 index 0000000..7d1cda9 --- /dev/null +++ b/Scripts/python/import_pdf_from_o365_de_v.1.0.py @@ -0,0 +1,168 @@ +import os +import requests +import msal +import base64 + +# ============================================================================== +# KONFIGURATION +# ============================================================================== +# Daten aus der Azure App-Registrierung +# Tennant ID : caee3499-03f8-4175-9fa8-a935248d0ece +TENANT_ID = "caee3499-03f8-4175-9fa8-a935248d0ece" +# Client Id : 3a08b279-1fc3-419f-a77e-31f12a0f65f7 +CLIENT_ID = "3a08b279-1fc3-419f-a77e-31f12a0f65f7" +# Key : 3cd0be8b-e58f-4e0c-9856-5c9788183b2c +CLIENT_SECRET = "Rk-8Q~nJ.sZ-xUiNxtEDdzVgoFFosODLVHX~jdrh" # Der "Wert", nicht die "Secret ID" + +# Das zu überwachende Postfach +# USER_EMAIL = "Bestellung-Fax-Eingang@aps-hh.de" +USER_EMAIL = "i.meszely@aps-hh.de" + +# Speicherort für heruntergeladene PDFs +# DOWNLOAD_DIR = r"\\aps-nb090\test" +# DOWNLOAD_DIR = r"C:\Users\YourUsername\Downloads\PDFs" +DOWNLOAD_DIR = "C:/Tools/PDF" + +# Name des Ordners, in den verarbeitete E-Mails verschoben werden +PROCESSED_FOLDER_NAME = "something" +# ============================================================================== + +# Microsoft Graph API Endpunkte +GRAPH_API_ENDPOINT = "https://graph.microsoft.com/v1.0" +AUTHORITY_URL = f"https://login.microsoftonline.com/{TENANT_ID}" +SCOPES = ["https://graph.microsoft.com/.default"] + + +def get_graph_api_token(): + """Ruft das Zugriffstoken für die Microsoft Graph API ab.""" + app = msal.ConfidentialClientApplication( + client_id=CLIENT_ID, + authority=AUTHORITY_URL, + client_credential=CLIENT_SECRET + ) + result = app.acquire_token_silent(scopes=SCOPES, account=None) + if not result: + result = app.acquire_token_for_client(scopes=SCOPES) + + if "access_token" in result: + print("Graph API-Token erfolgreich abgerufen.") + return result["access_token"] + else: + print("Fehler beim Abrufen des Tokens!") + print(result.get("error")) + print(result.get("error_description")) + return None + +def get_folder_id(access_token, folder_name): + """Sucht die ID eines Ordners anhand seines Namens.""" + headers = {"Authorization": f"Bearer {access_token}"} + url = f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/mailFolders" + response = requests.get(url, headers=headers) + response.raise_for_status() + folders = response.json().get("value", []) + + for folder in folders: + if folder["displayName"].lower() == folder_name.lower(): + return folder["id"] + + # Man könnte auch den Fall behandeln, dass der Ordner nicht existiert, und ihn erstellen. + # Vorerst wird einfach ein Fehler ausgelöst. + raise ValueError(f"Der Ordner '{folder_name}' wurde nicht gefunden.") + + +def main(): + """Hauptverarbeitungsfunktion.""" + print("Graph API-Token wird abgerufen...") + access_token = get_graph_api_token() + if not access_token: + return + + headers = {"Authorization": f"Bearer {access_token}"} + + try: + print(f"Suche nach der ID für den Ordner '{PROCESSED_FOLDER_NAME}'...") + processed_folder_id = get_folder_id(access_token, PROCESSED_FOLDER_NAME) + print("Ordner-ID erfolgreich abgerufen.") + except requests.exceptions.HTTPError as e: + print(f"Fehler beim Abrufen der Ordner-ID: {e}") + if e.response.status_code == 403: + print("Mögliche Ursache: Fehlende oder unzureichende Graph API-Berechtigungen. Bitte stellen Sie sicher, dass die Anwendung die erforderlichen 'Application Permissions' (z.B. Mail.Read, Mail.ReadWrite) in Azure AD hat und dass der Administrator die Zustimmung erteilt hat.") + return + except ValueError as e: + print(f"Fehler beim Abrufen der Ordner-ID: {e}") + return + + # Nur ungelesene E-Mails mit Anhängen abfragen + # $select=id,subject -> Nur die notwendigen Felder für mehr Effizienz abfragen + messages_url = ( + f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/mailFolders/inbox/messages?" + f"$filter=isRead eq false and hasAttachments eq true&" + f"$select=id,subject" + ) + + response = requests.get(messages_url, headers=headers) + response.raise_for_status() + messages = response.json().get("value", []) + + if not messages: + print("Keine neuen E-Mails zur Verarbeitung gefunden.") + return + + print(f"{len(messages)} neue E-Mail(s) mit Anhängen gefunden.") + + for message in messages: + msg_id = message["id"] + subject = message.get("subject", "N/A") + print(f"\n--- In Verarbeitung: '{subject}' (ID: {msg_id}) ---") + + attachments_url = f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/messages/{msg_id}/attachments" + response = requests.get(attachments_url, headers=headers) + if response.status_code != 200: + print(f" Fehler beim Abrufen der Anhänge: {response.json()}") + continue + + attachments = response.json().get("value", []) + pdf_found = False + + for att in attachments: + filename = att.get("name", "unknown") + content_type = att.get("contentType", "") + + if filename.lower().endswith(".pdf") or content_type == "application/pdf": + print(f" PDF-Anhang gefunden: {filename}") + + # Der Inhalt des Anhangs befindet sich im Feld 'contentBytes' und ist Base64-kodiert + file_content = base64.b64decode(att["contentBytes"]) + + # Dateinamen bereinigen + safe_filename = "".join(c if c.isalnum() or c in (" ", ".", "_", "-") else "_" for c in filename) + filepath = os.path.join(DOWNLOAD_DIR, safe_filename) + + try: + with open(filepath, "wb") as f: + f.write(file_content) + print(f" PDF erfolgreich gespeichert: {filepath}") + pdf_found = True + except Exception as e: + print(f" Fehler beim Speichern der Datei: {e}") + + if pdf_found: + print(f" E-Mail wird in den Ordner '{PROCESSED_FOLDER_NAME}' verschoben...") + move_url = f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/messages/{msg_id}/move" + move_payload = {"destinationId": processed_folder_id} + + response = requests.post(move_url, headers=headers, json=move_payload) + if response.status_code == 201: + print(" E-Mail erfolgreich verschoben.") + else: + # Für das Verschieben ist die Berechtigung Mail.ReadWrite erforderlich! + print(f" Fehler beim Verschieben der E-Mail: {response.status_code} - {response.text}") + + print("\nVerarbeitung abgeschlossen.") + + +if __name__ == "__main__": + if not os.path.exists(DOWNLOAD_DIR): + print(f"Fehler: Der Download-Ordner existiert nicht: {DOWNLOAD_DIR}") + else: + main() diff --git a/Scripts/python/mail_o365.py b/Scripts/python/mail_o365.py new file mode 100644 index 0000000..6af1ea4 --- /dev/null +++ b/Scripts/python/mail_o365.py @@ -0,0 +1,102 @@ +import os +import requests +import msal + +# ============================================================================== +# KONFIGURATION +# ============================================================================== +# Daten aus der Azure App Registration +TENANT_ID = "caee3499-03f8-4175-9fa8-a935248d0ece" +CLIENT_ID = "3a08b279-1fc3-419f-a77e-31f12a0f65f7" +CLIENT_SECRET = "Rk-8Q~nJ.sZ-xUiNxtEDdzVgoFFosODLVHX~jdrh" + +# Überwachtes Postfach +USER_EMAIL = "i.meszely@aps-hh.de" + +# Microsoft Graph API Endpunkte +GRAPH_API_ENDPOINT = "https://graph.microsoft.com/v1.0" +AUTHORITY_URL = f"https://login.microsoftonline.com/{TENANT_ID}" +SCOPES = ["https://graph.microsoft.com/.default"] + +def get_graph_api_token(): + """Ruft das Zugriffstoken für die Microsoft Graph API ab.""" + app = msal.ConfidentialClientApplication( + client_id=CLIENT_ID, + authority=AUTHORITY_URL, + client_credential=CLIENT_SECRET + ) + result = app.acquire_token_silent(scopes=SCOPES, account=None) + if not result: + result = app.acquire_token_for_client(scopes=SCOPES) + + if "access_token" in result: + return result["access_token"] + else: + print("Fehler beim Abrufen des Tokens!") + print(result.get("error")) + print(result.get("error_description")) + return None + +def list_inbox_emails(access_token): + """Listet ungelesene E-Mails aus dem INBOX.""" + headers = {"Authorization": f"Bearer {access_token}"} + + # Nur notwendige Felder aus Effizienzgründen abrufen + messages_url = ( + f"{GRAPH_API_ENDPOINT}/users/{USER_EMAIL}/mailFolders/inbox/messages?" + f"$filter=isRead eq false&" + f"$select=from,subject,receivedDateTime&" + f"$orderby=receivedDateTime desc" + ) + + response = requests.get(messages_url, headers=headers) + response.raise_for_status() + messages = response.json().get("value", []) + + if not messages: + print("Keine neuen ungelesenen E-Mails im INBOX-Ordner.") + return + + print(f"\n{len(messages)} ungelesene E-Mails gefunden:") + print("=" * 60) + + for i, message in enumerate(messages, 1): + from_email = message.get("from", {}).get("emailAddress", {}) + sender = from_email.get("address", "Unbekannt") + subject = message.get("subject", "Kein Betreff") + received = message.get("receivedDateTime", "") + + # Datum formatieren + if received: + try: + from datetime import datetime + dt = datetime.fromisoformat(received.replace('Z', '+00:00')) + formatted_date = dt.strftime("%Y-%m-%d %H:%M") + except: + formatted_date = received[:19] # Einfache Formatierung bei Fehler + else: + formatted_date = "Unbekannt" + + print(f"\n{i}. {sender}") + print(f" Betreff: {subject}") + print(f" Zeit: {formatted_date}") + +def main(): + """Hauptfunktion.""" + print("Graph API Token wird abgerufen...") + access_token = get_graph_api_token() + if not access_token: + return + + try: + list_inbox_emails(access_token) + except requests.HTTPError as e: + print(f"Fehler beim Abrufen der E-Mails: {e}") + if "403" in str(e): + print("403 Fehler: Wahrscheinlich fehlende Mail.Read Berechtigung.") + print("Überprüfen Sie die API-Berechtigungen in der Azure App Registration!") + except Exception as e: + print(f"Unerwarteter Fehler: {e}") + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/Scripts/python/o365_mail.py b/Scripts/python/o365_mail.py new file mode 100644 index 0000000..a768a54 --- /dev/null +++ b/Scripts/python/o365_mail.py @@ -0,0 +1,21 @@ +# Code snippets are only available for the latest version. Current version is 1.x +# pip install msgraph-sdk +# New-ItemProperty -Path "HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem" -Name "LongPathsEnabled" -Value 1 -PropertyType DWORD -Force +from msgraph import GraphServiceClient +# To initialize your graph_client, see https://learn.microsoft.com/en-us/graph/sdks/create-client?from=snippets&tabs=python + +scopes = ['User.Read'] + +# Multi-tenant apps can use "common", +# single-tenant apps must use the tenant ID from the Azure portal +tenant_id = 'caee3499-03f8-4175-9fa8-a935248d0ece' + +# Values from app registration +client_id = '3a08b279-1fc3-419f-a77e-31f12a0f65f7' + +# azure.identity +credential = DeviceCodeCredential( + tenant_id=tenant_id, + client_id=client_id) + +graph_client = GraphServiceClient(credential, scopes)