"""mailu — recipe-specific functional test #3 (Phase 2 P3, the characteristic end-to-end mail flow). Provision a mailbox, SEND a uniquely-marked message to it over SMTP, then RETRIEVE it over IMAP and assert the marker arrived. This is mailu's defining behaviour (it is a mail server): a full deliver→store→fetch round-trip across postfix + rspamd + dovecot — not an API/health stand-in. To avoid rspamd greylisting (which defers an unknown inbound sender's first attempt for minutes), we send via AUTHENTICATED submission as the user itself (authenticated mail is not greylisted). notls deploy → submission accepts AUTH on 587; we try 587 (STARTTLS-if-offered) then fall back to 25. Retrieval polls INBOX (and Junk, in case rspamd files it) for the marker. """ from __future__ import annotations import email.message import imaplib import os import smtplib import sys import time import uuid sys.path.insert(0, os.path.dirname(__file__)) import _mailu # noqa: E402 def _send(addr_from: str, addr_to: str, password: str, marker: str) -> None: msg = email.message.EmailMessage() msg["From"] = addr_from msg["To"] = addr_to msg["Subject"] = marker msg.set_content(f"cc-ci mail-flow test body {marker}") last = None # Authenticated submission on 587 (no greylist); fall back to plain 25 local delivery. for port in (587, 25): try: smtp = smtplib.SMTP("127.0.0.1", port, timeout=30) try: smtp.ehlo() if smtp.has_extn("starttls"): smtp.starttls() smtp.ehlo() if smtp.has_extn("auth"): try: smtp.login(addr_from, password) except smtplib.SMTPException as e: # noqa: PERF203 last = e # 25 may not offer/allow AUTH; local delivery still works smtp.send_message(msg) return finally: try: smtp.quit() except Exception: # noqa: BLE001 pass except (smtplib.SMTPException, OSError) as e: last = e raise AssertionError(f"could not send mail via SMTP 587/25: {last}") def _retrieve(email_addr: str, password: str, marker: str, timeout: int = 150) -> bool: deadline = time.time() + timeout while time.time() < deadline: try: imap = imaplib.IMAP4("127.0.0.1", 143) try: imap.login(email_addr, password) for box in ("INBOX", "Junk"): typ, _ = imap.select(box) if typ != "OK": continue typ, data = imap.search(None, "SUBJECT", f'"{marker}"') if typ == "OK" and data and data[0].split(): return True imap.logout() finally: try: imap.shutdown() except Exception: # noqa: BLE001 pass except (imaplib.IMAP4.error, OSError): # noqa: PERF203 pass time.sleep(5) return False def test_send_and_receive_mail(live_app): mail_domain = live_app local = "ccci-flow-" + uuid.uuid4().hex[:8] password = "CcCi-" + uuid.uuid4().hex[:16] + "-Aa1!" _mailu.ensure_domain(live_app, mail_domain) email_addr = _mailu.create_user(live_app, local, mail_domain, password) marker = "ccci-mailflow-" + uuid.uuid4().hex _send(email_addr, email_addr, password, marker) assert _retrieve(email_addr, password, marker), ( f"mail with marker {marker!r} was sent to {email_addr} but never arrived in INBOX/Junk " f"over IMAP within the delivery window (postfix→rspamd→dovecot)" )