"""Bounded synthetic SMTP/mailbox fixture, available only inside a network-none peer.""" import email import email.policy import json import re import socketserver import threading import urllib.parse from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer from pathlib import Path MESSAGES = [] LOCK = threading.Lock() class SMTP(socketserver.StreamRequestHandler): def handle(self): self.connection.settimeout(15) recipient = None sender = False def reply(line): self.wfile.write((line + '\r\n').encode()) self.wfile.flush() reply('220 synthetic fixture') while True: raw = self.rfile.readline(8193) if not raw or len(raw) > 8192: return command = raw.decode(errors='replace').strip() upper = command.upper() if upper.startswith(('EHLO ', 'HELO ')): reply('250 synthetic fixture') elif upper.startswith('MAIL FROM:'): sender = upper == 'MAIL FROM:' reply('250 OK' if sender else '550 fixture sender only') elif upper.startswith('RCPT TO:'): recipient = ('alice@example.test' if upper == 'RCPT TO:' else None) reply('250 OK' if recipient else '550 fixture recipient only') elif upper == 'DATA' and sender and recipient: reply('354 End with dot') lines, size = [], 0 while True: line = self.rfile.readline(65537) if not line or len(line) > 65536: return if line == b'.\r\n': break size += len(line) if size > 65536: reply('552 fixture message too large') return lines.append(line[1:] if line.startswith(b'..') else line) message = email.message_from_bytes(b''.join(lines), policy=email.policy.default) body = message.get_body(preferencelist=('plain', 'html')) text = body.get_content() if body else message.get_content() links = re.findall(r'https://auth\.recovery\.test:9091/' r'reset-password/step2\?token=[A-Za-z0-9_.-]+', str(text)) with LOCK: if len(MESSAGES) >= 20: reply('452 fixture mailbox full') return MESSAGES.append({'number': len(MESSAGES) + 1, 'recipient': recipient, 'reset_links': list(dict.fromkeys(links))}) recipient, sender = None, False reply('250 fixture accepted') elif upper in {'RSET', 'NOOP'}: recipient, sender = None, False reply('250 OK') elif upper == 'QUIT': reply('221 bye') return else: reply('502 fixture command refused') class SMTPServer(socketserver.ThreadingTCPServer): daemon_threads = True allow_reuse_address = True class Mailbox(BaseHTTPRequestHandler): def log_message(self, *args): pass def do_GET(self): # noqa: N802 if urllib.parse.urlsplit(self.path).path == '/client-callback': body = b'{"status":"synthetic_callback_receiver"}' self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(body))) self.send_header('Cache-Control', 'no-store') self.end_headers() self.wfile.write(body) return if self.path not in {'/health', '/messages'}: self.send_error(404) return with LOCK: body = json.dumps({'messages': MESSAGES} if self.path == '/messages' else {'status': 'fixture-ready'}).encode() self.send_response(200) self.send_header('Content-Type', 'application/json') self.send_header('Content-Length', str(len(body))) self.send_header('Cache-Control', 'no-store') self.end_headers() self.wfile.write(body) if __name__ == '__main__': if not __debug__ or {p.name for p in Path('/sys/class/net').iterdir()} != {'lo'}: raise SystemExit('Fixture loopback boundary required') with SMTPServer(('127.0.0.1', 2525), SMTP) as smtp: thread = threading.Thread(target=smtp.serve_forever, daemon=True) thread.start() ThreadingHTTPServer(('127.0.0.1', 8088), Mailbox).serve_forever()