================================================================================ GMAIL CLEANUP - CHALLENGE 1 SOLUTION Chapter 6: Generalization & Extension Challenge: Extend to Another Email Service ================================================================================ PROBLEM: Adapt the pattern to Outlook/Microsoft Graph: 1. Study Microsoft Graph email API 2. Modify authentication (OAuth for Azure) 3. Update query syntax (Outlook filters) 4. Create equivalent cleanup utility SOLUTION: ================================================================================ The pattern is the SAME, only implementations differ: 1️⃣ AUTHENTICATION (Different for each service) Gmail (Google Cloud): - Uses googleapis oauth2 Outlook (Microsoft Azure): - Uses azure identity 2️⃣ API CALLS (Different endpoints) Gmail: - service.users().messages().list(userId='me', q=query) Outlook: - graph_client.me.messages.get() 3️⃣ QUERY SYNTAX (Different format) Gmail: - before:2020/01/01 - from:sender@example.com Outlook: - receivedDateTime lt 2020-01-01 - from/emailAddress/address eq 'sender@example.com' 4️⃣ THE WORKFLOW IS IDENTICAL: 1. Configure + validate 2. Authenticate 3. Find emails (query) 4. Preview 5. Confirm 6. Delete 7. Report EXAMPLE: Outlook Service ================================================================================ # outlook_utils.py from azure.identity import InteractiveBrowserCredential from msgraph.core import GraphClient def get_outlook_service(): """Get authenticated Outlook service.""" credential = InteractiveBrowserCredential() client = GraphClient(credential=credential) return client def find_old_emails_outlook(client, days: int): """Find old emails in Outlook.""" from datetime import datetime, timedelta cutoff = (datetime.now() - timedelta(days=days)).isoformat() query = f"receivedDateTime lt {cutoff}" messages = client.me.messages.get( filter=query, limit=10 ) return messages.value # outlook_cleanup.py class OutlookCleanup: """Same pattern, different API.""" def __init__(self, client): self.client = client self.deleted_count = 0 def find_emails(self, filter_query: str) -> list: """Find emails using Outlook filter syntax.""" try: messages = self.client.me.messages.get(filter=filter_query) return messages.value except Exception as e: print(f"Error: {e}") return [] def delete_email(self, message_id: str) -> bool: """Delete email in Outlook.""" try: self.client.me.messages[message_id].delete() self.deleted_count += 1 return True except Exception as e: print(f"Error: {e}") return False KEY INSIGHT ================================================================================ The STRUCTURE is the same: - Config + Validate - Authenticate - Create utility class - Find, Delete, Report The DETAILS change: - API endpoints - Authentication method - Query syntax - Response format Learn the pattern once, apply it everywhere! ================================================================================