Chore: Switch to a local IMAP server instead of a real email service (#11913)

This commit is contained in:
Trenton H
2026-01-27 11:35:12 -08:00
committed by GitHub
parent d9d83e3045
commit c84f2f04b3
4 changed files with 63 additions and 58 deletions

View File

@@ -75,9 +75,6 @@ jobs:
env:
NLTK_DATA: ${{ env.NLTK_DATA }}
PAPERLESS_CI_TEST: 1
PAPERLESS_MAIL_TEST_HOST: ${{ secrets.TEST_MAIL_HOST }}
PAPERLESS_MAIL_TEST_USER: ${{ secrets.TEST_MAIL_USER }}
PAPERLESS_MAIL_TEST_PASSWD: ${{ secrets.TEST_MAIL_PASSWD }}
run: |
uv run \
--python ${{ steps.setup-python.outputs.python-version }} \

View File

@@ -23,3 +23,14 @@ services:
container_name: tika
network_mode: host
restart: unless-stopped
greenmail:
image: greenmail/standalone:2.1.8
hostname: greenmail
container_name: greenmail
environment:
# Enable only IMAP for now (SMTP available via 3025 if needed later)
GREENMAIL_OPTS: >-
-Dgreenmail.setup.test.imap -Dgreenmail.users=test@localhost:test -Dgreenmail.users.login=test@localhost -Dgreenmail.verbose
ports:
- "3143:3143" # IMAP
restart: unless-stopped

View File

@@ -1,4 +1,3 @@
import os
from collections.abc import Generator
from pathlib import Path
@@ -70,18 +69,21 @@ def mail_parser() -> MailDocumentParser:
@pytest.fixture()
def live_mail_account() -> Generator[MailAccount, None, None]:
try:
account = MailAccount.objects.create(
name="test",
imap_server=os.environ["PAPERLESS_MAIL_TEST_HOST"],
username=os.environ["PAPERLESS_MAIL_TEST_USER"],
password=os.environ["PAPERLESS_MAIL_TEST_PASSWD"],
imap_port=993,
)
yield account
finally:
account.delete()
def greenmail_mail_account(db: None) -> Generator[MailAccount, None, None]:
"""
Create a mail account configured for local Greenmail server.
"""
account = MailAccount.objects.create(
name="Greenmail Test",
imap_server="localhost",
imap_port=3143,
imap_security=MailAccount.ImapSecurity.NONE,
username="test@localhost",
password="test",
character_set="UTF-8",
)
yield account
account.delete()
@pytest.fixture()

View File

@@ -1,6 +1,3 @@
import os
import warnings
import pytest
from paperless_mail.mail import MailAccountHandler
@@ -9,53 +6,51 @@ from paperless_mail.models import MailAccount
from paperless_mail.models import MailRule
# Only run if the environment is setup
# And the environment is not empty (forks, I think)
@pytest.mark.skipif(
"PAPERLESS_MAIL_TEST_HOST" not in os.environ
or not len(os.environ["PAPERLESS_MAIL_TEST_HOST"]),
reason="Live server testing not enabled",
)
@pytest.mark.django_db()
class TestMailLiveServer:
def test_process_non_gmail_server_flag(
@pytest.mark.django_db
class TestMailGreenmail:
"""
Mail tests using local Greenmail server
"""
def test_process_flag(
self,
mail_account_handler: MailAccountHandler,
live_mail_account: MailAccount,
):
greenmail_mail_account: MailAccount,
) -> None:
"""
Test processing mail with FLAG action.
"""
rule = MailRule.objects.create(
name="testrule",
account=greenmail_mail_account,
action=MailRule.MailAction.FLAG,
)
try:
rule1 = MailRule.objects.create(
name="testrule",
account=live_mail_account,
action=MailRule.MailAction.FLAG,
)
mail_account_handler.handle_mail_account(live_mail_account)
rule1.delete()
mail_account_handler.handle_mail_account(greenmail_mail_account)
except MailError as e:
pytest.fail(f"Failure: {e}")
except Exception as e:
warnings.warn(f"Unhandled exception: {e}")
finally:
rule.delete()
def test_process_non_gmail_server_tag(
def test_process_tag(
self,
mail_account_handler: MailAccountHandler,
live_mail_account: MailAccount,
):
greenmail_mail_account: MailAccount,
) -> None:
"""
Test processing mail with TAG action.
"""
rule = MailRule.objects.create(
name="testrule",
account=greenmail_mail_account,
action=MailRule.MailAction.TAG,
action_parameter="TestTag",
)
try:
rule2 = MailRule.objects.create(
name="testrule",
account=live_mail_account,
action=MailRule.MailAction.TAG,
)
mail_account_handler.handle_mail_account(live_mail_account)
rule2.delete()
mail_account_handler.handle_mail_account(greenmail_mail_account)
except MailError as e:
pytest.fail(f"Failure: {e}")
except Exception as e:
warnings.warn(f"Unhandled exception: {e}")
finally:
rule.delete()