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.