From 681e0582f66b59693bbdc7ba8bbd82fa6367b6a2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sun, 22 Mar 2026 19:05:41 +0000 Subject: [PATCH] Address code review: fix imports, salt hashing, conditional delivery message - Move asyncio import to module level in gmail_service.py - Move datetime import to module level in providers.py - Use hashlib.sha256 for per-user salt generation (no truncation risk) - Make delivery method message conditional in AddMailAccountModal Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> Agent-Logs-Url: https://github.com/christianlouis/pop_puller_to_gmail/sessions/de3ef930-a980-4958-8a9d-a2c802918e81 --- backend/app/api/v1/endpoints/providers.py | 3 +-- backend/app/core/security.py | 6 +++--- backend/app/services/gmail_service.py | 7 +------ frontend/src/components/AddMailAccountModal.tsx | 9 +++++---- 4 files changed, 10 insertions(+), 15 deletions(-) diff --git a/backend/app/api/v1/endpoints/providers.py b/backend/app/api/v1/endpoints/providers.py index b96bb08..bd4c43c 100644 --- a/backend/app/api/v1/endpoints/providers.py +++ b/backend/app/api/v1/endpoints/providers.py @@ -1,4 +1,5 @@ """Provider presets and Gmail credential management endpoints""" +from datetime import datetime from typing import List from fastapi import APIRouter, Depends, HTTPException, status from sqlalchemy.ext.asyncio import AsyncSession @@ -197,14 +198,12 @@ async def save_gmail_credential( existing.encrypted_access_token = encrypted_access existing.encrypted_refresh_token = encrypted_refresh existing.is_valid = True - from datetime import datetime existing.last_verified_at = datetime.utcnow() await db.commit() await db.refresh(existing) return existing else: # Create new - from datetime import datetime credential = GmailCredential( user_id=current_user.id, gmail_email=credential_in.gmail_email, diff --git a/backend/app/core/security.py b/backend/app/core/security.py index 825fd28..d40564e 100644 --- a/backend/app/core/security.py +++ b/backend/app/core/security.py @@ -1,6 +1,7 @@ """ Security utilities for encryption, hashing, and token generation. """ +import hashlib import secrets from datetime import datetime, timedelta from typing import Optional, Dict, Any @@ -81,10 +82,9 @@ class CredentialEncryption: if key is None: key = settings.ENCRYPTION_KEY - # Generate salt - in production, this should be unique per user + # Generate salt - unique per user for enhanced security if user_id is not None: - # Per-user salt for production - salt = f'pop3fwd_usr_{user_id}'.encode('utf-8')[:16].ljust(16, b'\x00') + salt = hashlib.sha256(f'pop3fwd_usr_{user_id}'.encode()).digest()[:16] else: # Default salt for system-wide operations (use with caution) salt = b'pop3_forwarder_0' diff --git a/backend/app/services/gmail_service.py b/backend/app/services/gmail_service.py index ef6a85f..8ba0d6f 100644 --- a/backend/app/services/gmail_service.py +++ b/backend/app/services/gmail_service.py @@ -5,6 +5,7 @@ Uses the Gmail API's users.messages.insert() method to inject emails into a user's Gmail account, preserving original headers and metadata. This is preferred over SMTP forwarding as it doesn't modify the email. """ +import asyncio import base64 import logging from typing import Optional, Dict, Any @@ -94,8 +95,6 @@ class GmailService: Raises: GmailInjectionError: If injection fails """ - import asyncio - if label_ids is None: label_ids = ["INBOX"] @@ -145,8 +144,6 @@ class GmailService: Returns: True if credentials are valid and can access Gmail """ - import asyncio - loop = asyncio.get_event_loop() try: @@ -170,8 +167,6 @@ class GmailService: Returns: Email address string or None if unavailable """ - import asyncio - loop = asyncio.get_event_loop() try: diff --git a/frontend/src/components/AddMailAccountModal.tsx b/frontend/src/components/AddMailAccountModal.tsx index 8f4f2f5..cea66d4 100644 --- a/frontend/src/components/AddMailAccountModal.tsx +++ b/frontend/src/components/AddMailAccountModal.tsx @@ -312,10 +312,11 @@ export function AddMailAccountModal({ account, onClose }: AddMailAccountModalPro -
- Gmail API Injection: Emails will be injected directly into your Gmail - account via the Gmail API. Make sure you have configured your Gmail credentials in Settings. +
+ Delivery: Emails will be delivered to your Gmail account. + Configure your Gmail API credentials in Settings for direct injection (recommended), + or they will be forwarded via SMTP.