Skip to main content
Glama
server_search.py5.42 kB
""" Server-side search functionality for email operations. This module provides functions for performing server-side searches using Outlook's AdvancedSearch functionality, which is more efficient for large folders. """ # Standard library imports import time from datetime import datetime, timedelta, timezone from typing import Any, List # Local application imports from ..logging_config import get_logger from ..outlook_session.session_manager import OutlookSessionManager from .search_common import get_date_limit logger = get_logger(__name__) def server_side_search( folder, search_term: str, days: int, search_type: str, match_all: bool, namespace=None ) -> List[Any]: """ Perform server-side search using Outlook's AdvancedSearch functionality. This is more efficient for large folders as it leverages Outlook's indexing. """ try: # Use the provided namespace from the existing session # This avoids creating duplicate COM objects which can cause issues # Build the search criteria with proper formatting date_limit = get_date_limit(days) # Escape single quotes in search term to prevent syntax errors escaped_search_term = search_term.replace("'", "''") # Use SQL format for all conditions to ensure compatibility sql_conditions = [] # Add date condition sql_conditions.append(f"urn:schemas:httpmail:datereceived >= '{date_limit.strftime('%Y-%m-%d')}'") # Add content condition based on search type if search_type == "subject": if match_all: sql_conditions.append(f"urn:schemas:httpmail:subject LIKE '%{escaped_search_term}%'") else: sql_conditions.append(f"urn:schemas:httpmail:subject LIKE '%{escaped_search_term}%'") elif search_type == "sender": sql_conditions.append(f"urn:schemas:httpmail:fromname LIKE '%{escaped_search_term}%'") elif search_type == "recipient": sql_conditions.append(f"urn:schemas:httpmail:to LIKE '%{escaped_search_term}%'") # Combine all conditions with AND search_criteria = "@SQL=" + " AND ".join(sql_conditions) logger.info(f"Server-side search criteria: {search_criteria}") # Get the folder path correctly folder_path = folder.FolderPath if hasattr(folder, 'FolderPath') else str(folder) logger.info(f"Folder path: {folder_path}") logger.info(f"Search criteria: {search_criteria}") # Try using the folder's Items collection with Restrict method instead of AdvancedSearch try: # Use Restrict method on the folder's Items collection items = folder.Items restricted_items = items.Restrict(search_criteria) results = list(restricted_items) logger.info(f"Restrict method completed: found {len(results)} results") return results except Exception as e: logger.warning(f"Restrict method failed: {e}") # Fallback to AdvancedSearch with proper scope format try: # Use Application.AdvancedSearch with proper scope format outlook = namespace.Application if hasattr(namespace, 'Application') else namespace # Create scope in the format "Inbox" or "\\Personal Folders\Inbox" scope = folder_path logger.info(f"Using scope: {scope}") search_results = outlook.AdvancedSearch( Scope=scope, Filter=search_criteria, SearchSubFolders=True ) # Wait for search to complete with timeout max_wait_time = 5 # seconds start_time = time.time() while search_results.SearchState != 1: # 1 = SearchComplete time.sleep(0.1) if time.time() - start_time > max_wait_time: logger.warning("Server-side search timed out") return [] results = list(search_results.Results) logger.info(f"AdvancedSearch completed: found {len(results)} results") return results except Exception as e2: logger.error(f"AdvancedSearch also failed: {e2}") return [] # Wait for search to complete with timeout max_wait_time = 5 # seconds start_time = time.time() while search_results.SearchState != 1: # 1 = SearchComplete time.sleep(0.1) if time.time() - start_time > max_wait_time: logger.warning("Server-side search timed out") return [] results = list(search_results.Results) logger.info(f"Server-side search completed: found {len(results)} results") return results except Exception as e: logger.error(f"Server-side search failed: {e}") logger.error(f"Error type: {type(e)}") logger.error(f"Error details: {str(e)}") import traceback logger.error(f"Traceback: {traceback.format_exc()}") return []

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/marlonluo2018/outlook-mcp-server'

If you have feedback or need assistance with the MCP directory API, please join our Discord server