From 30d24c96f2d1b4f03616106ebd8748cc5ce43be8 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 26 Mar 2026 13:00:57 +0000 Subject: [PATCH] Fix offset-naive/offset-aware datetime subtraction in process_mail_account Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/pop_puller_to_gmail/sessions/ff7ce94c-aeb6-4577-a87c-77fcdcb414f7 --- CHANGELOG.md | 3 +++ backend/app/workers/tasks.py | 13 +++++++++++-- 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 766c7e3..6754953 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0 ## [Unreleased] +### Fixed +- Fixed `TypeError: can't subtract offset-naive and offset-aware datetimes` in `process_mail_account` task when computing `duration_seconds`. After a database refresh, `started_at` may be returned as a naive datetime; it is now normalized to UTC before subtraction. + ### Security - Upgraded `python-jose` from 3.3.0 to 3.5.0 to fix CVE: algorithm confusion vulnerability with OpenSSH ECDSA keys (affected versions < 3.4.0). - Upgraded `python-jose[cryptography]` from `3.3.0` to `3.4.0` to fix an algorithm-confusion vulnerability with OpenSSH ECDSA keys (CVE affects all versions < 3.4.0). diff --git a/backend/app/workers/tasks.py b/backend/app/workers/tasks.py index 64b431b..72e6a24 100644 --- a/backend/app/workers/tasks.py +++ b/backend/app/workers/tasks.py @@ -29,6 +29,13 @@ from sqlalchemy import select, delete logger = logging.getLogger(__name__) +def _as_utc(dt: datetime) -> datetime: + """Return *dt* with UTC tzinfo, attaching it if the datetime is naive.""" + if dt.tzinfo is None: + return dt.replace(tzinfo=timezone.utc) + return dt + + class AsyncTask(Task): """Base task class that handles async operations""" @@ -249,7 +256,9 @@ async def process_mail_account(account_id: int): run.emails_forwarded = emails_forwarded # type: ignore[assignment] run.emails_failed = emails_failed # type: ignore[assignment] run.completed_at = datetime.now(timezone.utc) # type: ignore[assignment] - run.duration_seconds = (run.completed_at - run.started_at).total_seconds() + run.duration_seconds = ( + run.completed_at - _as_utc(run.started_at) + ).total_seconds() run.status = "completed" if emails_failed == 0 else "partial_failure" # type: ignore[assignment] # Update account @@ -281,7 +290,7 @@ async def process_mail_account(account_id: int): run.error_message = str(e) # type: ignore[assignment] run.completed_at = datetime.now(timezone.utc) # type: ignore[assignment] run.duration_seconds = ( - run.completed_at - run.started_at + run.completed_at - _as_utc(run.started_at) ).total_seconds() # Update account error status