Download tests/test_smtp_client.py from sitcod3/modul-x: direct link, hf CLI and curl.
- Browser
- Download file 4.92 kB
-
https://huggingface.co/spaces/sitcod3/modul-x/resolve/main/tests/test_smtp_client.py
- Command line
-
hf download hf://spaces/sitcod3/modul-x/tests/test_smtp_client.py
-
curl -L -o test_smtp_client.py https://huggingface.co/spaces/sitcod3/modul-x/resolve/main/tests/test_smtp_client.py
4.92 kB
| import unittest | |
| from app.validator.smtp_client import SmtpConnection, RcptOutcome | |
| class FakeSock: | |
| """Scripted TCP socket: returns queued byte chunks on recv, records sends.""" | |
| def __init__(self, chunks): | |
| self.chunks = list(chunks) | |
| self.sent: list[str] = [] | |
| self.closed = False | |
| self.timeout = None | |
| def settimeout(self, t): | |
| self.timeout = t | |
| def sendall(self, data: bytes): | |
| self.sent.append(data.decode("utf-8", "replace")) | |
| def recv(self, _n: int) -> bytes: | |
| return self.chunks.pop(0) if self.chunks else b"" | |
| def close(self): | |
| self.closed = True | |
| def make_conn(chunks, **kw): | |
| sock = FakeSock(chunks) | |
| conn = SmtpConnection( | |
| "mx.example.test", | |
| timeout=5, | |
| helo_domain="validator.test", | |
| connect=lambda *a, **k: sock, | |
| **kw, | |
| ) | |
| return conn, sock | |
| BANNER = b"220 mx.example.test ESMTP ready\r\n" | |
| EHLO_OK = b"250-mx.example.test\r\n250-PIPELINING\r\n250 OK\r\n" | |
| class SmtpConnectionTests(unittest.TestCase): | |
| def test_handshake_reads_banner_and_sends_ehlo(self): | |
| conn, sock = make_conn([BANNER, EHLO_OK, b"250 OK\r\n"]) | |
| conn.open() | |
| self.assertTrue(conn.ready) | |
| self.assertTrue(any(c.startswith("EHLO ") for c in sock.sent)) | |
| self.assertIn("validator.test", "".join(sock.sent)) | |
| def test_multiline_ehlo_is_parsed_as_single_response(self): | |
| conn, _ = make_conn([BANNER, EHLO_OK]) | |
| conn.open() | |
| self.assertEqual(conn.server_code, 250) | |
| def test_accepting_rcpt_returns_250(self): | |
| conn, sock = make_conn( | |
| [BANNER, EHLO_OK, b"250 OK\r\n", b"250 2.1.5 Ok\r\n", b"250 OK\r\n"] | |
| ) | |
| conn.open() | |
| out = conn.probe("real@example.test") | |
| self.assertEqual(out.code, 250) | |
| self.assertTrue(out.accepted) | |
| self.assertFalse(out.transport_error) | |
| self.assertTrue(any(c.startswith("RCPT TO:") for c in sock.sent)) | |
| def test_rejecting_rcpt_returns_550(self): | |
| conn, _ = make_conn( | |
| [ | |
| BANNER, | |
| EHLO_OK, | |
| b"250 OK\r\n", | |
| b"550 5.1.1 The email account that you tried to reach does not exist\r\n", | |
| b"250 OK\r\n", | |
| ] | |
| ) | |
| conn.open() | |
| out = conn.probe("ghost@example.test") | |
| self.assertEqual(out.code, 550) | |
| self.assertFalse(out.accepted) | |
| self.assertIn("does not exist", out.message) | |
| def test_multiple_probes_reuse_one_connection(self): | |
| # The whole point of the engine: one TCP session, many RCPT probes. | |
| conn, sock = make_conn( | |
| [ | |
| BANNER, | |
| EHLO_OK, | |
| b"250 OK\r\n", # MAIL FROM #1 | |
| b"250 OK\r\n", # RCPT #1 | |
| b"250 OK\r\n", # RSET | |
| b"250 OK\r\n", # MAIL FROM #2 | |
| b"550 5.1.1 nope\r\n", # RCPT #2 | |
| b"250 OK\r\n", # RSET | |
| b"221 Bye\r\n", | |
| ] | |
| ) | |
| conn.open() | |
| first = conn.probe("a@example.test") | |
| second = conn.probe("b@example.test") | |
| conn.quit() | |
| self.assertTrue(first.accepted) | |
| self.assertFalse(second.accepted) | |
| # Two MAIL FROM commands, one EHLO, one connection. | |
| sends = "".join(sock.sent) | |
| self.assertEqual(sends.count("MAIL FROM:"), 2) | |
| self.assertEqual(sends.count("EHLO "), 1) | |
| self.assertEqual(sends.count("RSET"), 2) | |
| self.assertTrue(sock.closed) | |
| def test_transport_failure_is_reported_not_raised(self): | |
| conn, _ = make_conn([BANNER, EHLO_OK]) | |
| conn.open() | |
| conn._sock.chunks = [] # server dies mid-session | |
| out = conn.probe("a@example.test") | |
| self.assertTrue(out.transport_error) | |
| self.assertIsNone(out.code) | |
| self.assertTrue(out.retryable) | |
| def test_unexpected_banner_is_not_ready(self): | |
| conn, _ = make_conn([b"554 Service unavailable\r\n"]) | |
| conn.open() | |
| self.assertFalse(conn.ready) | |
| def test_greylist_code_marked_retryable(self): | |
| conn, _ = make_conn( | |
| [BANNER, EHLO_OK, b"250 OK\r\n", b"451 4.7.1 Greylisted, try later\r\n", b"250 OK\r\n"] | |
| ) | |
| conn.open() | |
| out = conn.probe("a@example.test") | |
| self.assertEqual(out.code, 451) | |
| self.assertTrue(out.retryable) | |
| self.assertFalse(out.permanent_reject) | |
| class RcptOutcomeTests(unittest.TestCase): | |
| def test_flags_for_5xx(self): | |
| o = RcptOutcome(code=550, message="550 no such user") | |
| self.assertTrue(o.permanent_reject) | |
| self.assertFalse(o.retryable) | |
| def test_flags_for_accept(self): | |
| o = RcptOutcome(code=250, message="250 OK") | |
| self.assertTrue(o.accepted) | |
| self.assertFalse(o.retryable) | |
| self.assertFalse(o.permanent_reject) | |
| if __name__ == "__main__": | |
| unittest.main() |