# Copyright (c) 2025 Patrick Motsch # All rights reserved. """ Folder Management helper for Outlook operations. Handles folder ID resolution and folder name lookups. """ import logging import requests from typing import Dict, Any, Optional logger = logging.getLogger(__name__) class FolderManagementHelper: """Helper for folder management operations""" def __init__(self, methodInstance): """ Initialize folder management helper. Args: methodInstance: Instance of MethodOutlook (for access to services) """ self.method = methodInstance self.services = methodInstance.services def getFolderId(self, folder_name: str, connection: Dict[str, Any]) -> Optional[str]: """ Get the folder ID for a given folder name or ID. Returns the input as-is if it already looks like a Microsoft Graph folder ID. """ if not folder_name or not str(folder_name).strip(): return None # Graph folder IDs are base64-like strings (e.g. AQMk...); return as-is s = str(folder_name).strip() if s.startswith("AQMk") and len(s) > 20 and " " not in s: return s try: graph_url = "https://graph.microsoft.com/v1.0" headers = { "Authorization": f"Bearer {connection['accessToken']}", "Content-Type": "application/json" } # Get mail folders api_url = f"{graph_url}/me/mailFolders" response = requests.get(api_url, headers=headers) if response.status_code == 200: folders_data = response.json() all_folders = folders_data.get("value", []) # Try exact match first for folder in all_folders: if folder.get("displayName", "").lower() == folder_name.lower(): return folder.get("id") # Try common variations for Drafts folder if folder_name.lower() == "drafts": draft_variations = ["drafts", "draft", "entwürfe", "entwurf", "brouillons", "brouillon"] for folder in all_folders: folder_display_name = folder.get("displayName", "").lower() if any(variation in folder_display_name for variation in draft_variations): return folder.get("id") # Try common variations for other folders if folder_name.lower() == "sent items": sent_variations = ["sent items", "sent", "gesendete elemente", "éléments envoyés"] for folder in all_folders: folder_display_name = folder.get("displayName", "").lower() if any(variation in folder_display_name for variation in sent_variations): return folder.get("id") logger.warning(f"Folder '{folder_name}' not found. Available folders: {[f.get('displayName', 'Unknown') for f in all_folders]}") return None else: logger.warning(f"Could not retrieve folders: {response.status_code}") return None except Exception as e: logger.warning(f"Error getting folder ID for '{folder_name}': {str(e)}") return None def getFolderNameById(self, folder_id: str, connection: Dict[str, Any]) -> str: """ Get the folder display name for a given folder ID """ try: graph_url = "https://graph.microsoft.com/v1.0" headers = { "Authorization": f"Bearer {connection['accessToken']}", "Content-Type": "application/json" } # Get folder by ID api_url = f"{graph_url}/me/mailFolders/{folder_id}" response = requests.get(api_url, headers=headers) if response.status_code == 200: folder_data = response.json() return folder_data.get("displayName", folder_id) else: logger.warning(f"Could not retrieve folder name for ID {folder_id}: {response.status_code}") return folder_id except Exception as e: logger.warning(f"Error getting folder name for ID '{folder_id}': {str(e)}") return folder_id