import pytest import os import tempfile from email.mime.text import MIMEText import sys import types import getpass import time import glob sys.path.insert(0, os.path.abspath(os.path.join(os.path.dirname(__file__), '..'))) from slic.utils.sendmail import * def test_sendmail_local_delivery(): # Get the current system user user = getpass.getuser() # Define the recipient and email content from_addr = f"{user}@localhost" to_addr = f"{user}@localhost" subject = "Local sendmail test" body = "Hello from pytest/local!" # Send the email using the function under test msg = sendmail(to_addr, from_addr=f"{user}@localhost", subject=subject, body=body) # Path to the Maildir 'new' folder for this user maildir_new = os.path.expanduser("~/Maildir/new") # Clean up the mail for f in glob.glob(os.path.join(maildir_new, "*")): os.remove(f) # Wait a short time for delivery files = [] for _ in range(50): # Try for ~5 seconds time.sleep(0.1) files = sorted(glob.glob(os.path.join(maildir_new, "*"))) if files: break # Assert that at least one mail file was delivered assert files, f"No email was delivered to {maildir_new}" # Read the most recent mail file with open(files[-1], "r", encoding="utf-8", errors="replace") as f: content = f.read() # Assert that both the subject and body appear in the delivered email assert subject in content, "Email subject not found in delivered message" assert body in content, "Email body not found in delivered message" repr_str = repr(msg) assert isinstance(repr_str, str), "__repr__() must return str" assert f"To: {to_addr}" in repr_str, "To header missing from __repr__()" assert f"From: {from_addr}" in repr_str, "From header missing from __repr__()" assert f"Subject: {subject}" in repr_str, "Subject header missing from __repr__()" assert body in repr_str, "Body missing from __repr__()" def test_sendmail_raises_on_sendmail_failure(monkeypatch): # Fake CompletedProcess-like object with a failing return code class FakeResult: def __init__(self): self.returncode = 75 # any non-zero is fine self.stderr = b"User unknown or local delivery failed" def check_returncode(self): import subprocess raise subprocess.CalledProcessError(self.returncode, "sendmail", stderr=self.stderr) # Monkeypatch subprocess.run so no real sendmail is called import subprocess monkeypatch.setattr(subprocess, "run", lambda *a, **kw: FakeResult()) # Trigger the failure path to_addr = "nonexistent@localhost" subject = "Should fail" body = "This is supposed to fail" with pytest.raises(SendMailError) as excinfo: sendmail(to_addr, from_addr="tester@localhost", subject=subject, body=body) err = excinfo.value # Check structured attributes provided by your exception class assert err.err_code == 75 assert "User unknown" in err.err_msg # The stringified exception should include the divider and the full message s = str(err) assert OUTPUT_DIVIDER in s assert OUTPUT_DIVIDER_BAR in s assert f"Subject: {subject}" in s assert f"To: {to_addr}" in s assert body in s