"""SDK message-read helpers: envelope + raw header access (SPEC ยง11).""" from __future__ import annotations import uuid from datetime import UTC, datetime from email.message import EmailMessage from sqlalchemy import delete from sqlalchemy.ext.asyncio import async_sessionmaker, create_async_engine from sqlalchemy.pool import NullPool from app.config import get_settings from app.identity.passwords import hash_password from app.indexer import blobstore from app.models import Account, Mailbox, Message, User from app.plugins.sdk import sdk async def test_messages_header_reads_raw_header() -> None: engine = create_async_engine(get_settings().database_url, poolclass=NullPool) sm = async_sessionmaker(engine, expire_on_commit=False) async with sm() as s: user = User( handle=f"hd{uuid.uuid4().hex[:8]}@test.local", password_hash=hash_password("pw") ) s.add(user) await s.flush() account = Account( user_id=user.id, email="me@example.com", imap_config={}, smtp_config={}, secret_ct=b"", discovery_src="manual", ) s.add(account) await s.flush() mbox = Mailbox(account_id=account.id, user_id=user.id, path="INBOX", special_use="inbox") s.add(mbox) await s.flush() raw = EmailMessage() raw["Subject"] = "Weekly digest" raw["From"] = "news@list.example" raw["List-Unsubscribe"] = "" raw.set_content("hello") sha = blobstore.store(user.id, raw.as_bytes()) msg = Message( user_id=user.id, account_id=account.id, mailbox_id=mbox.id, uid=1, subject="Weekly digest", flags=[], internal_date=datetime.now(UTC), blob_sha256=sha, ) s.add(msg) await s.commit() user_id, message_id = user.id, msg.id try: messages = sdk("unsubscribe").messages assert await messages.header(user_id, message_id, "List-Unsubscribe") == ( "" ) assert await messages.header(user_id, message_id, "X-Nope") is None assert await messages.header(user_id, uuid.uuid4(), "List-Unsubscribe") is None # Another user can't read this message's headers. assert await messages.header(uuid.uuid4(), message_id, "List-Unsubscribe") is None finally: async with sm() as s: await s.execute(delete(User).where(User.id == user_id)) await s.commit() await engine.dispose()