style: fix all flake8 linter errors across app/ directory

- Run Black formatter and isort on all app/ files
- Remove unused imports (F401) across multiple files
- Add # noqa: F401 for intentional re-exports in celery_worker.py,
  tasks/__init__.py, utils.py, frontend.py, views/base.py
- Fix f-strings without placeholders (F541) in azure.py, notification.py,
  check_credentials.py, upload_to_onedrive.py, settings.py
- Fix bare except (E722) in upload_to_sftp.py
- Fix block comment format (E265) in models.py
- Move imports to top of file to fix E402 in celery_app.py, celery_worker.py
- Fix line-too-long (E501) by wrapping strings in multiple files
- Remove unused variable (F841) in upload_to_nextcloud.py

Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com>
This commit is contained in:
copilot-swe-agent[bot]
2026-02-08 17:42:33 +00:00
parent 7827b97e06
commit d08040ac4a
73 changed files with 2200 additions and 2185 deletions
+69 -55
View File
@@ -1,24 +1,26 @@
#!/usr/bin/env python3
import os
import json
import logging
import os
import smtplib
import socket
import logging
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from datetime import datetime
from email.mime.application import MIMEApplication
from email.mime.image import MIMEImage
from datetime import datetime
from pathlib import Path
from email.mime.multipart import MIMEMultipart
from email.mime.text import MIMEText
from jinja2 import Environment, FileSystemLoader, select_autoescape
from app.celery_app import celery
from app.config import settings
from app.tasks.retry_config import BaseTaskWithRetry
from app.celery_app import celery
from app.utils import log_task_progress
logger = logging.getLogger(__name__)
def get_email_template(template_name="default.html"):
"""
Load email template from one of these locations in order of precedence:
@@ -30,26 +32,22 @@ def get_email_template(template_name="default.html"):
workdir_template_path = os.path.join(settings.workdir, "templates", "email")
if os.path.exists(workdir_template_path):
env = Environment(
loader=FileSystemLoader(workdir_template_path),
autoescape=select_autoescape(['html', 'xml'])
loader=FileSystemLoader(workdir_template_path), autoescape=select_autoescape(["html", "xml"])
)
env.globals['now'] = datetime.now # Add the now function to the Jinja environment
env.globals["now"] = datetime.now # Add the now function to the Jinja environment
template = env.get_template(template_name)
logger.info(f"Using custom email template from workdir: {template_name}")
return template
except Exception as e:
logger.warning(f"Failed to load custom email template: {str(e)}")
# Fallback to built-in template
try:
# Get the app directory path (where this file is)
current_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
app_template_path = os.path.join(current_dir, "templates", "email")
env = Environment(
loader=FileSystemLoader(app_template_path),
autoescape=select_autoescape(['html', 'xml'])
)
env.globals['now'] = datetime.now # Add the now function to the Jinja environment
env = Environment(loader=FileSystemLoader(app_template_path), autoescape=select_autoescape(["html", "xml"]))
env.globals["now"] = datetime.now # Add the now function to the Jinja environment
template = env.get_template(template_name)
logger.info(f"Using built-in email template: {template_name}")
return template
@@ -57,32 +55,34 @@ def get_email_template(template_name="default.html"):
logger.error(f"Failed to load built-in email template: {str(e)}")
raise ValueError(f"Could not find any valid email template: {str(e)}")
def extract_metadata_from_file(file_path):
"""
Try to extract metadata from a file using several methods:
1. Check for a .json metadata file with the same name
2. Extract metadata from PDF if it's embedded
Returns a dictionary of metadata or None if not found
"""
metadata = {}
# Check for separate metadata JSON file
metadata_path = os.path.splitext(file_path)[0] + '.json'
metadata_path = os.path.splitext(file_path)[0] + ".json"
if os.path.exists(metadata_path):
try:
with open(metadata_path, 'r', encoding='utf-8') as f:
with open(metadata_path, "r", encoding="utf-8") as f:
metadata = json.load(f)
logger.info(f"Loaded metadata from external JSON file: {metadata_path}")
return metadata
except Exception as e:
logger.warning(f"Failed to load metadata from JSON file: {str(e)}")
# TODO: For PDF files, try to extract embedded metadata using PyPDF2
# This would require additional dependencies, so for now we'll just check for external JSON
return metadata
def attach_logo(msg):
"""Attach the DocuElevate logo to the email with proper Content-ID."""
try:
@@ -97,27 +97,28 @@ def attach_logo(msg):
# Fallback to logo in frontend/static if app/static doesn't exist
if not os.path.exists(logo_path):
logo_path = os.path.join(app_dir, "..", "frontend", "static", "logo.png")
if os.path.exists(logo_path):
with open(logo_path, 'rb') as img:
with open(logo_path, "rb") as img:
logo_data = img.read()
# Determine image MIME type based on extension
mimetype = 'image/svg+xml' if logo_path.endswith('.svg') else 'image/png'
mimetype = "image/svg+xml" if logo_path.endswith(".svg") else "image/png"
logo_attach = MIMEImage(logo_data, mimetype)
logo_attach.add_header('Content-ID', '<logo>')
logo_attach.add_header('Content-Disposition', 'inline', filename='logo.png')
logo_attach.add_header("Content-ID", "<logo>")
logo_attach.add_header("Content-Disposition", "inline", filename="logo.png")
msg.attach(logo_attach)
logger.info(f"Logo attached from {logo_path}")
return True
else:
logger.warning("Could not find logo file")
return False
except Exception as e:
logger.warning(f"Error attaching logo: {str(e)}")
return False
def _prepare_recipients(recipients):
"""Helper function to prepare email recipients list."""
if not recipients:
@@ -130,22 +131,23 @@ def _prepare_recipients(recipients):
return [recipients], None # Convert single email to list
return recipients, None
def _send_email_with_smtp(msg, filename, recipients):
"""Helper function to handle SMTP connection and sending."""
try:
# First try to resolve the hostname
socket.gethostbyname(settings.email_host)
# Connect to the SMTP server
with smtplib.SMTP(settings.email_host, settings.email_port, timeout=30) as server:
# Use TLS if specified
if settings.email_use_tls:
server.starttls()
# Login if credentials are provided
if settings.email_username and settings.email_password:
server.login(settings.email_username, settings.email_password)
# Send the email
server.send_message(msg)
@@ -160,12 +162,22 @@ def _send_email_with_smtp(msg, filename, recipients):
logger.error(error_msg)
return {"status": "Failed", "reason": error_msg, "error": str(e)}
@celery.task(base=BaseTaskWithRetry, bind=True)
def upload_to_email(self, file_path: str, recipients=None, subject=None, message=None, template_name="default.html", include_metadata=True, file_id: int = None):
def upload_to_email(
self,
file_path: str,
recipients=None,
subject=None,
message=None,
template_name="default.html",
include_metadata=True,
file_id: int = None,
):
"""
Sends a file via email to the specified recipients.
If recipients is None, uses the configured default email recipient.
Args:
file_path: Path to the file to send
recipients: Optional list of recipient email addresses
@@ -180,7 +192,7 @@ def upload_to_email(self, file_path: str, recipients=None, subject=None, message
log_task_progress(
task_id, "upload_to_email", "in_progress", f"Sending via email: {os.path.basename(file_path)}", file_id=file_id
)
if not os.path.exists(file_path):
error_msg = f"File not found: {file_path}"
logger.error(f"[{task_id}] {error_msg}")
@@ -189,17 +201,19 @@ def upload_to_email(self, file_path: str, recipients=None, subject=None, message
# Extract filename
filename = os.path.basename(file_path)
# Check if email settings are configured
if not settings.email_host:
error_msg = "Email host is not configured"
logger.error(f"[{task_id}] {error_msg}")
log_task_progress(task_id, "upload_to_email", "skipped", error_msg, file_id=file_id)
return {"status": "Skipped", "reason": error_msg}
# Log email configuration for debugging
logger.debug(f"[{task_id}] Email config - Host: {settings.email_host}, Port: {settings.email_port}, "
f"Username: {settings.email_username}, TLS: {settings.email_use_tls}")
logger.debug(
f"[{task_id}] Email config - Host: {settings.email_host}, Port: {settings.email_port}, "
f"Username: {settings.email_username}, TLS: {settings.email_use_tls}"
)
# Process recipients
recipients, error = _prepare_recipients(recipients)
@@ -218,21 +232,21 @@ def upload_to_email(self, file_path: str, recipients=None, subject=None, message
try:
# Create the email
msg = MIMEMultipart('related')
msg['From'] = settings.email_sender or settings.email_username
msg['To'] = ", ".join(recipients)
msg['Subject'] = subject
msg = MIMEMultipart("related")
msg["From"] = settings.email_sender or settings.email_username
msg["To"] = ", ".join(recipients)
msg["Subject"] = subject
# Create alternative part for HTML content
alt_part = MIMEMultipart('alternative')
alt_part = MIMEMultipart("alternative")
msg.attach(alt_part)
# Attach logo to the email
has_logo = attach_logo(msg)
# Load and render template
template = get_email_template(template_name)
# Context data for the template
context = {
"filename": filename,
@@ -243,38 +257,38 @@ def upload_to_email(self, file_path: str, recipients=None, subject=None, message
"metadata": metadata,
"has_metadata": bool(metadata),
"has_logo": has_logo,
"current_year": datetime.now().year
"current_year": datetime.now().year,
}
# Render HTML body
html_content = template.render(**context)
alt_part.attach(MIMEText(html_content, 'html'))
alt_part.attach(MIMEText(html_content, "html"))
# Attach the file
with open(file_path, "rb") as file:
attachment = MIMEApplication(file.read(), _subtype="pdf")
attachment.add_header('Content-Disposition', f'attachment; filename="{filename}"')
attachment.add_header("Content-Disposition", f'attachment; filename="{filename}"')
msg.attach(attachment)
# Send the email through SMTP
error_result = _send_email_with_smtp(msg, filename, recipients)
if error_result:
logger.error(f"[{task_id}] Failed to send email: {error_result.get('reason')}")
log_task_progress(task_id, "upload_to_email", "failure", error_result.get('reason'), file_id=file_id)
log_task_progress(task_id, "upload_to_email", "failure", error_result.get("reason"), file_id=file_id)
return error_result
logger.info(f"[{task_id}] Successfully sent {filename} via email to {len(recipients)} recipients")
log_task_progress(task_id, "upload_to_email", "success", f"Sent via email: {filename}", file_id=file_id)
return {
"status": "Completed",
"file": file_path,
"recipients": recipients,
"subject": subject,
"metadata_included": bool(metadata),
"logo_included": has_logo
"logo_included": has_logo,
}
except Exception as e:
error_msg = f"Failed to send {filename} via email: {str(e)}"
logger.error(f"[{task_id}] {error_msg}")