Skip to main content
Glama
ZilongXue

ClaudePost

by ZilongXue

search-emails

Search emails by date range or keywords in specific folders using ClaudePost. Retrieve relevant emails from 'inbox' or 'sent' folders efficiently.

Instructions

Search emails within a date range and/or with specific keywords

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault
end_dateNoEnd date in YYYY-MM-DD format (optional)
folderNoFolder to search in ('inbox' or 'sent', defaults to 'inbox')
keywordNoKeyword to search in email subject and body (optional)
start_dateNoStart date in YYYY-MM-DD format (optional)

Implementation Reference

  • Executes the search-emails tool: selects folder, builds IMAP search criteria from dates and keyword, searches asynchronously, formats results as a table.
    if name == "search-emails":
        # 选择文件夹
        folder = arguments.get("folder", "inbox")  # 默认选择收件箱
        if folder == "sent":
            mail.select('"[Gmail]/Sent Mail"')  # 对于 Gmail
        else:
            mail.select("inbox")
        
        # Get optional parameters
        start_date = arguments.get("start_date")
        end_date = arguments.get("end_date")
        keyword = arguments.get("keyword")
        
        # If no dates provided, default to last 7 days
        if not start_date:
            start_date = datetime.now() - timedelta(days=7)
            start_date = start_date.strftime("%d-%b-%Y")
        else:
            start_date = datetime.strptime(start_date, "%Y-%m-%d").strftime("%d-%b-%Y")
            
        if not end_date:
            end_date = datetime.now().strftime("%d-%b-%Y")
        else:
            # Convert end_date to datetime object once
            end_date_obj = datetime.strptime(end_date, "%Y-%m-%d")
            end_date = end_date_obj.strftime("%d-%b-%Y")
        
        # Build search criteria
        if start_date == end_date:
            # If searching for a single day
            search_criteria = f'ON "{start_date}"'
        else:
            # Calculate next day using the already converted end_date_obj
            next_day = (end_date_obj + timedelta(days=1)).strftime("%d-%b-%Y")
            search_criteria = f'SINCE "{start_date}" BEFORE "{next_day}"'
            
        if keyword:
            # Fix: Properly combine keyword search with date criteria
            keyword_criteria = f'(OR SUBJECT "{keyword}" BODY "{keyword}")'
            search_criteria = f'({keyword_criteria} {search_criteria})'
        
        logging.debug(f"Search criteria: {search_criteria}")  # Add debug logging
        
        try:
            async with asyncio.timeout(SEARCH_TIMEOUT):
                email_list = await search_emails_async(mail, search_criteria)
                
            if not email_list:
                return [types.TextContent(
                    type="text",
                    text="No emails found matching the criteria."
                )]
            
            # Format the results as a table
            result_text = "Found emails:\n\n"
            result_text += "ID | From | Date | Subject\n"
            result_text += "-" * 80 + "\n"
            
            for email in email_list:
                result_text += f"{email['id']} | {email['from']} | {email['date']} | {email['subject']}\n"
            
            result_text += "\nUse get-email-content with an email ID to view the full content of a specific email."
            
            return [types.TextContent(
                type="text",
                text=result_text
            )]
            
        except asyncio.TimeoutError:
            return [types.TextContent(
                type="text",
                text="Search operation timed out. Please try with a more specific search criteria."
            )]
  • JSON schema for search-emails input parameters: start_date, end_date, keyword, folder.
    inputSchema={
        "type": "object",
        "properties": {
            "start_date": {
                "type": "string",
                "description": "Start date in YYYY-MM-DD format (optional)",
            },
            "end_date": {
                "type": "string",
                "description": "End date in YYYY-MM-DD format (optional)",
            },
            "keyword": {
                "type": "string",
                "description": "Keyword to search in email subject and body (optional)",
            },
            "folder": {
                "type": "string",
                "description": "Folder to search in ('inbox' or 'sent', defaults to 'inbox')",
                "enum": ["inbox", "sent"],
            },
        },
    },
  • Tool registration in list_tools(): defines name, description, and schema for search-emails.
    types.Tool(
        name="search-emails",
        description="Search emails within a date range and/or with specific keywords",
        inputSchema={
            "type": "object",
            "properties": {
                "start_date": {
                    "type": "string",
                    "description": "Start date in YYYY-MM-DD format (optional)",
                },
                "end_date": {
                    "type": "string",
                    "description": "End date in YYYY-MM-DD format (optional)",
                },
                "keyword": {
                    "type": "string",
                    "description": "Keyword to search in email subject and body (optional)",
                },
                "folder": {
                    "type": "string",
                    "description": "Folder to search in ('inbox' or 'sent', defaults to 'inbox')",
                    "enum": ["inbox", "sent"],
                },
            },
        },
    ),
  • Helper function that performs the actual IMAP email search, fetches messages, formats summaries, limits to MAX_EMAILS.
    async def search_emails_async(mail: imaplib.IMAP4_SSL, search_criteria: str) -> list[dict]:
        """Asynchronously search emails with timeout."""
        loop = asyncio.get_event_loop()
        try:
            _, messages = await loop.run_in_executor(None, lambda: mail.search(None, search_criteria))
            if not messages[0]:
                return []
                
            email_list = []
            for num in messages[0].split()[:MAX_EMAILS]:  # Limit to MAX_EMAILS
                _, msg_data = await loop.run_in_executor(None, lambda: mail.fetch(num, '(RFC822)'))
                email_list.append(format_email_summary(msg_data))
                
            return email_list
        except Exception as e:
            raise Exception(f"Error searching emails: {str(e)}")
  • Helper to extract and format basic summary (id, from, date, subject) from raw email message data.
    def format_email_summary(msg_data: tuple) -> dict:
        """Format an email message into a summary dict with basic information."""
        email_body = email.message_from_bytes(msg_data[0][1])
        
        return {
            "id": msg_data[0][0].split()[0].decode(),  # Get the email ID
            "from": email_body.get("From", "Unknown"),
            "date": email_body.get("Date", "Unknown"),
            "subject": email_body.get("Subject", "No Subject"),
        }
Install Server

Other Tools

Related Tools

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/ZilongXue/claude-post'

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