diff --git a/google/gmail/helpers.py b/google/gmail/helpers.py index 2abb4cb84..9b9a52c60 100644 --- a/google/gmail/helpers.py +++ b/google/gmail/helpers.py @@ -1,7 +1,10 @@ import base64 import os +import re import gptscript from filetype import guess_mime +from datetime import datetime, timezone, timedelta +from zoneinfo import ZoneInfo from email.mime.text import MIMEText from email.mime.multipart import MIMEMultipart from email.mime.base import MIMEBase @@ -104,6 +107,7 @@ def client(service_name: str, version: str): async def list_messages(service, query, max_results): all_messages = [] next_page_token = None + query = format_query_dates(service, query) try: while True: if next_page_token: @@ -357,7 +361,7 @@ def format_reply_gmail_style(original_from, original_date, original_body_html): if original_body_html is None: original_body_html = "" - + # Format date as "Mon, Mar 18, 2024 at 10:30 AM" formatted_date = original_date try: @@ -373,3 +377,61 @@ def format_reply_gmail_style(original_from, original_date, original_body_html): reply_html = f'

On {formatted_date}, {original_from} wrote:
{quoted_body_html}' return reply_html + +def format_query_dates(service, query): + """ + Converts date strings in Gmail search queries to Unix timestamps for correct timezone handling. + - before: uses beginning of day (00:00:00) + - after: uses end of day (23:59:59) + """ + if not query: + return query + + # Get user's timezone + user_tz_str = get_user_timezone(service) + + # Use UTC if timezone is invalid + try: + user_tz = ZoneInfo(user_tz_str) + except: + user_tz = timezone.utc + + def replace_date(match): + operator, quote1, date_str, quote2 = match.groups() + date_str = date_str.replace('/', '-') + + try: + # Parse date parts + year, month, day = map(int, date_str.split('-')) + + if operator == "before": + # For 'before:', use beginning of day (00:00:00) + dt = datetime(year, month, day, 0, 0, 0, tzinfo=user_tz) + else: # after + # For 'after:', use end of day (23:59:59) + dt = datetime(year, month, day, 23, 59, 59, tzinfo=user_tz) + + timestamp = int(dt.timestamp()) + return f"{operator}:{quote1}{timestamp}{quote2}" + except: + return match.group(0) + + # Replace dates with timestamps + pattern = r'(before|after):(["\']?)(\d{4}[-/]\d{1,2}[-/]\d{1,2})(["\']?)' + return re.sub(pattern, replace_date, query) + + +def get_obot_user_timezone(): + return os.getenv("OBOT_USER_TIMEZONE", "UTC").strip() + +def get_user_timezone(service): + """Fetches the authenticated user's time zone from User's Gmail settings.""" + try: + settings = service.settings().get(setting="timezone").execute() + return settings.get("value", get_obot_user_timezone()) # Default to Obot's user timezone if not found + except HttpError as err: + if err.status_code == 403: + raise Exception(f"HttpError retrieving user timezone: {err}") + return "UTC" + except Exception as e: + return "UTC"