================================================================================ GMAIL CLEANUP - CHALLENGE 2 SOLUTION Chapter 2: Configuration Management Challenge: Configuration Validation ================================================================================ PROBLEM: Extend Config.validate() to check: 1. GMAIL_USER is not empty 2. GMAIL_USER contains @ symbol (valid email) 3. API_REQUEST_TIMEOUT is positive number 4. Return True if all valid, False otherwise SOLUTION: ================================================================================ File: config.py (updated) import os import re from pathlib import Path from dotenv import load_dotenv ENV_FILE = Path(__file__).parent / ".env" load_dotenv(ENV_FILE) class Config: """Application configuration with validation.""" def __init__(self): self.gmail_user = os.environ.get('GMAIL_USER') self.api_timeout = int(os.environ.get('API_REQUEST_TIMEOUT', '10')) self.max_results = int(os.environ.get('MAX_RESULTS', '100')) self.days_old = int(os.environ.get('DELETE_OLDER_THAN_DAYS', '365')) self.min_attachment_mb = int(os.environ.get('MIN_ATTACHMENT_SIZE_MB', '10')) def validate(self) -> bool: """Validate all configuration values.""" # Check GMAIL_USER is not empty if not self.gmail_user: print("❌ GMAIL_USER is empty!") print(" Fix: Set GMAIL_USER in .env") return False # Check GMAIL_USER is not just whitespace if not self.gmail_user.strip(): print("❌ GMAIL_USER is just whitespace!") print(" Fix: Remove spaces from GMAIL_USER") return False # Check email format (has @) if '@' not in self.gmail_user: print(f"❌ GMAIL_USER '{self.gmail_user}' is not a valid email!") print(" Fix: Use format: user@gmail.com") return False # Check email format (regex) email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$' if not re.match(email_pattern, self.gmail_user): print(f"❌ GMAIL_USER '{self.gmail_user}' doesn't look like a valid email!") print(" Fix: Use format: user@example.com") return False # Check API timeout is positive if self.api_timeout <= 0: print(f"❌ API_REQUEST_TIMEOUT must be positive! Got: {self.api_timeout}") print(" Fix: Set API_REQUEST_TIMEOUT to positive number (e.g., 10)") return False # Check MAX_RESULTS is positive if self.max_results <= 0: print(f"❌ MAX_RESULTS must be positive! Got: {self.max_results}") print(" Fix: Set MAX_RESULTS to positive number (e.g., 100)") return False # Check days_old is positive if self.days_old < 0: print(f"❌ DELETE_OLDER_THAN_DAYS must be >= 0! Got: {self.days_old}") print(" Fix: Set to positive number (e.g., 365)") return False print("✅ All configuration values are valid!") return True TESTING ================================================================================ Test 1: Valid configuration (should pass) Config with GMAIL_USER=emubantam@gmail.com, API_REQUEST_TIMEOUT=10 Result: ✅ All configuration values are valid! Test 2: Missing GMAIL_USER (should fail) Config with GMAIL_USER="" (empty) Result: ❌ GMAIL_USER is empty! Fix: Set GMAIL_USER in .env Test 3: Invalid email (should fail) Config with GMAIL_USER=notanemail Result: ❌ GMAIL_USER 'notanemail' is not a valid email! Fix: Use format: user@gmail.com Test 4: Negative timeout (should fail) Config with API_REQUEST_TIMEOUT=-5 Result: ❌ API_REQUEST_TIMEOUT must be positive! Got: -5 Fix: Set API_REQUEST_TIMEOUT to positive number (e.g., 10) KEY IMPROVEMENTS ================================================================================ ✅ Multiple validation checks ✅ Clear error messages ✅ Helpful hints for fixing errors ✅ Email format validation (regex) ✅ Range checking for numbers ================================================================================