From df64aece2c19215cf762b2ac62d476888cd21527 Mon Sep 17 00:00:00 2001 From: "google-labs-jules[bot]" <161369871+google-labs-jules[bot]@users.noreply.github.com> Date: Mon, 16 Mar 2026 09:05:02 +0000 Subject: [PATCH] feat: Extract embedded PDF metadata using pypdf in upload_to_email Co-authored-by: christianlouis <361235+christianlouis@users.noreply.github.com> --- app/tasks/upload_to_email.py | 19 +++++++++++++++++-- tests/test_upload_email.py | 26 ++++++++++++++++++++++++++ 2 files changed, 43 insertions(+), 2 deletions(-) diff --git a/app/tasks/upload_to_email.py b/app/tasks/upload_to_email.py index 8b9c8220..c68e4bf7 100644 --- a/app/tasks/upload_to_email.py +++ b/app/tasks/upload_to_email.py @@ -11,6 +11,7 @@ from email.mime.image import MIMEImage from email.mime.multipart import MIMEMultipart from email.mime.text import MIMEText +import pypdf from jinja2 import Environment, FileSystemLoader, select_autoescape from app.celery_app import celery @@ -80,8 +81,22 @@ def extract_metadata_from_file(file_path): 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 + # Try to extract embedded metadata from PDF + if file_path.lower().endswith(".pdf") and os.path.exists(file_path): + try: + with open(file_path, "rb") as f: + pdf_reader = pypdf.PdfReader(f) + pdf_metadata = pdf_reader.metadata + if pdf_metadata: + # Convert metadata to a standard dictionary + for key, value in pdf_metadata.items(): + # Remove the leading slash from PDF metadata keys (e.g., '/Title' -> 'Title') + clean_key = key[1:] if key.startswith("/") else key + metadata[clean_key] = str(value) + + logger.info(f"Extracted embedded metadata from PDF: {file_path}") + except Exception as e: + logger.warning(f"Failed to extract metadata from PDF {file_path}: {str(e)}") return metadata diff --git a/tests/test_upload_email.py b/tests/test_upload_email.py index c92893a6..72be0587 100644 --- a/tests/test_upload_email.py +++ b/tests/test_upload_email.py @@ -121,6 +121,32 @@ class TestExtractMetadataFromFile: assert result == {} + def test_extract_metadata_from_pdf(self, tmp_path): + """Test extracting metadata from a PDF file using pypdf when JSON is missing.""" + import pypdf + + file_path = tmp_path / "test.pdf" + + # Create a test PDF with metadata + writer = pypdf.PdfWriter() + writer.add_blank_page(width=100, height=100) + writer.add_metadata({ + "/Title": "Test Title", + "/Author": "Test Author", + "/Subject": "Test Document", + "/Keywords": "test, metadata, pypdf" + }) + with open(file_path, "wb") as f: + writer.write(f) + + result = extract_metadata_from_file(str(file_path)) + + # Check that the leading slash is stripped and keys/values match + assert result.get("Title") == "Test Title" + assert result.get("Author") == "Test Author" + assert result.get("Subject") == "Test Document" + assert result.get("Keywords") == "test, metadata, pypdf" + @pytest.mark.unit class TestAttachLogo: