|
import gradio as gr |
|
import json |
|
import os |
|
from typing import Dict, List |
|
from datetime import datetime, timedelta |
|
from dotenv import load_dotenv |
|
|
|
|
|
from tools import extract_query_info, analyze_emails |
|
from email_scraper import scrape_emails_by_text_search_with_credentials, _load_email_db |
|
from logger import logger |
|
|
|
load_dotenv() |
|
|
|
def search_emails(email_address: str, app_password: str, query: str) -> str: |
|
""" |
|
Search for emails based on a natural language query and return a summary. |
|
|
|
Args: |
|
email_address (str): The Gmail address to connect to |
|
app_password (str): The Gmail app password for authentication |
|
query (str): Natural language query (e.g., "show me mails from swiggy last week") |
|
|
|
Returns: |
|
str: JSON string containing email search results and analysis |
|
""" |
|
try: |
|
logger.info("Email MCP tool called with query: %s", query) |
|
|
|
|
|
query_info = extract_query_info(query) |
|
sender_keyword = query_info.get("sender_keyword", "") |
|
start_date = query_info.get("start_date") |
|
end_date = query_info.get("end_date") |
|
|
|
print(f"Searching for emails with keyword '{sender_keyword}' between {start_date} and {end_date}") |
|
|
|
|
|
full_emails = scrape_emails_by_text_search_with_credentials( |
|
email_address, app_password, sender_keyword, start_date, end_date |
|
) |
|
|
|
if not full_emails: |
|
result = { |
|
"query_info": query_info, |
|
"email_summary": [], |
|
"analysis": {"summary": f"No emails found for '{sender_keyword}' in the specified date range.", "insights": []}, |
|
"email_count": 0 |
|
} |
|
return json.dumps(result, indent=2) |
|
|
|
|
|
email_summary = [] |
|
for email in full_emails: |
|
summary_email = { |
|
"date": email.get("date"), |
|
"time": email.get("time"), |
|
"subject": email.get("subject"), |
|
"from": email.get("from", "Unknown Sender"), |
|
"message_id": email.get("message_id") |
|
} |
|
email_summary.append(summary_email) |
|
|
|
|
|
analysis = analyze_emails(full_emails) |
|
|
|
|
|
result = { |
|
"query_info": query_info, |
|
"email_summary": email_summary, |
|
"analysis": analysis, |
|
"email_count": len(full_emails) |
|
} |
|
|
|
return json.dumps(result, indent=2) |
|
|
|
except Exception as e: |
|
logger.error("Error in search_emails: %s", e) |
|
error_result = { |
|
"error": str(e), |
|
"query": query, |
|
"message": "Failed to search emails. Please check your credentials and try again." |
|
} |
|
return json.dumps(error_result, indent=2) |
|
|
|
|
|
def get_email_details(email_address: str, app_password: str, message_id: str) -> str: |
|
""" |
|
Get full details of a specific email by its message ID. |
|
|
|
Args: |
|
email_address (str): The Gmail address to connect to |
|
app_password (str): The Gmail app password for authentication |
|
message_id (str): The message ID of the email to retrieve |
|
|
|
Returns: |
|
str: JSON string containing the full email details |
|
""" |
|
try: |
|
logger.info("Getting email details for message_id: %s", message_id) |
|
|
|
|
|
db = _load_email_db() |
|
|
|
|
|
for sender_data in db.values(): |
|
for email in sender_data.get("emails", []): |
|
if email.get("message_id") == message_id: |
|
return json.dumps(email, indent=2) |
|
|
|
|
|
error_result = { |
|
"error": f"No email found with message_id '{message_id}'", |
|
"message": "Email may not be in local cache. Try searching for emails first." |
|
} |
|
return json.dumps(error_result, indent=2) |
|
|
|
except Exception as e: |
|
logger.error("Error in get_email_details: %s", e) |
|
error_result = { |
|
"error": str(e), |
|
"message_id": message_id, |
|
"message": "Failed to retrieve email details." |
|
} |
|
return json.dumps(error_result, indent=2) |
|
|
|
|
|
def analyze_email_patterns(email_address: str, app_password: str, sender_keyword: str, days_back: str = "30") -> str: |
|
""" |
|
Analyze email patterns from a specific sender over a given time period. |
|
|
|
Args: |
|
email_address (str): The Gmail address to connect to |
|
app_password (str): The Gmail app password for authentication |
|
sender_keyword (str): The sender/company keyword to analyze (e.g., "amazon", "google") |
|
days_back (str): Number of days to look back (default: "30") |
|
|
|
Returns: |
|
str: JSON string containing email pattern analysis |
|
""" |
|
try: |
|
logger.info("Analyzing email patterns for sender: %s, days_back: %s", sender_keyword, days_back) |
|
|
|
|
|
days_int = int(days_back) |
|
end_date = datetime.today() |
|
start_date = end_date - timedelta(days=days_int) |
|
|
|
start_date_str = start_date.strftime("%d-%b-%Y") |
|
end_date_str = end_date.strftime("%d-%b-%Y") |
|
|
|
|
|
full_emails = scrape_emails_by_text_search_with_credentials( |
|
email_address, app_password, sender_keyword, start_date_str, end_date_str |
|
) |
|
|
|
if not full_emails: |
|
result = { |
|
"sender_keyword": sender_keyword, |
|
"date_range": f"{start_date_str} to {end_date_str}", |
|
"analysis": {"summary": f"No emails found from '{sender_keyword}' in the last {days_back} days.", "insights": []}, |
|
"email_count": 0 |
|
} |
|
return json.dumps(result, indent=2) |
|
|
|
|
|
analysis = analyze_emails(full_emails) |
|
|
|
result = { |
|
"sender_keyword": sender_keyword, |
|
"date_range": f"{start_date_str} to {end_date_str}", |
|
"analysis": analysis, |
|
"email_count": len(full_emails) |
|
} |
|
|
|
return json.dumps(result, indent=2) |
|
|
|
except Exception as e: |
|
logger.error("Error in analyze_email_patterns: %s", e) |
|
error_result = { |
|
"error": str(e), |
|
"sender_keyword": sender_keyword, |
|
"message": "Failed to analyze email patterns." |
|
} |
|
return json.dumps(error_result, indent=2) |
|
|
|
|
|
|
|
search_interface = gr.Interface( |
|
fn=search_emails, |
|
inputs=[ |
|
gr.Textbox(label="Email Address", placeholder="[email protected]"), |
|
gr.Textbox(label="App Password", type="password", placeholder="Your Gmail app password"), |
|
gr.Textbox(label="Query", placeholder="Show me emails from amazon last week") |
|
], |
|
outputs=gr.Textbox(label="Search Results", lines=20), |
|
title="Email Search", |
|
description="Search your emails using natural language queries" |
|
) |
|
|
|
|
|
details_interface = gr.Interface( |
|
fn=get_email_details, |
|
inputs=[ |
|
gr.Textbox(label="Email Address", placeholder="[email protected]"), |
|
gr.Textbox(label="App Password", type="password", placeholder="Your Gmail app password"), |
|
gr.Textbox(label="Message ID", placeholder="Email message ID from search results") |
|
], |
|
outputs=gr.Textbox(label="Email Details", lines=20), |
|
title="Email Details", |
|
description="Get full details of a specific email by message ID" |
|
) |
|
|
|
|
|
analysis_interface = gr.Interface( |
|
fn=analyze_email_patterns, |
|
inputs=[ |
|
gr.Textbox(label="Email Address", placeholder="[email protected]"), |
|
gr.Textbox(label="App Password", type="password", placeholder="Your Gmail app password"), |
|
gr.Textbox(label="Sender Keyword", placeholder="amazon, google, linkedin, etc."), |
|
gr.Textbox(label="Days Back", value="30", placeholder="Number of days to analyze") |
|
], |
|
outputs=gr.Textbox(label="Analysis Results", lines=20), |
|
title="Email Pattern Analysis", |
|
description="Analyze email patterns from a specific sender over time" |
|
) |
|
|
|
|
|
demo = gr.TabbedInterface( |
|
[search_interface, details_interface, analysis_interface], |
|
["Email Search", "Email Details", "Pattern Analysis"], |
|
title="π§ Email Assistant MCP Server" |
|
) |
|
|
|
if __name__ == "__main__": |
|
|
|
import os |
|
os.environ["GRADIO_MCP_SERVER"] = "True" |
|
|
|
|
|
demo.launch(share=False) |
|
|
|
print("\nπ MCP Server is running!") |
|
print("π MCP Endpoint: http://localhost:7860/gradio_api/mcp/sse") |
|
print("π Copy this URL to your Claude Desktop MCP configuration") |